Java – Get the signature chain from CMSSignedData

Get the signature chain from CMSSignedData… here is a solution to the problem.

Get the signature chain from CMSSignedData

How do I get a signature chain from CMSSignedData (BouncyCaSTLe) to verify it with the signature chain store?

Certificate[] storeCertChain = store.getCertificateChain(alias)

Without a command or anything like that, can I get a signature chain of data? Or get a certificate from the signing chain?

Solution

The certificate chain used for signing may be in CMSSignedData, but it is not mandatory.

According to RFC 3852, CMS SignedData has following structure (described in section 5.1) :

SignedData ::= SEQUENCE {
    version CMSVersion,
    digestAlgorithms DigestAlgorithmIdentifiers,
    encapContentInfo EncapsulatedContentInfo,
    certificates [0] IMPLICIT CertificateSet OPTIONAL,
    crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
    signerInfos SignerInfos }

The certificates field is described as:

certificates is a collection of certificates. It is intended that
the set of certificates be sufficient to contain certification
paths from a recognized “root” or “top-level certification
authority” to all of the signers in the signerInfos field. There
may be
more certificates than necessary, and there may be
certificates sufficient to contain certification paths from two or
more independent top-level certification authorities. There may
also be fewer certificates than necessary
, if it is expected that
recipients have an alternate means of obtaining necessary
certificates (e.g., from a previous set of certificates). The
signer’s certificate MAY be included.

Note that the certificates field is optional, and even if it exists, all of its contents are optional. Therefore, this field may contain a certificate chain, but it is not guaranteed.

If this field exists, you can get it using BouncyCaSTLe (I’m using version 1.56):

import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.util.Store;

CMSSignedData sigData = ...
Store store = sigData.getCertificates();

I’m not sure if getCertificates() returns null or an empty Store when there is no certificate (I think it may vary from implementation to implementation).

If Store is not null, you can check if the signer’s certificate exists:

import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;

SignerInformationStore signers = sigData.getSignerInfos();
Collection<SignerInformation> c = signers.getSigners();
for (SignerInformation signer : c) {
     this collection will contain the signer certificate, if present
    Collection signerCol = store.getMatches(signer.getSID());
}

The signerCol collection will contain the signer certificate if it appears in the certificates field. You can then use it to verify the signature, just as you doin your other question

To check if the entire chain is in the CMS structure, you can take all the certificates in the Store and check if they exist.
To get everything in the Store, you can use code like used here:

Collection<X509CertificateHolder> allCerts = store.getMatches(null);

In the version I’m using (BouncyCaSTLe 1.56), passing null returns all certificates in the store. You can then check if the chain is in the allCerts collection.

If the chain is not there, you will have to get it from somewhere else.

  • If you have a certificate from the signer (end entity), you can use permission information access to try (check this answer
  • ).

  • If this is not possible, you must download the chain or obtain a certificate with the signer

Related Problems and Solutions