看来,Ruby 的 OpenSSL EC 支持的文档和实际 API 目前都相当缺乏。特别是,在 Ruby <= 2.3.1 中,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))
这两种技术都给你一个二进制字符串。我认为您需要在将其添加为请求标头之前对其进行 base64 编码。
提取公钥以检查签名验证也有点棘手(尽管您可以只使用openssl
命令行并读入文件)。这些public_key
方法返回一个OpenSSL::PKey::EC::Point
对象而不是实际密钥,因此我们需要从私钥重新创建一个。该verify
方法确实适用于 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 似乎是正确的。(我也可能完全弄错了,Apple 使用的是完全不同的格式。我很想知道这段代码是否对你有用)。