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

时间:2016-11-18 20:01:55

标签: 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才能进行验证。我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:3)

只需验证签名,检查签名者的证书是否真实,以及链是否通向受信任的根目录是不够的。任何验证码也必须确保证书持有者有权为特定目的执行签名。获得具有smimeSign特权的证书的审查要比审查代码签名证书严格得多。

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

进行签名

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

[在我的原始答案之下,以解决您的编辑前问题&#39; 我是否可以指定我要在PKCS7中验证签名以防止其他目的&#39; :] < / p>

证书可以包含名为&#34;扩展密钥用法&#34;的(可选)属性。此属性用于指示允许使用证书的内容。一些可能的X509.v3用法是:

  • serverAuthentication
  • clientAuthentication
  • 代码签名
  • emailProtection
  • ipSecEndSystem
  • ipSecTunnel
  • 时间戳
  • ocspSigning
  • smartCardLogin
  • pkiPeerAuth

您可以在x509v3_config手册页中查看openssl知道的密钥用法标记。

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

如果您想分发一些代码,并且您希望确保收件人可以验证分发来自您并且未经更改,则可以使用PKCS#7进行分发,在这种情况下,您的证书应该具有codeSigning增强的密钥用法属性。 证书可能有多个关键用法,但一般来说,为不同的使用类型设置单独的密钥(以及证书)是个好主意。

Openssl在命令行上支持在使用&#34; openssl smime&#34;时指定证书的预期用途。命令。例如,

    openssl smime -verify -in myfile.p7b -inform DER -out my-p7-content -purpose any

将验证文件&#39; my file.p7p&#39;中的签名,它会将PKCS#7容器的内容写入文件&#39; my-p7-content&#39;并且它将接受任何有效的证书,无论其指明的目的是什么。 ( - 任何目的)。请注意,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, ...);

这将在验证时将目的设置为SSL客户端。