use of org.openecard.bouncycastle.cms.SignerInformation in project open-ecard by ecsec.
the class SignatureVerifier method validate.
public void validate(@Nonnull byte[] signature) throws KeyStoreException, SignatureInvalid {
try {
// load BC provider, so that the algorithms are available for the signature verification
Security.addProvider(new BouncyCastleProvider());
CMSProcessable wrappedChallenge = new CMSProcessableByteArray(challenge);
CMSSignedData signedData = new CMSSignedData(wrappedChallenge, signature);
Store<X509CertificateHolder> certStore = signedData.getCertificates();
SignerInformationStore signerInfoStore = signedData.getSignerInfos();
Collection<SignerInformation> signers = signerInfoStore.getSigners();
Collection<X509Certificate> allCerts = convertCertificates(certStore.getMatches(new AllSelector()));
for (SignerInformation signer : signers) {
Collection<X509CertificateHolder> certCollection = certStore.getMatches(signer.getSID());
X509CertificateHolder cert = certCollection.iterator().next();
DigestCalculatorProvider dp = new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
JcaSignerInfoVerifierBuilder verifBuilder = new JcaSignerInfoVerifierBuilder(dp).setProvider("BC");
verifBuilder.setSignatureAlgorithmFinder(new DefaultSignatureAlgorithmIdentifierFinder() {
@Override
public AlgorithmIdentifier find(String sigAlgName) {
if (!AllowedSignatureAlgorithms.isKnownJcaAlgorithm(sigAlgName)) {
throw new IllegalArgumentException("Unsupported signature algorithm used.");
} else {
return super.find(sigAlgName);
}
}
});
SignerInformationVerifier verif = verifBuilder.build(cert);
// verify the signature
if (!signer.verify(verif)) {
throw new SignatureInvalid("Signer information could not be verified.");
}
// verify the path and certificate
X509Certificate x509Cert = convertCertificate(cert);
// TODO: verify that the signature is not too old. How old can it be at max? 1 minute?
validatePath(x509Cert, allCerts, null);
// check that the end certificate is under the admissable certificates
if (ChipGatewayProperties.isUseSubjectWhitelist()) {
X500Principal subj = x509Cert.getSubjectX500Principal();
if (!AllowedSubjects.instance().isInSubjects(subj)) {
String msg = "The certificate used in the signature has an invalid subject: " + subj.getName();
throw new InvalidSubjectException(msg);
}
}
}
// fail if there is no signature in the SignedData structure
if (signers.isEmpty()) {
throw new SignatureInvalid("No signatures present in the given SignedData element.");
}
} catch (CertificateException ex) {
throw new SignatureInvalid("Failed to read a certificate form the CMS data structure.", ex);
} catch (CertPathBuilderException ex) {
throw new SignatureInvalid("Failed to build certificate path for PKIX validation.", ex);
} catch (CMSVerifierCertificateNotValidException ex) {
throw new SignatureInvalid("Signer certificate was not valid when the signature was created.", ex);
} catch (CMSException ex) {
throw new SignatureInvalid("Failed to validate CMS data structure.", ex);
} catch (InvalidSubjectException ex) {
throw new SignatureInvalid("Certificate with invalid subject used in signature.", ex);
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | OperatorCreationException ex) {
throw new SignatureInvalid("Invalid or unsupported algorithm or algorithm parameter used in signature.", ex);
} catch (IllegalArgumentException ex) {
throw new SignatureInvalid("Signature containes an invalid value.", ex);
}
}
Aggregations