Combining All of the Tasks Needed to Verify a PKCS#7 Signature

╄→尐↘猪︶ㄣ 提交于 2019-12-04 08:05:18
Jcs

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. Find the signer certificate

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. Find a certificate chain from the signer certificate to a trusted root certificate

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. Validate the chain

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. the certificate signature with the issuer public key
  2. the validity date of the certificate
  3. the revocation status of the certificate

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 */

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

4. Validate the SignerInfo signature with the public key

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

5. Validate that the document digest matches the signed digest

byte[] contentDigest = computeDigest(originalDoc, signerInfo.getDigestAlgOID());
assertArrayEquals(contentDigest, signer.getContentDigest());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!