上载的示例文件有一些属性,这些属性会阻止对其进行验证。
p7
文件已于过期
Apr 24 22:33:39 2014 GMT
. 如果要验证链,则必须禁用过期日期检查。这是通过使用verify标志以编程方式完成的
X509_V_FLAG_NO_CHECK_TIME
-no_check_time
对于OpenSSL
smime -verify
然后,你的“信任之根”,在
mroot.pem.cer
Microsoft Time-Stamp PCA
证书的签署人
p7
文件链到
Microsoft Code Signing PCA
证明书
trust.pem.cer
. 该证书不是自签名的:其颁发者是
Microsoft Root Certificate Authority
. 如果您希望这样的证书位于链的末尾,则必须指出您正在使用所谓的部分链。这是通过使用verify标志以编程方式完成的
X509_V_FLAG_PARTIAL_CHAIN
,或选择
-partial_chain
smime-验证
工具。
此外,PKCS7验证的OpenSSL实现似乎要求您的证书包含S/MIME签名的扩展密钥用法,而您的证书不包含该用法。看起来可以通过为OpenSSL设置代码签名目的来解决这个问题
X509_STORE
. OpenSSL
工具不公开此类设置,因此您必须通过设置
XKU_CODE_SIGN
XKU
下面的代码段(省略返回代码检查)成功验证了您数据库中的证书链
p7
文件,但不是签名:
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);
verify_pe_pkcs7() in
osslsigncode.c
给出了执行此操作的示例代码。它的
PKCS7_verify()
调用不会验证证书链,但会检查签名。这需要提取散列,散列存储在p7中的Microsoft特定元素中,类型为
SpcIndirectDataContent
,正如下面的@dave_thompson_085所指出的。可以验证接管该散列的签名。为了完成验证,您还需要重新计算PE文件本身的哈希值,并将其与p7中的哈希值进行比较。
这个答案基于OpenSSL 1.1.1。刚才,我意识到您正在使用libressl,它基于(更)旧的OpenSSL版本。这在你的情况下可能不起作用。例如,对于我的libressl版本
工具不支持
partial_chain
和
no_time_check
选项,因为它们是在OpenSSL 1.1.0分支中引入的。