假设所有内容都定义为它们在您的代码段中,具有分离的签名,没有到受信任根的证书链,证书 crt ,签名 signed 和数据 data ,以下应该做你想要的:
crt
signed
data
store = OpenSSL::X509::Store.new p7 = OpenSSL::PKCS7.new(signed.to_der) verified = p7.verify([crt], store, data, OpenSSL::PKCS7::DETACHED || OpenSSL::PKCS7::NOVERIFY)
(我没有测试过,YMMV)
以下是我如何找到这个的完整故事,其中包含我所使用的所有资源的链接,因此如果您需要更多信息,您可以在某处查看。
我们发现,看看OpenSSL :: PKCS7文档 这一点点智慧 :
的 PKCS7.new => PKCS7 强> 的 PKCS7.new(string)=> PKCS7 强> 本课程中的许多方法都没有记录。
一个快速的谷歌也没有改变任何东西。这表明我们将不得不采取更极端的措施。我们做一个 Google代码搜索 对于使用OpenSSL :: PKCS7验证签名的任何人。
嗯。我们发现 一些测试用例 。非常好;至少它有单元测试,可以帮助显示功能确实有效,并提供它的工作原理演示。
store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) ca_certs = [@ca_cert] data = "aaaaa\r\nbbbbb\r\nccccc\r\n" tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) p7 = OpenSSL::PKCS7::PKCS7.new(tmp.to_der) certs = p7.certificates signers = p7.signers assert(p7.verify([], store)) assert_equal(data, p7.data)
那不算太糟糕。包装证书商店。对您的数据进行签名,然后从签名数据中创建一个新的OpenSSL :: PKCS7对象。然后,你可以打电话 certificates 在它上面提取它签署的证书链, signers 提取签名者,和 verify 可以调用以验证签名是否有效。您似乎将包含可信CA证书的证书存储作为要验证的第二个参数传递。您可以通过调用来提取数据 data 在上面。
certificates
signers
verify
但第一个论点意味着什么?在我们的测试用例中似乎没有人传递任何东西,只有第一个参数的空列表。嗯。一个谜。我们会回过头来看看。
第三个,可选的,参数 verify 看起来像它用于 验证分离的签名 :
data = "aaaaa\nbbbbb\nccccc\n" flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag) p7 = OpenSSL::PKCS7::PKCS7.new(tmp.to_der) a1 = OpenSSL::ASN1.decode(p7) certs = p7.certificates signers = p7.signers assert(!p7.verify([], store)) assert(p7.verify([], store, data))
回到第一个论点。当我们进行代码搜索时,我们发现的不仅仅是测试用例;我们还发现了一些其他用途。事实上,第二个似乎是 使用第一个参数 :
# 'true' if signature was created using given cert, 'false' otherwise def match?(cert) @p7.verify([cert.raw_cert], @store, nil, OpenSSL::PKCS7::NOVERIFY) end
喔好吧。这是要检查的证书列表。现在有第四个参数,它似乎由标志组成。检查 OpenSSL文档 ,我们看到这个不直观的名称(使用NOVERIFY标志验证?)意味着您应该只检查传入的证书和签名中嵌入的证书的签名,而不是尝试针对您的可信CA存储验证整个证书链。
这都是有用的信息,但我们有什么遗漏?值得庆幸的是,Ruby是开源软件,因此我们可以“使用源代码,Luke!”在谷歌代码搜索上乱七八糟之后,我们发现了 的定义 ossl_pkcs7_verify 。一旦你超越了有些神秘的名字,代码就可以直接阅读;它基本上只是将其参数转换为OpenSSL可以理解的格式,并调用:
ossl_pkcs7_verify
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
所以,它看起来像 那' 我们真正想要寻找文件的地方。
描述 PKCS7_verify() 验证PKCS#7 signedData结构。 的 P7 强> 是要验证的PKCS7结构。 的 证书 强> 是一组用于搜索签名者证书的证书。 的 商店 强> 是一个值得信赖的证书商店(用于链验证)。 的 INDATA 强> 是内容不存在的签名数据 的 P7 强> (这是分离的)。内容写入 的 出 强> 如果它不是NULL。 的 旗 强> 是一组可选的标志,可用于修改验证 操作。 PKCS7_get0_signers() 从中检索签名者的证书 的 P7 强> 它确实如此 的 不 强> 检查其有效性或签名是否有效。该 的 证书 强> 和 的 旗 强> 参数与中的含义相同 PKCS7_verify().
PKCS7_verify() 验证PKCS#7 signedData结构。 的 P7 强> 是要验证的PKCS7结构。 的 证书 强> 是一组用于搜索签名者证书的证书。 的 商店 强> 是一个值得信赖的证书商店(用于链验证)。 的 INDATA 强> 是内容不存在的签名数据 的 P7 强> (这是分离的)。内容写入 的 出 强> 如果它不是NULL。
PKCS7_verify()
的 旗 强> 是一组可选的标志,可用于修改验证 操作。
PKCS7_get0_signers() 从中检索签名者的证书 的 P7 强> 它确实如此 的 不 强> 检查其有效性或签名是否有效。该 的 证书 强> 和 的 旗 强> 参数与中的含义相同 PKCS7_verify().
PKCS7_get0_signers()
PKCS7_verify().
见 完整的男人页 更多细节。
哦,作为旁注,我找到了 这个警告 在搜索时;它看起来像在Ruby 1.9中,并且可能在一些更高版本的Ruby 1.8中,该类已从冗余的OpenSSL :: PKCS7 :: PKCS7转移到OpenSSL :: PKCS7。
warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")