不确定如何生成 ECDSA 签名,给定私钥和消息

Not sure how to generate an ECDSA signature, given a private key and a message

我正在关注 Apple's guide 编写 CloudKit Web 服务请求。我遇到的问题是第 2 步,在 "Authenticate Web Service Requests":

  1. Compute the ECDSA signature of this message with your private key.

在这之前,我生成了我的证书,一个 .pem 文件,当在文本编辑器中打开它时,它会显示我的私钥,所以我也有字符串格式的。

我还按照生成消息的步骤进行操作,我现在将其作为字符串。

所以假设我有一个私钥(或者 .pem 文件,如果需要的话)和一个字符串形式的消息,理论上我应该相当简单地获得消息的 ECDSA 签名,计算用我的私钥。但这就是我挣扎的地方。 Libraries that I've found online 似乎采用了一种复杂得多的方法,具有不同的移动部件,没有引用 .pem 文件并谈论生成新的 public/private 密钥。

如果您对此步骤有任何帮助,我们将不胜感激。

看来 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 编码,然后再将其添加为您的请求header。

要提取 public 密钥来检查签名验证也有点棘手(尽管您可以只使用 openssl 命令行并读入文件)。 public_key 方法 returns 一个 OpenSSL::PKey::EC::Point object 而不是实际的密钥,因此我们需要从私钥重新创建一个。 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 使用的是完全不同的格式。我很想知道这段代码是否适用于你)。