了解为什么在使用openssl验证期间pkcs7块失败 [英] Understand why pkcs7 block failed during verification using openssl
问题描述
我有一个名为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 :
推荐答案
您上传的示例文件具有一些属性,无法通过验证.
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_chain
和no_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屋!