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
- Verify that the root certificate is a trusted certificate
- Verify the certificate chain from the root certificate to the signing certificate
- Verify that the signer's name is who you would expect it to be
- Verify that the certificates are not expired
- Verify that the certificates do not appear on a CRL (for simplicity assume that the CRL is already downloaded locally)
- 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());