如何在Ruby中使用OpenSSL验证CMS/PKCS#7消息?
PKCS#7消息用作用户消息的数字签名,因此我需要签署新的用户消息并验证传入的消息.我没有在文档和谷歌中找到任何有用的东西.我发现很少有用于签名的代码示例,但没有用于验证:
signed = OpenSSL::PKCS7::sign(crt, key, data, [], OpenSSL::PKCS7::DETACHED)
Run Code Online (Sandbox Code Playgroud)
Bri*_*ell 40
假设所有内容都定义为它们在您的代码段中,具有分离的签名,没有证书链到受信任的根,证书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)
Run Code Online (Sandbox Code Playgroud)
(我没有测试过,YMMV)
以下是我如何找到这个的完整故事,其中包含我所使用的所有资源的链接,因此如果您需要更多信息,您可以在某处查看.
看一下OpenSSL :: PKCS7文档,我们发现了这一点:
PKCS7.new => pkcs7
PKCS7.new(string)=> pkcs7此类中的
许多方法都没有记录.
一个快速的谷歌也没有改变任何东西.这表明我们将不得不采取更极端的措施.让我们为使用OpenSSL :: PKCS7验证签名的任何人进行Google代码搜索.
嗯.我们找到了一些测试用例.非常好; 至少它有单元测试,可以帮助显示功能确实有效,并提供它的工作原理演示.
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)
Run Code Online (Sandbox Code Playgroud)
那不算太糟糕.包装证书商店.对您的数据进行签名,然后从签名数据中创建一个新的OpenSSL :: PKCS7对象.然后,您可以调用certificates它来提取其签名的证书链,signers提取签名者,并verify可以调用以验证签名是否有效.您似乎将包含可信CA证书的证书存储作为要验证的第二个参数传递.您可以通过调用来提取数据data.
但第一个论点意味着什么?我们的测试用例中没有人似乎传递了除第一个参数的空列表之外的任何内容.嗯.一个谜.我们会回过头来看看.
第三个可选的参数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))
Run Code Online (Sandbox Code Playgroud)
回到第一个论点.当我们进行代码搜索时,我们发现的不仅仅是测试用例; 我们还发现了一些其他用途.事实上,第二个似乎使用第一个参数:
# 'true' if signature was created using given cert, 'false' otherwise
def match?(cert)
@p7.verify([cert.raw_cert], @store, nil, OpenSSL::PKCS7::NOVERIFY)
end
Run Code Online (Sandbox Code Playgroud)
喔好吧.这是要检查的证书列表.现在有第四个参数,它似乎由标志组成.检查OpenSSL文档,我们看到这个不直观的名称(使用NOVERIFY标志验证?)意味着您应该只检查传入的证书和签名中嵌入的证书的签名,而不是尝试验证整个证书链您信任的CA商店.
这都是有用的信息,但我们有什么遗漏?值得庆幸的是,Ruby是开源软件,因此我们可以"使用源代码,Luke!" 在谷歌代码搜索上乱七八糟之后,我们找到了定义ossl_pkcs7_verify.一旦你超越了有点神秘的名字,代码就可以直接阅读; 它基本上只是将其参数转换为OpenSSL可以理解的格式,并调用:
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
Run Code Online (Sandbox Code Playgroud)
所以,看起来这就是我们真正想要寻找文档的地方.
描述
crt验证PKCS#7 signedData结构.p7是要验证的PKCS7结构.certs是一组用于搜索签名者证书的证书.store是一个值得信赖的certficate商店(用于链验证).如果p7中没有内容(即它已分离),则indata是签名数据.内容被写入了 ,如果它不为NULL.flags是一组可选的标志,可用于修改验证操作.
signed从检索签名者的证书P7,它并 没有对其进行合法性检查,还是任何签名是有效的.该证书 和标志参数具有相同的含义data
有关更多详细信息,请参见完整手册页.
哦,作为旁注,我在搜索时发现了这个警告 ; 它看起来像在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")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10580 次 |
| 最近记录: |