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

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

问题描述

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

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和数据data,则以下应做您想做的:

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也不显示任何内容.那就是说我们将不得不采取更多的极端措施.让我们做一个

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\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提取数据.

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\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))

返回第一个参数.当我们进行代码搜索时,我们发现的不只是测试用例.我们还发现了其他一些用途.实际上,第二个似乎是

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是开源软件,因此我们可以使用源代码,卢克!"在Google代码搜索中弄乱了一些内容之后,我们找到了

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#7signedData结构. p7 是要验证的PKCS7结构. 证书是一组证书,用于在其中搜索签名者的证书. 商店是受信任的证书商店(用于链验证).如果 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 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.

哦,作为旁注,我发现

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天全站免登陆