6

我正在遵循Apple编写 CloudKit Web 服务请求的指南。我遇到的问题是“验证 Web 服务请求”下的第 2 步:

  1. 使用您的私钥计算此消息的 ECDSA 签名。

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

我还遵循了生成它所指的消息的步骤,现在我将其作为字符串。

因此,鉴于我有一个私钥(或 .pem 文件,如果需要)和一个字符串形式的消息,理论上我应该相当简单地获得消息的 ECDSA 签名,用我的私钥计算。但这就是我挣扎的地方。我在网上找到的库似乎采取了一种更为复杂的方法,具有不同的移动部件,没有引用 .pem 文件,并且谈论生成新的公钥/私钥。

对此步骤的任何帮助将不胜感激。

4

1 回答 1

5

看来,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 使用的是完全不同的格式。我很想知道这段代码是否对你有用)。

于 2016-08-13T19:21:42.920 回答