问题
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