看来 Ruby 的 OpenSSL EC 支持的文档和实际 API 目前都相当缺乏。特别是,在 Ruby OpenSSL::PKey::EC不遵循与 RSA 和 DSA 密钥相同的 API 进行签名和验证。你想要做的,但目前不能使用 EC 密钥,是这样的(这里的所有代码假设你已经调用require 'openssl'
某处):
# Get the key, here I'm reading the file
priv_key = OpenSSL::PKey.read(File.read('eckey.pem'))
# This should be the appropriately formatted string
data = "some data to sign"
# The hash algorithm, I assume SHA256 is being used
digest = OpenSSL::Digest::SHA256.new
# This doesn't work in 2.3.1, but does in 2.4.0-preview1
signature = priv_key.sign(digest, data)
正如我在评论中指出的,这在 Ruby 2.4.0-preview1 中确实有效,但这对您来说可能没有多大用处。
要让它与当前的 Ruby 一起工作,您需要执行以下操作:
# As before:
priv_key = OpenSSL::PKey.read(File.read('eckey.pem'))
data = "some data to sign"
signature = priv_key.dsa_sign_asn1(OpenSSL::Digest::SHA256.digest(data))
这两种技术都会给你一个二进制字符串。我think在将其添加为请求标头之前,您需要对其进行 Base64 编码。
要提取公钥来检查签名验证也有点棘手(尽管您可以只使用openssl
命令行并读入文件)。这public_key
方法返回一个OpenSSL::PKey::EC::Point
对象而不是实际的密钥,因此我们需要从私钥重新创建一个。这verify
method does在 Ruby 2.3.1 上工作:
pub = OpenSSL::PKey::EC.new(priv_key.group)
pub.public_key = priv_key.public_key
data = "some data to sign"
digest = OpenSSL::Digest::SHA256.new
puts pub.verify(digest, sig, data)
Apple 页面似乎没有指定要使用的哈希算法,但从我所看到的来看,SHA-256 似乎是正确的。 (另外,我可能完全错了,苹果使用了完全不同的格式。我很想知道这段代码是否对你有用)。