307 List<X509CertificateHolder> certs =
new ArrayList<>(Arrays.asList(basicOcspResponse.getCerts()));
308 X509Certificate signingCert = null;
311 certs.add(
new JcaX509CertificateHolder(issuerCertificate));
312 if (responderCertificate != null) {
313 certs.add(
new JcaX509CertificateHolder(responderCertificate));
315 }
catch (CertificateEncodingException e) {
318 if (certs.size() > 0) {
320 X500Name responderName = basicOcspResponse.getResponderId().toASN1Primitive().getName();
321 byte[] responderKey = basicOcspResponse.getResponderId().toASN1Primitive().getKeyHash();
323 if (responderName != null) {
324 logger.log(Level.INFO,
"Responder Name: {0}", responderName.toString());
325 for (X509CertificateHolder certHolder : certs) {
327 X509Certificate tempCert =
new JcaX509CertificateConverter()
328 .setProvider(
"BC").getCertificate(certHolder);
329 X500Name respName =
new X500Name(tempCert.getSubjectX500Principal().getName());
330 if (responderName.equals(respName)) {
331 signingCert = tempCert;
332 logger.log(Level.INFO,
"Found a certificate whose principal \"{0}\" matches the responder name \"{1}\"",
333 new Object[] {tempCert.getSubjectDN().getName(), responderName.toString()});
336 }
catch (CertificateException e) {
337 logger.log(Level.FINE, e.getMessage());
340 }
else if (responderKey != null) {
341 SubjectKeyIdentifier responderSubjectKey =
new SubjectKeyIdentifier(responderKey);
342 logger.log(Level.INFO,
"Responder Key: {0}", Arrays.toString(responderKey));
343 for (X509CertificateHolder certHolder : certs) {
345 X509Certificate tempCert =
new JcaX509CertificateConverter()
346 .setProvider(
"BC").getCertificate(certHolder);
348 SubjectKeyIdentifier subjectKeyIdentifier = null;
349 if (certHolder.getExtensions() != null) {
350 subjectKeyIdentifier = SubjectKeyIdentifier.fromExtensions(certHolder.getExtensions());
353 if (subjectKeyIdentifier != null) {
354 logger.log(Level.INFO,
"Certificate: {0}\nSubject Key Id: {1}",
355 new Object[] {tempCert.getSubjectDN().getName(), Arrays.toString(subjectKeyIdentifier.getKeyIdentifier())});
358 if (subjectKeyIdentifier != null && responderSubjectKey.equals(subjectKeyIdentifier)) {
359 signingCert = tempCert;
360 logger.log(Level.INFO,
"Found a signer certificate \"{0}\" with the subject key extension value matching the responder key",
361 signingCert.getSubjectDN().getName());
366 subjectKeyIdentifier =
new JcaX509ExtensionUtils().createSubjectKeyIdentifier(tempCert.getPublicKey());
367 if (responderSubjectKey.equals(subjectKeyIdentifier)) {
368 signingCert = tempCert;
369 logger.log(Level.INFO,
"Found a certificate \"{0}\" with the subject key matching the OCSP responder key", signingCert.getSubjectDN().getName());
373 }
catch (CertificateException e) {
374 logger.log(Level.FINE, e.getMessage());
379 if (signingCert != null) {
380 if (signingCert.equals(issuerCertificate)) {
381 logger.log(Level.INFO,
"OCSP response is signed by the target\'s Issuing CA");
382 }
else if (responderCertificate != null && signingCert.equals(responderCertificate)) {
386 logger.log(Level.INFO,
"OCSP response is signed by an authorized responder certificate");
392 if (!signingCert.getIssuerX500Principal().equals(issuerCertificate.getSubjectX500Principal())) {
393 logger.log(Level.INFO,
"Signer certificate's Issuer: {0}\nIssuer certificate's Subject: {1}",
394 new Object[] {signingCert.getIssuerX500Principal().getName(), issuerCertificate.getSubjectX500Principal().getName()});
395 throw new CertPathValidatorException(
"Responder\'s certificate is not authorized to sign OCSP responses");
398 List<String> purposes = signingCert.getExtendedKeyUsage();
399 if (purposes != null && !purposes.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) {
400 logger.log(Level.INFO,
"OCSPSigning extended usage is not set");
401 throw new CertPathValidatorException(
"Responder\'s certificate not valid for signing OCSP responses");
403 }
catch (CertificateParsingException e) {
404 logger.log(Level.FINE,
"Failed to get certificate's extended key usage extension\n{0}", e.getMessage());
407 signingCert.checkValidity();
409 signingCert.checkValidity(date);
412 Extension noOCSPCheck =
new JcaX509CertificateHolder(signingCert).getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck);
415 logger.log(Level.INFO,
"OCSP no-check extension is {0} present", noOCSPCheck == null ?
"not" :
"");
416 }
catch (CertificateEncodingException e) {
417 logger.log(Level.FINE,
"Certificate encoding exception: {0}", e.getMessage());
421 signingCert.verify(issuerCertificate.getPublicKey());
422 logger.log(Level.INFO,
"OCSP response is signed by an Authorized Responder");
424 }
catch (GeneralSecurityException ex) {
429 if (signingCert == null) {
430 throw new CertPathValidatorException(
"Unable to verify OCSP Response\'s signature");
433 throw new CertPathValidatorException(
"Error verifying OCSP Response\'s signature");
435 Extension responseNonce = basicOcspResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
436 if (responseNonce != null && requestNonce != null && !Arrays.equals(requestNonce, responseNonce.getExtnValue().getOctets())) {
437 throw new CertPathValidatorException(
"Nonces do not match.");
442 long current = date == null ? System.currentTimeMillis() : date.getTime();
443 Date stop =
new Date(current + (
long)
TIME_SKEW);
444 Date start =
new Date(current - (
long)
TIME_SKEW);
446 Iterator<SingleResp> iter = Arrays.asList(basicOcspResponse.getResponses()).iterator();
447 SingleResp singleRes = null;
449 if (!iter.hasNext()) {
452 singleRes = iter.next();
454 while (!stop.before(singleRes.getThisUpdate()) &&
455 !start.after(singleRes.getNextUpdate() != null ? singleRes.getNextUpdate() : singleRes.getThisUpdate()));
457 throw new CertPathValidatorException(
"Response is unreliable: its validity interval is out-of-date");
static final Logger logger
Definition: OCSPUtils.java:76
static boolean verifySignature(BasicOCSPResp basicOcspResponse, X509Certificate cert)
Definition: OCSPUtils.java:463
static final int TIME_SKEW
Definition: OCSPUtils.java:79