openssl cms -verify 不适用于外部证书

openssl cms -verify doesn't work with external certificate

我研究了几天,终于想出了一个简单的测试用例。我需要签署并验证 SMIME/CMS 格式文件的签名,该文件不得包含证书。

签名工作正常,但只有当证书嵌入到签名文件中并且允许 openssl 使用它时,验证才有效。如果我不包含证书或者如果我告诉 openssl 忽略它,验证将失败,即使我在这两种情况下都明确指定了签名者证书和 CA 证书。

我有以下文件:

第一步:生成签名文件:

$ openssl cms -sign -signer server-crt.pem -inkey server-key.pem -nodetach -md sha256 -in sample.xml -outform der -out sample.cms-der -noattr

注意我没有要求 openssl 排除证书。在最终版本中,我还必须添加 -nocerts,但现在如果我们保留它更容易测试。

第 2 步:使用嵌入式证书验证签名

好的,现在我们在 sample.cms-der 中有了签名文件 – 让我们首先使用签名文件中包含的证书来验证它:

$ openssl cms -verify -CAfile ca-crt.pem -inform der -signer server-crt.pem -in sample.cms-der
Verification successful

第 3 步 Alpha:忽略嵌入式证书验证签名

现在让 openssl 忽略签名文件中嵌入的证书——我使用的是完全相同的命令行,只是我在末尾添加了 -nointern 选项:

$ openssl cms -verify -CAfile ca-crt.pem -inform der -signer server-crt.pem -in sample.cms-der -nointern
Verification failure
14712:error:2E09D08A:CMS routines:CMS_verify:signer certificate not found:.\crypto\cms\cms_smime.c:333:

当然,在这种情况下,我仍然可以验证签名,因为证书已包含在内——但如果我使用 -nocerts 选项生成签名文件,我最终会失败,无论我是否验证是否使用 -nointern

第 3 步测试版:SMIME 而非 CMS

我也试过用smime代替cms,有趣的是,虽然报错信息是一样的,但是报错的报错号不同,而且来自源码的不同部分:

$ openssl smime -verify -CAfile ca-crt.pem -inform der -signer server-crt.pem -in sample.cms-der -nointern
Verification failure
13580:error:2107C080:PKCS7 routines:PKCS7_get0_signers:signer certificate not found:.\crypto\pkcs7\pk7_smime.c:466:

我使用的openssl版本是OpenSSL 1.0.2n 7 Dec 2017.

我正在调查的问题是更大背景的一部分,事实证明我在这个特定测试用例中遇到的问题相当愚蠢:我使用了错误的参数来指示签名证书。验证时不应该使用 -signer 来表示签名证书,而是 -certfile:

$ openssl cms -verify -CAfile ca-crt.pem -inform der -certfile server-crt.pem -in sample.cms-der -nointern
Verification successful

它也适用于 SMIME:

$ openssl smime -verify -CAfile ca-crt.pem -inform der -certfile server-crt.pem -in sample.cms-der -nointern
Verification successful

我通常会完全删除这个问题,但也许将来有人会发现它有用。