合并验证PKCS#7签名所需的所有任务 [英] Combining All of the Tasks Needed to Verify a PKCS#7 Signature

查看:147
本文介绍了合并验证PKCS#7签名所需的所有任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题我已经将我的头撞在墙上约20个小时了,我可能会错过一些容易的事情。但是,我觉得我需要帮助。我已经阅读了许多关于如何解决问题的不同部分的解释,但是我无法弄清楚如何将它们融合在一起。

I've been banging my head against the wall with this problem for about 20 hours now and I am probably missing something easy. However, I've gotten to the point where I think I need help. I have read dozens of explanations for how to do different parts of the problem, but I cannot figure out how to bring them all together.

我有一个DER编码的分离式PKCS#7数字签名。签名符合RFC 3852(加密消息语法)。对于我的项目,我需要逐步完成验证签名所需的每个步骤,并能够确定验证失败的步骤。我正在Java中使用BouncyCastle。

I have a DER-encoded detached PKCS#7 digital signature. The signature conforms to RFC 3852 (Cryptographic Message Syntax). For my project I need to step through each of the steps needed to verify a signature and be able to tell which step the verification failed on. I am using BouncyCastle in Java.

据我了解,验证数字签名需要六个基本步骤

To my understanding there are six basic steps needed to verify a digital signature


  1. 验证根证书是受信任的证书

  2. 验证从根证书到签名证书的证书链

  3. 验证签名者的姓名是您希望的名字

  4. 验证证书未过期

  5. 验证证书没有出现在CRL上(为简单起见,假设CRL已在本地下载)

  6. 验证签名中的摘要与文档的摘要匹配

  1. Verify that the root certificate is a trusted certificate
  2. Verify the certificate chain from the root certificate to the signing certificate
  3. Verify that the signer's name is who you would expect it to be
  4. Verify that the certificates are not expired
  5. Verify that the certificates do not appear on a CRL (for simplicity assume that the CRL is already downloaded locally)
  6. Verify the digest in the signature matches the digest of the document

编辑:一些评论要求将OSCP检查添加到列表中。

Several comments requested adding an OSCP check to the list.

在BouncyCastle测试代码中,我能够找到下面的例子。它似乎完成了2/6,但是尚不清楚它完成了其中的任何一项任务。如果有人能为我指出完成其余任务的正确方向,将不胜感激。

In the BouncyCastle test code, I was able to find the following example. It seems to accomplish 2/6, however, it is not clear that it does any of the of the tasks. If anyone could point me in the right direction for the rest of the tasks it would be greatly appreciated.

CMSSignedData s = ...
byte[] contentDigest = ...

Store certStore = s.getCertificates();
Store crlStore = s.getCRLs();
SignerInformationStore  signers = s.getSignerInfos();

Collection c = signers.getSigners();
Iterator it = c.iterator();

while (it.hasNext())
{
    SignerInformation   signer = (SignerInformation)it.next();
    Collection certCollection = certStore.getMatches(signer.getSID());

    Iterator certIt = certCollection.iterator();
    X509CertificateHolder cert = (X509CertificateHolder)certIt.next();

    assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert)));

    if (contentDigest != null)
    {
        assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
    }
}

Collection certColl = certStore.getMatches(null);
Collection crlColl = crlStore.getMatches(null);

assertEquals(certColl.size(), s.getCertificates().getMatches(null).size());
assertEquals(crlColl.size(), s.getCRLs().getMatches(null).size());


推荐答案

CMS签名数据验证中最复杂的是X.509验证部分。对于签名数据中的每个签名者,步骤如下:

The most complex in a CMS signed data validation is the X.509 validation part. For each signer in the signed data The steps are as follows:

1。查找签名者证书

SignerInformation signerInfo = (SignerInformation)it.next();
Collection certCollection = certStore.getMatches(signerInfo.getSID());
Iterator certIt = certCollection.iterator();
X509CertificateHolder signerCertificateHolder = (X509CertificateHolder)certIt.next();

我假设这里只有一个匹配的证书。

I assume here there is only one matching certificate.

2。查找从签名者证书到受信任的根证书的证书链

在这里,您要检查 Store中的证书以便找到证书链。使用主题DN /颁发者DN和主题密钥标识符/授权密钥标识符匹配来构建该链。

Here you are to inspect the certificates in the Store in order to find the certificate chain. Use the subject DN/Issuer DN and Subject Key Identifier/Authority Key Identifier matches to build that chain.

3。验证链

此步骤对链中的每个证书进行递归验证。对于每个证书,从根证书正下方的证书开始,您需要检查:

This step a recursive validation of every certificate in the chain. For each certificate, starting from the certificate directly under the root certificate you need to check:


  1. 证书签名颁发者公共密钥

  2. 证书的有效日期

  3. 证书的吊销状态

希望执行第2步和第2步; 3您可以使用内置的PKIX证书路径构建器和验证机制:

Hopefully for steps 2 & 3 you can use the built-in PKIX certificate path builder and validation mechanisms:

KeyStore trustAnchors = getTrustAnchors();
X509CertSelector target = new X509CertSelector();
target.setCertificate(signerCertificate);
PKIXBuilderParameters params = new PKIXBuilderParameters(anchors, target);
CertStoreParameters additionalCerts = new CollectionCertStoreParameters(allOtherCerts)
params.addCertStore(CertStore.getInstance("Collection", additionalCerts));
CertStoreParameters revocationObjects = new CollectionCertStoreParameters(allCRLs);
params.addCertStore(CertStore.getInstance("Collection", revocationObjects));
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
PKIXCertPathBuilderResult r = (PKIXCertPathBuilderResult) builder.build(params);
/* if the build method returns without exception, the certificate chain is valid */

为便于阅读,我省略了 java(x).crypto 和Bouncycastle类型之间的对象转换。

For the sake of readability I omited the convertion of objects between java(x).crypto an Bouncycastle types.

4。使用公钥验证SignerInfo签名

JcaSimpleSignerInfoVerifierBuilder builder = new JcaSimpleSignerInfoVerifierBuilder();
SignerInformationVerifier verifier = builder.build(signerCertificateHolder);
assertTrue(signerInfo.verify(verifier));

5。验证文档摘要与签名摘要是否匹配

byte[] contentDigest = computeDigest(originalDoc, signerInfo.getDigestAlgOID());
assertArrayEquals(contentDigest, signer.getContentDigest());

这篇关于合并验证PKCS#7签名所需的所有任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆