使用 OpenSSL 进行数字签名验证 [英] Digital signature verification with OpenSSL

查看:123
本文介绍了使用 OpenSSL 进行数字签名验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Ruby 中使用 OpenSSL 验证 CMS/PKCS #7 消息?
PKCS #7 消息用作用户消息的数字签名,因此我需要签署新的用户消息并验证传入的消息.我在 文档 和谷歌中没有找到任何有用的信息.我发现很少有用于签名的代码示例,但没有用于验证的代码示例:

How can I verify CMS/PKCS #7 messages using OpenSSL in Ruby?
PKCS #7 message is used as a digital signature for user messages, so I need to sign a new user message and verify the incoming one. I haven't found anything helpfull in documentation and google. I have found few code samples for signing, but nothing for verifying:

signed = OpenSSL::PKCS7::sign(crt, key, data, [], OpenSSL::PKCS7::DETACHED)

推荐答案

简短回答

假设所有内容都定义为它们在您的代码段中的定义,带有分离的签名,没有到受信任根的证书链、证书 crt、签名 signed 和数据 <代码>数据,以下应该做你想做的:

Short answer

Assuming everything is defined as they were in your snippet, with a detached signature, with no certificate chain to a trusted root, certificate crt, signature signed and data data, the following should do what you want:

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)

(I have not tested this, YMMV)

这是我如何找到它的完整故事,以及我使用的所有资源的链接,因此如果您需要更多信息,可以去某个地方查看.

Here's the full story of how I found this, with links to all of the sources I used, so if you need more information, you have somewhere to go to look.

查看 OpenSSL::PKCS7 文档,我们发现 这一点点智慧:

Taking a look at the OpenSSL::PKCS7 documentation, we find this morsel of wisdom:

PKCS7.new => pkcs7
PKCS7.new(string) => pkcs7
此类中的许多方法没有记录.

PKCS7.new => pkcs7
PKCS7.new(string) => pkcs7
Many methods in this class aren’t documented.

快速的谷歌也没有发现任何问题.这意味着我们将不得不采取更极端的措施.让我们做一个 Google 代码搜索,适用于使用 OpenSSL::PKCS7 验证签名的任何人.

And a quick Google doesn't turn anything up either. That says we're going to have to take more extreme measures. Let's do do a Google code search for anyone who uses OpenSSL::PKCS7 to verify a signature.

嗯.我们找到 一些测试用例.那挺好的;至少它有单元测试,可以帮助证明该功能确实有效,并提供了它如何工作的演示.

Hmm. We find some test cases. That's good; at least it has unit tests, which can help show that the functionality does work, and provide a demonstration of how it works.

store = OpenSSL::X509::Store.new
store.add_cert(@ca_cert)
ca_certs = [@ca_cert]

data = "aaaaa
bbbbb
ccccc
"
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 来提取数据.

That's not too bad. Crate a certificate store. Sign your data, then create a new OpenSSL::PKCS7 object from the signed data. Then, you can call certificates on it to extract the certificate chain it was signed with, signers to extract the signers, and verify can be called to verify that the signature is valid. It looks like you pass your certificate store, containing your trusted CA certificates, as the second argument to verify. And you can extract the data by calling data on it.

但是第一个参数是什么意思?我们的测试用例中似乎没有人为第一个参数传递一个空列表.唔.一个谜.我们会回到那个话题.

But what does the first argument mean? No one in our test cases seems to pass anything but an empty list in for the first argument. Hmm. A mystery. We'll come back to that.

verify 的第三个可选参数看起来像是用于 验证分离的签名:

The third, optional, argument to verify looks like it's used for verifying a detached signature:

data = "aaaaa
bbbbb
ccccc
"
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))

回到第一个论点.当我们进行代码搜索时,我们发现的不仅仅是测试用例;我们还发现了一些其他用途.事实上,第二个似乎 使用第一个参数:

Back to the first argument. We found more than just the test cases when we did our code search; we also found a few other uses. In fact, the second one seems to to 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 文档,我们看到这个不直观的名称(使用 NOVERIFY 标志验证?) 意味着您应该只根据传入的证书和签名中嵌入的证书检查签名,而不要尝试根据您受信任的 CA 存储验证整个证书链.

Ah, OK. It's a list of certs to check against. And now there's a fourth parameter, which appears to consist of flags. Checking the OpenSSL docs, we see that this unintuitive name (verify with a NOVERIFY flag?) means that you should only check the signature against the certs passed in and the certs embedded in the signature, and not attempt to verify the entire certificate chain against your trusted CA store.

这些都是有用的信息,但我们还遗漏了什么吗?幸运的是,Ruby 是开源软件,所以我们可以使用源代码,Luke!"在 Google 代码搜索上进行了一些乱七八糟的搜索后,我们找到了 ossl_pkcs7_verify 的定义.一旦你了解了一些有点神秘的名字,代码就相当容易阅读了;它基本上只是将其参数转换为 OpenSSL 可以理解的格式,然后调用:

This is all useful information, but is there anything we're missing? Thankfully, Ruby is open source software, so we can "Use the source, Luke!" After some messing around on Google code search, we find the definition of ossl_pkcs7_verify. Once you get past the somewhat cryptic names, the code is fairly straightforward to read; it's basically just converting its arguments to a format that OpenSSL can understand, and calling:

ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);

所以,看起来那是我们真正想看的地方用于文档.

So, it looks like that's where we really want to look for documentation.

PKCS7_verify() 验证 PKCS#7 签名数据结构.p7 是要验证的 PKCS7 结构.certs 是一组用于搜索签名者证书的证书.store 是受信任的证书存储(用于链验证).如果 p7 中不存在内容(即已分离),则 indata 是签名数据.内容被写入out如果它不是NULL.

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 是一组可选的标志,可用于修改验证手术.

flags is an optional set of flags, which can be used to modify the verify operation.

PKCS7_get0_signers()p7 检索签名者的证书,它确实检查它们的有效性或任何签名是否有效.证书flags 参数与 PKCS7_verify() 中的含义相同.

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 in PKCS7_verify().

有关详细信息,请参阅完整手册页.

See the full man page for more details.

哦,顺便提一下,我发现了 这个警告 搜索时;它看起来像在 Ruby 1.9 中,并且可能在 Ruby 1.8 的某些更高版本中,该类已从冗余的 OpenSSL::PKCS7::PKCS7 移至 OpenSSL::PKCS7.

Oh, and as a side note, I found this warning while searching; it looks like in Ruby 1.9, and possibly in some later versions of Ruby 1.8, the class has been moved from the redundant OpenSSL::PKCS7::PKCS7 to OpenSSL::PKCS7.

warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")

这篇关于使用 OpenSSL 进行数字签名验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆