了解为什么在使用openssl验证期间pkcs7块失败 [英] Understand why pkcs7 block failed during verification using openssl

查看:770
本文介绍了了解为什么在使用openssl验证期间pkcs7块失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为p7的PKCS#7 Der格式的文件 和一个名为mroot.der.cer的x509证书文件,该文件与p7链的根证书匹配.

I've got PKCS#7 Der formatted file called p7 and an x509 certificate file called mroot.der.cer which matches the root certificate of p7 chain.

我想使用以下命令使用openssl验证我的p7证书链:

I'd like to verify my p7 certificate chain using openssl using the following commands :

First - convert my mroot trusted cert file to pem format. 
openssl x509 -in mroot.der.cer -inform der -outform PEM -out mroot.pem.cer

Second - verify the root chain using mroot.pem.cer
openssl  smime -verify -CAfile mroot.pem.cer -in p7 -inform DER -out blabla

但是,出现以下错误:

验证失败 140735569544136:错误:21075075:PKCS7例程:PKCS7_verify:证书验证错误:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_smime.c:343:验证错误:无法获得本地发行者证书

Verification failure 140735569544136:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_smime.c:343:Verify error:unable to get local issuer certificate

我也尝试添加最后一个命令-noverify标志,但是出现了另一个错误.

I also tried to add the last command, the -noverify flag but got a different error.

验证失败 140735569544136:错误:21071065:PKCS7例程:PKCS7_signatureVerify:摘要失败:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_doit.c:1084: 140735569544136:错误:21075069:PKCS7例程:PKCS7_verify:签名失败:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_smime.c:412:

Verification failure 140735569544136:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_doit.c:1084: 140735569544136:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_smime.c:412:

pkcs7结构应该很好,因为我已经从PE文件iexlorer.exe中提取了它,并且从它的链中提取了根证书,并将其称为受信任证书.

The pkcs7 structure should be fine as I've extracted it from the PE file iexlorer.exe and from its chain I've extracted the root certificate, and refer to it as a trusted one.

我在这里做错了什么?

What am I doing wrong here ?

P.s. 为了观察与我相同的失败,我已将文件上传到以下链接:

P.s. To observe the same failures I did, I've uploaded the files to the following links :

https://ufile.io/vrqpt

https://ufile.io/ajgex

推荐答案

您上传的示例文件具有一些属性,无法通过验证.

Your uploaded example files have a few properties which prevent it from being verified.

首先,p7文件中的签名者证书已在Apr 24 22:33:39 2014 GMT上过期.如果要验证链,则必须禁用对到期日期的检查.这是通过验证标志X509_V_FLAG_NO_CHECK_TIME或OpenSSL smime -verify工具的选项-no_check_time以编程方式完成的.

First, the certificate of the signer in the p7 file has expired on Apr 24 22:33:39 2014 GMT. You will have to disable checking of the expiration date if you want to verify the chain. This is programmatically done with the verify flag X509_V_FLAG_NO_CHECK_TIME, or the option -no_check_time for the OpenSSL smime -verify tool.

然后,您在mroot.pem.cer文件中找到的信任根"不是正确的.您提取了Microsoft Time-Stamp PCA证书,而p7文件的签名者链接到了Microsoft Code Signing PCA证书.

Then, your "root of trust", found in the mroot.pem.cer file is not the right one. You extracted the Microsoft Time-Stamp PCA certificate whereas the signer of the p7 file chains up to the Microsoft Code Signing PCA certificate.

比方说,您将正确的证书提取到名为trust.pem.cer的文件中.该证书不是自签名的:它的颁发者是Microsoft Root Certificate Authority.如果您希望这样的证书位于链的末尾,则必须指出您正在使用所谓的部分链.通过验证标志X509_V_FLAG_PARTIAL_CHAIN或OpenSSL smime -verify工具的选项-partial_chain以编程方式完成此操作.

Let's say that you extract that correct certificate to a file called trust.pem.cer. That certificate is not self-signed: its issuer is the Microsoft Root Certificate Authority. You will have to indicate that you are using a so-called partial chain if you want such a certificate to be at the end of the chain. This is programmatically done with the verify flag X509_V_FLAG_PARTIAL_CHAIN, or the option -partial_chain for the OpenSSL smime -verify tool.

此外,看起来PKCS7验证的OpenSSL实现要求您的证书包括S/MIME签名的扩展密钥用法,而您的证书不包括该扩展密钥用法.通过为OpenSSL X509_STORE设置代码签名目的,似乎可以解决此问题. OpenSSL smime -verify工具不会公开这种设置,因此您必须通过设置XKU_CODE_SIGN用途以编程方式进行此设置. XKU代表扩展密钥用法,并且要注意,实际上不存在围绕它的OpenSSL文档.如果您决定使用它,则必须进行彻底的测试.

Also, it looks like the OpenSSL implementation of the PKCS7 verification requires your certificate to include the extended key usage of S/MIME signing, which your certificate does not include. It looks like this can be worked around by setting a code-signing purpose for the OpenSSL X509_STORE. The OpenSSL smime -verify tool does not expose this kind of setting so you will have to do this programmatically by setting the XKU_CODE_SIGN purpose. XKU stands for eXtended Key Usage and, as a caveat, the OpenSSL documentation around that is virtually non-existent. You have to thoroughly test this if you decide to use it.

下面的代码段(省略返回代码检查)成功地验证了p7文件中的证书链,但没有验证签名:

The piece of code below (return code checking omitted) successfully verifies the certificate chain in your p7 file, but not the signature:

BIO *bio_p7 = BIO_new_file("p7", "r");
PKCS7 *p7 = d2i_PKCS7_bio(bio_p7, NULL);
X509_STORE *store = X509_STORE_new();
X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
X509_LOOKUP_load_file(lookup, "trust.pem.cer", X509_FILETYPE_PEM);
X509_STORE_set_purpose(store, XKU_CODE_SIGN); /* see caveat above */
X509_VERIFY_PARAM_set_flags(
    X509_STORE_get0_param(store),
    X509_V_FLAG_NO_CHECK_TIME | X509_V_FLAG_PARTIAL_CHAIN);
int retcode = PKCS7_verify(p7, NULL, store, NULL, NULL, PKCS7_NOSIGS);

对于签名本身的验证:函数osslsigncode.c 中的> verify_pe_pkcs7()给出了执行此操作的示例代码.它的PKCS7_verify()调用不会验证证书链,但是会检查签名.这需要提取散列,该散列存储在p7的Microsoft特定元素中,其类型为SpcIndirectDataContent,如下面的@ dave_thompson_085所指出的.可以验证在该哈希上取得的签名.为了进行完整的验证,您还需要重新计算PE文件本身的哈希值,并将其与p7中的哈希值进行比较.

For a verification of the signature itself: the function verify_pe_pkcs7() in osslsigncode.c gives example code to do that. Its PKCS7_verify() invocation does not verify the certificate chain, but it does check the signature. This requires extraction of a hash which is stored in a Microsoft-specific element in the p7 of a type called SpcIndirectDataContent, as pointed out by @dave_thompson_085 below. It is possible to verify the signature that was taken over that hash. For a complete verification, you will also need to re-calculate the hash over the PE file itself and compare it to the hash value found in the p7.

此答案基于OpenSSL 1.1.1.刚才,我意识到您正在使用libressl,它基于(很多)旧版本的OpenSSL.在您的情况下,它可能不起作用.例如,对于我的libressl版本,smime -verify工具不支持partial_chainno_time_check选项,因为这些是在OpenSSL 1.1.0分支中引入的.

This answer is based on OpenSSL 1.1.1. Just now, I realize that you are using libressl, which is based on a (much) older version of OpenSSL. It might not work in your case. For example, for my version of libressl, the smime -verify tool does not support the partial_chain and no_time_check options because those were introduced in the OpenSSL 1.1.0 branch.

这篇关于了解为什么在使用openssl验证期间pkcs7块失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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