PKCS#7消息用作用户消息的数字签名,因此我需要签署一个新的用户消息并验证传入的消息.
我在 documentation和谷歌没有找到任何有用的东西.
我发现几个代码示例进行签名,但没有任何验证:
signed = OpenSSL::PKCS7::sign(crt,key,data,[],OpenSSL::PKCS7::DETACHED)
解决方法
假设一切都被定义为它们在您的代码段中,具有分离的签名,没有证书链可信任的根,证书crt,签名签名和数据数据,以下应该做你想要的:
store = OpenSSL::X509::Store.new p7 = OpenSSL::PKCS7.new(signed.to_der) verified = p7.verify([crt],store,OpenSSL::PKCS7::DETACHED || OpenSSL::PKCS7::NOVERIFY)
(我没有测试过,YMMV)
全文
这是完整的故事,我发现这一点,链接到我使用的所有来源,所以如果你需要更多的信息,你有去看看.
看看OpenSSL :: PKCS7文档,我们发现this morsel of wisdom:
PKCS7.new => pkcs7
PKCS7.new(string) => pkcs7
Many methods in this class aren’t documented.
而且一个快速的Google也不会改变任何东西.那就是说我们要采取更加极端的措施.对于使用OpenSSL :: PKCS7的任何人来验证签名,我们来做一个Google code search.
嗯.我们找到了some test cases.那很好至少它有单元测试,这可以帮助表明功能确实有效,并提供其工作原理的演示.
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,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对象.然后,您可以调用其上的证书来提取其签名的证书链,签名者提取签名者,并且可以调用验证以验证签名是否有效.看起来您将您的证书存储区(包含您的受信任的CA证书)作为第二个参数进行验证.您可以通过调用数据来提取数据.
但第一个论点是什么意思?在我们的测试用例中,没有一个人似乎只是为了第一个参数传递了一个空列表.嗯.一个谜.我们会回来
第三个可选参数验证看起来像是用于verifying a detached signature:
data = "aaaaa\nbbbbb\nccccc\n" flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED tmp = OpenSSL::PKCS7.sign(@ee1_cert,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([],data))
回到第一个参数当我们进行代码搜索时,我们发现不仅仅是测试用例;我们还发现了其他一些用途.其实第二个似乎是use the first argument:
# '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 docs,我们看到这个不直观的名称(用NOVERIFY标志验证)意味着您只应该检查签名中嵌入的证书和签名中嵌入的证书的签名,而不是尝试根据您的签名验证整个证书链值得信赖的CA商店.
这是所有有用的信息,但有什么我们缺少吗?幸运的是,Ruby是开源软件,所以我们可以“使用源码,Luke!”在Google代码搜索上发生了一些混乱之后,我们发现了definition of ossl_pkcs7_verify
.一旦你超过了一些隐秘的名字,代码是非常简单的阅读;它基本上只是将其参数转换为OpenSSL可以理解的格式,并调用:
ok = PKCS7_verify(p7,x509s,x509st,in,out,flg);
所以,看起来像that’我们真的想要查找文档.
DESCRIPTION
PKCS7_verify()
verifies a PKCS#7 signedData structure. p7 is the PKCS7 structure to verify. certs is a set of certificates in which to search for the signer’s certificate. store is a trusted certficate store (used for chain verification). indata is the signed data if the content is not present in p7 (that is it is detached). The content is written to out
if it is not NULL.flags is an optional set of flags,which can be used to modify the verify
operation.
PKCS7_get0_signers()
retrieves the signer’s certificates from p7,it does
not check their validity or whether any signatures are valid. The certs
and flags parameters have the same meanings as inPKCS7_verify().
有关详细信息,请参阅full man page.
哦,作为一个旁注,我在搜索时找到了this warning;看起来像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")