package es.uji.security.crypto.cms; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import java.security.Signature; import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; import java.security.cert.CertStore; import java.security.cert.CertStoreException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.SignerId; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationStore; public class CMSSignatureVerifier { private boolean verifyAgainstCA(X509Certificate[] caCertificates, CertStore certs, Provider provider) throws CertStoreException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, CertificateException, CertPathValidatorException { List<Certificate> certChain = new ArrayList<Certificate>(); if (caCertificates.length > 0) { X509Certificate rootCert = caCertificates[0]; certChain.add(rootCert); } for (int i = 1; i < caCertificates.length; i++) { certChain.add(caCertificates[i]); } Collection<? extends Certificate> certCollection = certs.getCertificates(null); for (Certificate c : certCollection) { certChain.add(c); } CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(certChain); CertStore store = CertStore.getInstance("Collection", ccsp); CertPath cp = CertificateFactory.getInstance("X.509", provider).generateCertPath(certChain); Set<TrustAnchor> trust = new HashSet<TrustAnchor>(); trust.add(new TrustAnchor((X509Certificate) certChain.get(0), null)); PKIXParameters param = new PKIXParameters(trust); param.addCertStore(store); param.setRevocationEnabled(false); param.setTrustAnchors(trust); CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider); cpv.validate(cp, param); return true; } /** * * Check the signature is correct, conform to plain data and the certificate chain is ok * * @throws CertPathValidatorException * @throws CertificateException * @throws InvalidAlgorithmParameterException * */ @SuppressWarnings("unchecked") public boolean verify(byte[] data, byte[] signedData, X509Certificate[] caCertificates, Provider provider) throws NoSuchProviderException, NoSuchAlgorithmException, CertStoreException, CMSException, InvalidAlgorithmParameterException, CertificateException, CertPathValidatorException { CMSProcessableByteArray processableByteArray = new CMSProcessableByteArray(data); CMSSignedData cmsSignedData = new CMSSignedData(processableByteArray, signedData); CertStore certs = cmsSignedData.getCertificatesAndCRLs("Collection", provider); SignerInformationStore signers = cmsSignedData.getSignerInfos(); Collection<SignerInformation> c = signers.getSigners(); boolean result = false; for (SignerInformation signer : c) { SignerId signerId = signer.getSID(); Collection certCollection = certs.getCertificates(signerId); Iterator certIt = certCollection.iterator(); X509Certificate cert = (X509Certificate) certIt.next(); result = signer.verify(cert, provider); if (result) { result = verifyAgainstCA(caCertificates, certs, provider); } else { return false; } } return result; } }