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

Viewed 2559

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.

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. 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

EDIT: Several comments requested adding an OSCP check to the list.

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());
1 Answers
Related