为什么 OpenSSL 的 PKCS7_verify() 需要“smimesign”证书目的?

Kon*_*yak 4 openssl digital-signature x509 pkcs#7

对于手册页PKCS7_verify()指出

...Each signer's certificate is chain verified using the smimesign purpose...

为什么总是需要这个目的?我理解它,因此签名的 PKCS7 结构可以用于许多事情,S/MIME 只是其中之一。

如果我的签名证书smimeSign在其extendedKeyUsage扩展名中PKCS7_verify()没有,则失败。我需要手动调整purpose以进行验证。我在这里错过了什么吗?

Pet*_*tok 5

仅仅验证签名、检查签名者的证书是否真实以及链是否指向受信任的根是不够的。任何验证码还必须确保证书持有者有权为特定目的执行签名。获得具有smimeSign特权的证书的审查比代码签名证书的审查要宽松得多。

想象一家软件开发公司,每个员工都获得了用于电子邮件签名和加密的证书。该公司还发布了软件产品,并提供了其产品的 PKCS#7 签名分发包。如果 PKCS#7 验证功能没有检查签名证书的目的(在这种情况下我们想要codesign),公司雇员中的不良行为者可能会创建软件产品的受损版本,并用他们的 E 签名-邮件证书(只有目的smimesign。)

对于 OpenSSL 的pkcs7_verify(),API 旨在暗示一个目的,而不是明确要求传入一个目的,smimeSign并被选为默认值。我猜因为 S/MIME 是 PKCS#7 最常见的用法,所以它是有道理的,它允许某人在大多数用例中验证 PKCS#7,而无需了解extendedKeyUsage.

[在我的原始答案下方,解决您编辑前的问题“我可以指定我想针对其他目的验证 PKCS7 中的签名吗”:]

证书可以包含称为“扩展密钥用法”的(可选)属性。此属性用于指示允许使用证书的用途。一些可能的 X509.v3 用法是:

  • 服务器认证
  • 客户端认证
  • 代码签名
  • 电子邮件保护
  • 网络安全终端系统
  • ipSec隧道
  • 时间戳
  • 签名
  • 智能卡登录
  • pkiPeerAuth

您可以查看x509v3_config手册页以了解 openssl 知道的密钥用法标志。

PKCS#7 是一种通用容器格式,允许对容器的内容进行签名和/或加密。S/MIME 使用 PKCS#7 对电子邮件消息进行签名和/或加密,在这种情况下,所使用的证书应具有 emailProtection 用法。

如果你想分发一些代码,并且你想确保收件人可以验证分发是来自你的,并且没有改变,你可以使用 PKCS#7 分发,在这种情况下,你的证书应该有 codeSigning 增强密钥使用属性。一个证书可能有多个密钥用途,但一般来说,为不同的用途类型拥有一个单独的密钥(以及证书)是个好主意。

在命令行上,Openssl 支持在使用“openssl smime”命令时指定证书的所需用途。例如,

    openssl smime -verify -in myfile.p7b -inform DER -out my-p7-content -purpose any
Run Code Online (Sandbox Code Playgroud)

将验证文件 'my file.p7p' 中的签名,它将 PKCS#7 容器的内容写入文件 'my-p7-content' 并且它会接受任何有效的证书,无论其指示的目的是什么。(-目的任何)。请注意,smime 的 openssl 手册页没有列出 -purpose 开关作为选项,但它确实受支持。

由于您以编程方式引用了 PKCS7_verify API 文档,因此您可以在设置 X509_STORE 对象时通过X509_VERIFY_PARAM_set_purpose方法指定用途。以下片段应该让您了解该过程:

X509_STORE store;
int purpose;

store = X509_STORE_new();
verify_params = X509_Store_get0_param(store);
purpose = X509_PURPOSE_get_by_sname("sslclient");
X509_VERIFY_PARAM_set_purpose(verify_params, purpose)
...
PKCS7_verify(..., store, ...);
Run Code Online (Sandbox Code Playgroud)

这将在验证时将用途设置为 SSL 客户端。