Get signing chain from CMSSignedData

好久不见. 提交于 2021-02-08 07:55:40

问题


How can I get a signing chain from a CMSSignedData (BouncyCastle) to verify it with the signing chain store?

Certificate[] storeCertChain = store.getCertificateChain(alias)

Isn't there a command or something like this I can get the signing chain of the data? Or get the certificate from it and there from the signing chain?


回答1:


The chain of the certificate used to sign might be in the CMSSignedData, but it's not mandatory.

According to RFC 3852, a CMS SignedData has the 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 when it's present, all its contents are also optional. So, this field might contain the certificate chain, but it's not guaranteed.

If this field is present, you can get it with BouncyCastle (I'm using version 1.56):

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

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

When there are no certificates, I'm not sure if getCertificates() returns null or an empty Store (I think it may vary according to implementation).

If the Store is not null, you can check if the signer's certificate is present:

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's present in the certificates field. Then you can use it to verify the signature, exactly like you were doing in your other question.

To check if the whole chain is in the CMS structure, you can get all the certificates in the Store and check if they're there. To get everything inside a Store, you can use code similar to used here:

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

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

If the chain is not present, you'll have to get it elsewhere.

  • if you have the signer's (end entity) certificate, you can try it using the Authority Information Access (check this answer)
  • if it's not possible, you have to download the chain or get the certificates with the signer


来源:https://stackoverflow.com/questions/44026852/get-signing-chain-from-cmssigneddata

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!