use of org.bouncycastle.cms.SignerInformationVerifier in project jmeter by apache.
the class SMIMEAssertion method verifySignature.
private static AssertionResult verifySignature(SMIMEAssertionTestElement testElement, SMIMESignedParser s, String name) throws CMSException {
AssertionResult res = new AssertionResult(name);
try {
Store certs = s.getCertificates();
SignerInformationStore signers = s.getSignerInfos();
Iterator<?> signerIt = signers.getSigners().iterator();
if (signerIt.hasNext()) {
SignerInformation signer = (SignerInformation) signerIt.next();
Iterator<?> certIt = certs.getMatches(signer.getSID()).iterator();
if (certIt.hasNext()) {
// the signer certificate
X509CertificateHolder cert = (X509CertificateHolder) certIt.next();
if (testElement.isVerifySignature()) {
SignerInformationVerifier verifier = null;
try {
verifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert);
} catch (OperatorCreationException e) {
log.error("Can't create a provider.", e);
}
if (verifier == null || !signer.verify(verifier)) {
res.setFailure(true);
res.setFailureMessage("Signature is invalid");
}
}
if (testElement.isSignerCheckConstraints()) {
StringBuilder failureMessage = new StringBuilder();
String serial = testElement.getSignerSerial();
if (!JOrphanUtils.isBlank(serial)) {
BigInteger serialNbr = readSerialNumber(serial);
if (!serialNbr.equals(cert.getSerialNumber())) {
res.setFailure(true);
failureMessage.append("Serial number ").append(serialNbr).append(" does not match serial from signer certificate: ").append(cert.getSerialNumber()).append("\n");
}
}
String email = testElement.getSignerEmail();
if (!JOrphanUtils.isBlank(email)) {
List<String> emailFromCert = getEmailFromCert(cert);
if (!emailFromCert.contains(email)) {
res.setFailure(true);
failureMessage.append("Email address \"").append(email).append("\" not present in signer certificate\n");
}
}
String subject = testElement.getSignerDn();
if (subject.length() > 0) {
final X500Name certPrincipal = cert.getSubject();
log.debug("DN from cert: {}", certPrincipal);
X500Name principal = new X500Name(subject);
log.debug("DN from assertion: {}", principal);
if (!principal.equals(certPrincipal)) {
res.setFailure(true);
failureMessage.append("Distinguished name of signer certificate does not match \"").append(subject).append("\"\n");
}
}
String issuer = testElement.getIssuerDn();
if (issuer.length() > 0) {
final X500Name issuerX500Name = cert.getIssuer();
log.debug("IssuerDN from cert: {}", issuerX500Name);
X500Name principal = new X500Name(issuer);
log.debug("IssuerDN from assertion: {}", principal);
if (!principal.equals(issuerX500Name)) {
res.setFailure(true);
failureMessage.append("Issuer distinguished name of signer certificate does not match \"").append(subject).append("\"\n");
}
}
if (failureMessage.length() > 0) {
res.setFailureMessage(failureMessage.toString());
}
}
if (testElement.isSignerCheckByFile()) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (InputStream fis = new FileInputStream(testElement.getSignerCertFile());
InputStream bis = new BufferedInputStream(fis)) {
X509CertificateHolder certFromFile = new JcaX509CertificateHolder((X509Certificate) cf.generateCertificate(bis));
if (!certFromFile.equals(cert)) {
res.setFailure(true);
res.setFailureMessage("Signer certificate does not match certificate " + testElement.getSignerCertFile());
}
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug("Could not read cert file {}", testElement.getSignerCertFile(), e);
}
res.setFailure(true);
res.setFailureMessage("Could not read certificate file " + testElement.getSignerCertFile());
}
}
} else {
res.setFailure(true);
res.setFailureMessage("No signer certificate found in signature");
}
}
// TODO support multiple signers
if (signerIt.hasNext()) {
log.warn("SMIME message contains multiple signers! Checking multiple signers is not supported.");
}
} catch (GeneralSecurityException e) {
log.error(e.getMessage(), e);
res.setError(true);
res.setFailureMessage(e.getMessage());
}
return res;
}
use of org.bouncycastle.cms.SignerInformationVerifier in project poi by apache.
the class TSPTimeStampService method timeStamp.
@SuppressWarnings("unchecked")
public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
// digest the message
MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo());
byte[] digest = messageDigest.digest(data);
// generate the TSP request
BigInteger nonce = new BigInteger(128, new SecureRandom());
TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator();
requestGenerator.setCertReq(true);
String requestPolicy = signatureConfig.getTspRequestPolicy();
if (requestPolicy != null) {
requestGenerator.setReqPolicy(new ASN1ObjectIdentifier(requestPolicy));
}
ASN1ObjectIdentifier digestAlgoOid = mapDigestAlgoToOID(signatureConfig.getTspDigestAlgo());
TimeStampRequest request = requestGenerator.generate(digestAlgoOid, digest, nonce);
byte[] encodedRequest = request.getEncoded();
// create the HTTP POST request
Proxy proxy = Proxy.NO_PROXY;
if (signatureConfig.getProxyUrl() != null) {
URL proxyUrl = new URL(signatureConfig.getProxyUrl());
String host = proxyUrl.getHost();
int port = proxyUrl.getPort();
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByName(host), (port == -1 ? 80 : port)));
}
HttpURLConnection huc = (HttpURLConnection) new URL(signatureConfig.getTspUrl()).openConnection(proxy);
if (signatureConfig.getTspUser() != null) {
String userPassword = signatureConfig.getTspUser() + ":" + signatureConfig.getTspPass();
String encoding = DatatypeConverter.printBase64Binary(userPassword.getBytes(Charset.forName("iso-8859-1")));
huc.setRequestProperty("Authorization", "Basic " + encoding);
}
huc.setRequestMethod("POST");
huc.setConnectTimeout(20000);
huc.setReadTimeout(20000);
// also sets method to POST.
huc.setDoOutput(true);
huc.setRequestProperty("User-Agent", signatureConfig.getUserAgent());
huc.setRequestProperty("Content-Type", signatureConfig.isTspOldProtocol() ? "application/timestamp-request" : // "; charset=ISO-8859-1");
"application/timestamp-query");
OutputStream hucOut = huc.getOutputStream();
hucOut.write(encodedRequest);
// invoke TSP service
huc.connect();
int statusCode = huc.getResponseCode();
if (statusCode != 200) {
LOG.log(POILogger.ERROR, "Error contacting TSP server ", signatureConfig.getTspUrl() + ", had status code " + statusCode + "/" + huc.getResponseMessage());
throw new IOException("Error contacting TSP server " + signatureConfig.getTspUrl() + ", had status code " + statusCode + "/" + huc.getResponseMessage());
}
// HTTP input validation
String contentType = huc.getHeaderField("Content-Type");
if (null == contentType) {
throw new RuntimeException("missing Content-Type header");
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(huc.getInputStream(), bos);
LOG.log(POILogger.DEBUG, "response content: ", HexDump.dump(bos.toByteArray(), 0, 0));
if (!contentType.startsWith(signatureConfig.isTspOldProtocol() ? "application/timestamp-response" : "application/timestamp-reply")) {
throw new RuntimeException("invalid Content-Type: " + contentType + // dump the first few bytes
": " + HexDump.dump(bos.toByteArray(), 0, 0, 200));
}
if (bos.size() == 0) {
throw new RuntimeException("Content-Length is zero");
}
// TSP response parsing and validation
TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray());
timeStampResponse.validate(request);
if (0 != timeStampResponse.getStatus()) {
LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus());
LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString());
PKIFailureInfo failInfo = timeStampResponse.getFailInfo();
if (null != failInfo) {
LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue());
if (/*PKIFailureInfo.unacceptedPolicy*/
(1 << 8) == failInfo.intValue()) {
LOG.log(POILogger.DEBUG, "unaccepted policy");
}
}
throw new RuntimeException("timestamp response status != 0: " + timeStampResponse.getStatus());
}
TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken();
SignerId signerId = timeStampToken.getSID();
BigInteger signerCertSerialNumber = signerId.getSerialNumber();
X500Name signerCertIssuer = signerId.getIssuer();
LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber);
LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer);
// TSP signer certificates retrieval
Collection<X509CertificateHolder> certificates = timeStampToken.getCertificates().getMatches(null);
X509CertificateHolder signerCert = null;
Map<X500Name, X509CertificateHolder> certificateMap = new HashMap<X500Name, X509CertificateHolder>();
for (X509CertificateHolder certificate : certificates) {
if (signerCertIssuer.equals(certificate.getIssuer()) && signerCertSerialNumber.equals(certificate.getSerialNumber())) {
signerCert = certificate;
}
certificateMap.put(certificate.getSubject(), certificate);
}
// TSP signer cert path building
if (signerCert == null) {
throw new RuntimeException("TSP response token has no signer certificate");
}
List<X509Certificate> tspCertificateChain = new ArrayList<X509Certificate>();
JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter();
x509converter.setProvider("BC");
X509CertificateHolder certificate = signerCert;
do {
LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject());
tspCertificateChain.add(x509converter.getCertificate(certificate));
if (certificate.getSubject().equals(certificate.getIssuer())) {
break;
}
certificate = certificateMap.get(certificate.getIssuer());
} while (null != certificate);
// verify TSP signer signature
X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded());
DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator();
DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder();
DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder();
BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider();
BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator);
SignerInformationVerifier verifier = verifierBuilder.build(holder);
timeStampToken.validate(verifier);
// verify TSP signer certificate
if (signatureConfig.getTspValidator() != null) {
signatureConfig.getTspValidator().validate(tspCertificateChain, revocationData);
}
LOG.log(POILogger.DEBUG, "time-stamp token time: " + timeStampToken.getTimeStampInfo().getGenTime());
return timeStampToken.getEncoded();
}
Aggregations