List of usage examples for org.bouncycastle.cert.ocsp BasicOCSPResp getResponses
public SingleResp[] getResponses()
From source file:org.jruby.ext.openssl.OCSPBasicResponse.java
License:Common Public License
private boolean checkIssuer(BasicOCSPResp basicOCSPResp, IRubyObject chain) throws IOException { boolean ret = false; if (((RubyArray) chain).size() <= 0) return false; List<SingleResp> singleResponses = Arrays.asList(basicOCSPResp.getResponses()); CertificateID certId = checkCertIds(singleResponses); X509Cert signer = (X509Cert) ((RubyArray) chain).first(); if (((RubyArray) chain).size() > 1) { X509Cert signerCA = (X509Cert) ((RubyArray) chain).entry(1); if (matchIssuerId(signerCA, certId, singleResponses)) { return checkDelegated(signerCA); }//from w w w.j a v a 2s.c o m } else { ret = matchIssuerId(signer, certId, singleResponses); } return ret; }
From source file:org.keycloak.common.util.OCSPUtils.java
License:Apache License
private static OCSPRevocationStatus processBasicOCSPResponse(X509Certificate issuerCertificate, X509Certificate responderCertificate, Date date, JcaCertificateID certificateID, BigInteger nounce, BasicOCSPResp basicOcspResponse) throws OCSPException, NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException { SingleResp expectedResponse = null;/*from ww w .j a v a2 s .c o m*/ for (SingleResp singleResponse : basicOcspResponse.getResponses()) { if (compareCertIDs(certificateID, singleResponse.getCertID())) { expectedResponse = singleResponse; break; } } if (expectedResponse != null) { verifyResponse(basicOcspResponse, issuerCertificate, responderCertificate, nounce.toByteArray(), date); return singleResponseToRevocationStatus(expectedResponse); } else { throw new CertPathValidatorException( "OCSP response does not include a response for a certificate supplied in the OCSP request"); } }
From source file:org.keycloak.common.util.OCSPUtils.java
License:Apache License
private static void verifyResponse(BasicOCSPResp basicOcspResponse, X509Certificate issuerCertificate, X509Certificate responderCertificate, byte[] requestNonce, Date date) throws NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException { List<X509CertificateHolder> certs = new ArrayList<>(Arrays.asList(basicOcspResponse.getCerts())); X509Certificate signingCert = null; try {/*w w w . j a v a 2 s . com*/ certs.add(new JcaX509CertificateHolder(issuerCertificate)); if (responderCertificate != null) { certs.add(new JcaX509CertificateHolder(responderCertificate)); } } catch (CertificateEncodingException e) { e.printStackTrace(); } if (certs.size() > 0) { X500Name responderName = basicOcspResponse.getResponderId().toASN1Primitive().getName(); byte[] responderKey = basicOcspResponse.getResponderId().toASN1Primitive().getKeyHash(); if (responderName != null) { logger.log(Level.INFO, "Responder Name: {0}", responderName.toString()); for (X509CertificateHolder certHolder : certs) { try { X509Certificate tempCert = new JcaX509CertificateConverter().setProvider("BC") .getCertificate(certHolder); X500Name respName = new X500Name(tempCert.getSubjectX500Principal().getName()); if (responderName.equals(respName)) { signingCert = tempCert; logger.log(Level.INFO, "Found a certificate whose principal \"{0}\" matches the responder name \"{1}\"", new Object[] { tempCert.getSubjectDN().getName(), responderName.toString() }); break; } } catch (CertificateException e) { logger.log(Level.FINE, e.getMessage()); } } } else if (responderKey != null) { SubjectKeyIdentifier responderSubjectKey = new SubjectKeyIdentifier(responderKey); logger.log(Level.INFO, "Responder Key: {0}", Arrays.toString(responderKey)); for (X509CertificateHolder certHolder : certs) { try { X509Certificate tempCert = new JcaX509CertificateConverter().setProvider("BC") .getCertificate(certHolder); SubjectKeyIdentifier subjectKeyIdentifier = null; if (certHolder.getExtensions() != null) { subjectKeyIdentifier = SubjectKeyIdentifier.fromExtensions(certHolder.getExtensions()); } if (subjectKeyIdentifier != null) { logger.log(Level.INFO, "Certificate: {0}\nSubject Key Id: {1}", new Object[] { tempCert.getSubjectDN().getName(), Arrays.toString(subjectKeyIdentifier.getKeyIdentifier()) }); } if (subjectKeyIdentifier != null && responderSubjectKey.equals(subjectKeyIdentifier)) { signingCert = tempCert; logger.log(Level.INFO, "Found a signer certificate \"{0}\" with the subject key extension value matching the responder key", signingCert.getSubjectDN().getName()); break; } subjectKeyIdentifier = new JcaX509ExtensionUtils() .createSubjectKeyIdentifier(tempCert.getPublicKey()); if (responderSubjectKey.equals(subjectKeyIdentifier)) { signingCert = tempCert; logger.log(Level.INFO, "Found a certificate \"{0}\" with the subject key matching the OCSP responder key", signingCert.getSubjectDN().getName()); break; } } catch (CertificateException e) { logger.log(Level.FINE, e.getMessage()); } } } } if (signingCert != null) { if (signingCert.equals(issuerCertificate)) { logger.log(Level.INFO, "OCSP response is signed by the target''s Issuing CA"); } else if (responderCertificate != null && signingCert.equals(responderCertificate)) { // https://www.ietf.org/rfc/rfc2560.txt // 2.6 OCSP Signature Authority Delegation // - The responder certificate is issued to the responder by CA logger.log(Level.INFO, "OCSP response is signed by an authorized responder certificate"); } else { // 4.2.2.2 Authorized Responders // 3. Includes a value of id-ad-ocspSigning in an ExtendedKeyUsage // extension and is issued by the CA that issued the certificate in // question." if (!signingCert.getIssuerX500Principal().equals(issuerCertificate.getSubjectX500Principal())) { logger.log(Level.INFO, "Signer certificate''s Issuer: {0}\nIssuer certificate''s Subject: {1}", new Object[] { signingCert.getIssuerX500Principal().getName(), issuerCertificate.getSubjectX500Principal().getName() }); throw new CertPathValidatorException( "Responder\'s certificate is not authorized to sign OCSP responses"); } try { List<String> purposes = signingCert.getExtendedKeyUsage(); if (purposes != null && !purposes.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) { logger.log(Level.INFO, "OCSPSigning extended usage is not set"); throw new CertPathValidatorException( "Responder\'s certificate not valid for signing OCSP responses"); } } catch (CertificateParsingException e) { logger.log(Level.FINE, "Failed to get certificate''s extended key usage extension\n{0}", e.getMessage()); } if (date == null) { signingCert.checkValidity(); } else { signingCert.checkValidity(date); } try { Extension noOCSPCheck = new JcaX509CertificateHolder(signingCert) .getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck); // TODO If the extension is present, the OCSP client can trust the // responder's certificate for the lifetime of the certificate. logger.log(Level.INFO, "OCSP no-check extension is {0} present", noOCSPCheck == null ? "not" : ""); } catch (CertificateEncodingException e) { logger.log(Level.FINE, "Certificate encoding exception: {0}", e.getMessage()); } try { signingCert.verify(issuerCertificate.getPublicKey()); logger.log(Level.INFO, "OCSP response is signed by an Authorized Responder"); } catch (GeneralSecurityException ex) { signingCert = null; } } } if (signingCert == null) { throw new CertPathValidatorException("Unable to verify OCSP Response\'s signature"); } else { if (!verifySignature(basicOcspResponse, signingCert)) { throw new CertPathValidatorException("Error verifying OCSP Response\'s signature"); } else { Extension responseNonce = basicOcspResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); if (responseNonce != null && requestNonce != null && !Arrays.equals(requestNonce, responseNonce.getExtnValue().getOctets())) { throw new CertPathValidatorException("Nonces do not match."); } else { // See Sun's OCSP implementation. // https://www.ietf.org/rfc/rfc2560.txt, if nextUpdate is not set, // the responder is indicating that newer update is avilable all the time long current = date == null ? System.currentTimeMillis() : date.getTime(); Date stop = new Date(current + (long) TIME_SKEW); Date start = new Date(current - (long) TIME_SKEW); Iterator<SingleResp> iter = Arrays.asList(basicOcspResponse.getResponses()).iterator(); SingleResp singleRes = null; do { if (!iter.hasNext()) { return; } singleRes = iter.next(); } while (!stop.before(singleRes.getThisUpdate()) && !start.after(singleRes.getNextUpdate() != null ? singleRes.getNextUpdate() : singleRes.getThisUpdate())); throw new CertPathValidatorException( "Response is unreliable: its validity interval is out-of-date"); } } } }
From source file:org.poreid.verify.ocsp.OCSPClient.java
License:Open Source License
public CertStatus getCertificateStatus() throws OCSPValidationException { try {/* ww w . java2 s .c o m*/ if (null == url) { throw new OCSPValidationException("Certificado no tem validao por OCSP"); } byte[] encodedOcspRequest = generateOCSPRequest(issuer, certificate.getSerialNumber()).getEncoded(); HttpURLConnection httpConnection; httpConnection = (HttpURLConnection) url.openConnection(); httpConnection.setRequestProperty("Content-Type", "application/ocsp-request"); httpConnection.setRequestProperty("Accept", "application/ocsp-response"); httpConnection.setDoOutput(true); try (DataOutputStream dataOut = new DataOutputStream( new BufferedOutputStream(httpConnection.getOutputStream()))) { dataOut.write(encodedOcspRequest); dataOut.flush(); } InputStream in = (InputStream) httpConnection.getContent(); if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new OCSPValidationException( "Cdigo HTTP recebido != 200 [" + httpConnection.getResponseCode() + "]"); } OCSPResp ocspResponse = new OCSPResp(in); BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject(); byte[] receivedNonce = basicResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce).getExtnId() .getEncoded(); if (!Arrays.equals(receivedNonce, sentNonce)) { throw new OCSPValidationException("Nonce na resposta ocsp no coincide com nonce do pedido ocsp"); } X509CertificateHolder certHolder = basicResponse.getCerts()[0]; if (!basicResponse .isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(issuer))) { if (!certHolder.isValidOn(Date.from(Instant.now()))) { throw new OCSPValidationException("Certificado no vlido na data atual"); } // Certificado tem de ter uma Key Purpose ID for authorized responders if (!ExtendedKeyUsage.fromExtensions(certHolder.getExtensions()) .hasKeyPurposeId(KeyPurposeId.id_kp_OCSPSigning)) { throw new OCSPValidationException( "Certificado no contm extenso necessria (id_kp_OCSPSigning)"); } // Certificado tem de ser emitido pela mesma CA do certificado que estamos a verificar if (!certHolder.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(issuer))) { throw new OCSPValidationException("Certificado no assinado pelo mesmo issuer"); } // Validar assinatura na resposta ocsp if (!basicResponse.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(certHolder))) { throw new OCSPValidationException("No foi possivel validar resposta ocsp"); } } else { if (!certHolder.isValidOn(Date.from(Instant.now()))) { throw new OCSPValidationException("Certificado no vlido na data atual"); } } // Politica de Certificados do SCEE if (null == certHolder.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck).getExtnId()) { throw new OCSPValidationException( "Extenso id_pkix_ocsp_nocheck no encontrada no certificado (Politica de Certificados do SCEE)"); } SingleResp[] responses = basicResponse.getResponses(); if (responses[0].getCertID().getSerialNumber().equals(certificate.getSerialNumber())) { CertificateStatus status = responses[0].getCertStatus(); if (status == CertificateStatus.GOOD) { return CertStatus.GOOD; } else { if (status instanceof RevokedStatus) { revokedStatus = (RevokedStatus) status; return CertStatus.REVOKED; } else { return CertStatus.UNKNOWN; } } } else { throw new OCSPValidationException( "Nmero de srie do certificado na resposta ocsp no coincide com nmero de srie do certificado"); } } catch (CertificateEncodingException | OperatorCreationException | OCSPException | IOException ex) { throw new OCSPValidationException("No foi possivel efetuar a validao atravs de OCSP (" + certificate.getSubjectX500Principal().getName() + ")", ex); } catch (CertException | CertificateException ex) { throw new OCSPValidationException("No foi possivel efetuar a validao atravs de OCSP (" + certificate.getSubjectX500Principal().getName() + ")", ex); } }
From source file:org.signserver.module.xades.validator.AbstractCustomCertPathChecker.java
License:Open Source License
/** * Parses received response bytes to form basic ocsp response object and verifies ocsp response * If returns , ocsp response is successfully verified, otherwise throws exception detailing problem * /*from w ww.j a v a 2 s. c o m*/ * @param x509Cert - certificate originally passed to validator for validation * @param ocspresp - ocsp response received from ocsp responder * @throws OCSPException * @throws NoSuchProviderException * @throws IOException * @throws CertStoreException * @throws NoSuchAlgorithmException * @throws SignServerException * @throws CertificateParsingException * @throws CryptoTokenOfflineException * @throws IllegalRequestException */ protected void parseAndVerifyOCSPResponse(X509Certificate x509Cert, OCSPResp ocspresp, X509Certificate cACert) throws NoSuchProviderException, OCSPException, NoSuchAlgorithmException, CertStoreException, IOException, SignServerException, CertificateParsingException, IllegalRequestException, CryptoTokenOfflineException, OperatorCreationException, CertificateEncodingException { if (ocspresp.getStatus() != OCSPRespStatus.SUCCESSFUL) { throw new SignServerException( "Unexpected ocsp response status. Response Status Received : " + ocspresp.getStatus()); } // we currently support only basic ocsp response BasicOCSPResp basicOCSPResponse = (BasicOCSPResp) ocspresp.getResponseObject(); if (basicOCSPResponse == null) { throw new SignServerException( "Could not construct BasicOCSPResp object from response. Only BasicOCSPResponse as defined in RFC 2560 is supported."); } //OCSP response might be signed by CA issuing the certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate ocspRespSignerCertificate = null; //first check if CA issuing certificate signed the response //since it is expected to be the most common case if (basicOCSPResponse.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(cACert.getPublicKey()))) { ocspRespSignerCertificate = cACert; } //if CA did not sign the ocsp response, look for authorized ocsp responses from properties or from certificate chain received with response if (ocspRespSignerCertificate == null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromOCSPResponse(basicOCSPResponse); //could not find the certificate signing the OCSP response in the ocsp response if (ocspRespSignerCertificate == null) { throw new SignServerException( "Certificate signing the ocsp response is not found in ocsp response's certificate chain received and is not signed by CA issuing certificate"); } } LOG.debug("OCSP response signed by : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, in which case we do not validateUsingCRL (perform revocation check on ) ocsp certs for lifetime of certificate // using CRL RFC 2560 sect 4.2.2.2.1 // TODO : RFC States the extension value should be NULL, so maybe bare existence of the extension is not sufficient ?? if (ocspRespSignerCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()) != null) { //check if lifetime of certificate is ok try { ocspRespSignerCertificate.checkValidity(); } catch (CertificateExpiredException e) { throw new SignServerException( "Certificate signing the ocsp response has expired. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } catch (CertificateNotYetValidException e) { throw new SignServerException( "Certificate signing the ocsp response is not yet valid. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } } else if (ocspRespSignerCertificate.equals(cACert)) { LOG.debug("Not performing revocation check on issuer certificate"); } else { // TODO: Could try to use CRL if available throw new SignServerException("Revokation check of OCSP certificate not yet supported"); } //get the response we requested for for (SingleResp singleResponse : basicOCSPResponse.getResponses()) { if (singleResponse.getCertID().getSerialNumber().equals(x509Cert.getSerialNumber())) { //found our response //check if response is OK, and if not throw OCSPStatusNotGoodException if (singleResponse.getCertStatus() != null) { throw new OCSPStatusNotGoodException( "Responce for queried certificate is not good. Certificate status returned : " + singleResponse.getCertStatus(), singleResponse.getCertStatus()); } //check the dates ThisUpdate and NextUpdate RFC 2560 sect : 4.2.2.1 if (singleResponse.getNextUpdate() != null && (new Date()).compareTo(singleResponse.getNextUpdate()) >= 0) { throw new SignServerException( "Unreliable response received. Response reported a nextupdate as : " + singleResponse.getNextUpdate().toString() + " which is earlier than current date."); } if (singleResponse.getThisUpdate() != null && (new Date()).compareTo(singleResponse.getThisUpdate()) <= 0) { throw new SignServerException( "Unreliable response received. Response reported a thisupdate as : " + singleResponse.getThisUpdate().toString() + " which is earlier than current date."); } break; } } }
From source file:org.signserver.validationservice.server.OCSPPathChecker.java
License:Open Source License
/** * Parses received response bytes to form basic ocsp response object and verifies ocsp response * If returns , ocsp response is successfully verified, otherwise throws exception detailing problem * /*from ww w . j av a 2 s.c o m*/ * @param x509Cert - certificate originally passed to validator for validation * @param derocspresponse - der formatted ocsp response received from ocsp responder * @throws OCSPException * @throws NoSuchProviderException * @throws IOException * @throws CertStoreException * @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException * @throws SignServerException * @throws CertificateParsingException * @throws CryptoTokenOfflineException * @throws IllegalRequestException */ protected void parseAndVerifyOCSPResponse(X509Certificate x509Cert, byte[] derocspresponse) throws NoSuchProviderException, OCSPException, NoSuchAlgorithmException, CertStoreException, IOException, SignServerException, CertificateParsingException, IllegalRequestException, CryptoTokenOfflineException, OperatorCreationException, CertificateEncodingException { //parse received ocsp response OCSPResp ocspresp = new OCSPResp(derocspresponse); if (ocspresp.getStatus() != OCSPRespStatus.SUCCESSFUL) { throw new SignServerException( "Unexpected ocsp response status. Response Status Received : " + ocspresp.getStatus()); } // we currently support only basic ocsp response BasicOCSPResp basicOCSPResponse = (BasicOCSPResp) ocspresp.getResponseObject(); if (basicOCSPResponse == null) { throw new SignServerException( "Could not construct BasicOCSPResp object from response. Only BasicOCSPResponse as defined in RFC 2560 is supported."); } //OCSP response might be signed by CA issuing the certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate ocspRespSignerCertificate = null; //first check if CA issuing certificate signed the response //since it is expected to be the most common case if (basicOCSPResponse.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(cACert.getPublicKey()))) { ocspRespSignerCertificate = cACert; } //if CA did not sign the ocsp response, look for authorized ocsp responses from properties or from certificate chain received with response if (ocspRespSignerCertificate == null) { log.debug("OCSP Response is not signed by issuing CA. Looking for authorized responders"); if (basicOCSPResponse.getCerts() == null) { log.debug( "OCSP Response does not contain certificate chain, trying to verify response using one of configured authorized ocsp responders"); //certificate chain is not present in response received //try to verify using one of the configured AuthorizedOCSPResponderCerts ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromProperties(basicOCSPResponse); if (ocspRespSignerCertificate == null) { throw new SignServerException( "OCSP Response does not contain certificate chain, and response is not signed by any of the configured Authorized OCSP Responders or CA issuing certificate."); } } else { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromOCSPResponse( basicOCSPResponse); //could not find the certificate signing the OCSP response in the ocsp response if (ocspRespSignerCertificate == null) { throw new SignServerException( "Certificate signing the ocsp response is not found in ocsp response's certificate chain received and is not signed by CA issuing certificate"); } } } log.debug("OCSP response signed by : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, in which case we do not validate (perform revocation check on ) ocsp certs for lifetime of certificate // using CRL RFC 2560 sect 4.2.2.2.1 // TODO : RFC States the extension value should be NULL, so maybe bare existence of the extension is not sufficient ?? if (ocspRespSignerCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()) != null) { //check if lifetime of certificate is ok try { ocspRespSignerCertificate.checkValidity(); } catch (CertificateExpiredException e) { throw new SignServerException( "Certificate signing the ocsp response has expired. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } catch (CertificateNotYetValidException e) { throw new SignServerException( "Certificate signing the ocsp response is not yet valid. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } } else { // check if CDP exists in ocsp signers certificate // TODO : ?? add property for issuer whether to accept the OCSP response if the CDPs are not available (or use preconfigured CRLs) on signing certificate CRL RFC 2560 sect 4.2.2.2.1 if (CertTools.getCrlDistributionPoint(ocspRespSignerCertificate) == null) { throw new SignServerException( "CRL Distribution Point extension missing in ocsp signer's certificate."); } //verify certificate using CRL Validator //TODO : refactor Validators to follow factory pattern (discuss) CRLValidator crlValidator = new CRLValidator(); Validation valresult = crlValidator.validate(ocspRespSignerCertificate, this.props); if (valresult.getStatus() != Validation.Status.VALID) { throw new SignServerException( "Validation of ocsp signer's certificate failed. Status message received : " + valresult.getStatusMessage()); } } //get the response we requested for for (SingleResp singleResponse : basicOCSPResponse.getResponses()) { if (singleResponse.getCertID().getSerialNumber().equals(x509Cert.getSerialNumber())) { //found our response //check if response is OK, and if not throw OCSPStatusNotGoodException if (singleResponse.getCertStatus() != null) { throw new OCSPStatusNotGoodException( "Responce for queried certificate is not good. Certificate status returned : " + singleResponse.getCertStatus(), singleResponse.getCertStatus()); } //check the dates ThisUpdate and NextUpdate RFC 2560 sect : 4.2.2.1 if (singleResponse.getNextUpdate() != null && (new Date()).compareTo(singleResponse.getNextUpdate()) >= 0) { throw new SignServerException( "Unreliable response received. Response reported a nextupdate as : " + singleResponse.getNextUpdate().toString() + " which is earlier than current date."); } if (singleResponse.getThisUpdate() != null && (new Date()).compareTo(singleResponse.getThisUpdate()) <= 0) { throw new SignServerException( "Unreliable response received. Response reported a thisupdate as : " + singleResponse.getThisUpdate().toString() + " which is earlier than current date."); } break; } } }
From source file:org.xdi.oxauth.cert.validation.OCSPCertificateVerifier.java
License:MIT License
@Override public ValidationStatus validate(X509Certificate certificate, List<X509Certificate> issuers, Date validationDate) {// w ww. j a v a 2 s. c om X509Certificate issuer = issuers.get(0); ValidationStatus status = new ValidationStatus(certificate, issuer, validationDate, ValidatorSourceType.OCSP, CertificateValidity.UNKNOWN); try { Principal subjectX500Principal = certificate.getSubjectX500Principal(); String ocspUrl = getOCSPUrl(certificate); if (ocspUrl == null) { log.error("OCSP URL for '" + subjectX500Principal + "' is empty"); return status; } log.debug("OCSP URL for '" + subjectX500Principal + "' is '" + ocspUrl + "'"); DigestCalculator digestCalculator = new JcaDigestCalculatorProviderBuilder().build() .get(CertificateID.HASH_SHA1); CertificateID certificateId = new CertificateID(digestCalculator, new JcaX509CertificateHolder(certificate), certificate.getSerialNumber()); // Generate OCSP request OCSPReq ocspReq = generateOCSPRequest(certificateId); // Get OCSP response from server OCSPResp ocspResp = requestOCSPResponse(ocspUrl, ocspReq); if (ocspResp.getStatus() != OCSPRespBuilder.SUCCESSFUL) { log.error("OCSP response is invalid!"); status.setValidity(CertificateValidity.INVALID); return status; } boolean foundResponse = false; BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); SingleResp[] singleResps = basicOCSPResp.getResponses(); for (SingleResp singleResp : singleResps) { CertificateID responseCertificateId = singleResp.getCertID(); if (!certificateId.equals(responseCertificateId)) { continue; } foundResponse = true; log.debug("OCSP validationDate: " + validationDate); log.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); log.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); status.setRevocationObjectIssuingTime(basicOCSPResp.getProducedAt()); Object certStatus = singleResp.getCertStatus(); if (certStatus == CertificateStatus.GOOD) { log.debug("OCSP status is valid for '" + certificate.getSubjectX500Principal() + "'"); status.setValidity(CertificateValidity.VALID); } else { if (singleResp.getCertStatus() instanceof RevokedStatus) { log.warn("OCSP status is revoked for: " + subjectX500Principal); if (validationDate .before(((RevokedStatus) singleResp.getCertStatus()).getRevocationTime())) { log.warn("OCSP revocation time after the validation date, the certificate '" + subjectX500Principal + "' was valid at " + validationDate); status.setValidity(CertificateValidity.VALID); } else { Date revocationDate = ((RevokedStatus) singleResp.getCertStatus()).getRevocationTime(); log.info("OCSP for certificate '" + subjectX500Principal + "' is revoked since " + revocationDate); status.setRevocationDate(revocationDate); status.setRevocationObjectIssuingTime(singleResp.getThisUpdate()); status.setValidity(CertificateValidity.REVOKED); } } } } if (!foundResponse) { log.error("There is no matching OCSP response entries"); } } catch (Exception ex) { log.error("OCSP exception: ", ex); } return status; }
From source file:org.xipki.ocsp.client.impl.AbstractOCSPRequestor.java
License:Open Source License
@Override public OCSPResp ask(final X509Certificate issuerCert, final BigInteger[] serialNumbers, final URL responderUrl, final RequestOptions requestOptions, final RequestResponseDebug debug) throws OCSPResponseException, OCSPRequestorException { if (requestOptions == null) { throw new IllegalArgumentException("requestOptions could not be null"); }//from ww w. ja v a 2 s. c o m byte[] nonce = null; if (requestOptions.isUseNonce()) { nonce = nextNonce(requestOptions.getNonceLen()); } OCSPReq ocspReq = buildRequest(issuerCert, serialNumbers, nonce, requestOptions); byte[] encodedReq; try { encodedReq = ocspReq.getEncoded(); } catch (IOException e) { throw new OCSPRequestorException("could not encode OCSP request: " + e.getMessage(), e); } RequestResponsePair msgPair = null; if (debug != null) { msgPair = new RequestResponsePair(); debug.add(msgPair); msgPair.setRequest(encodedReq); } byte[] encodedResp; try { encodedResp = send(encodedReq, responderUrl, requestOptions); } catch (IOException e) { throw new ResponderUnreachableException("IOException: " + e.getMessage(), e); } if (debug != null) { msgPair.setRequest(encodedResp); } OCSPResp ocspResp; try { ocspResp = new OCSPResp(encodedResp); } catch (IOException e) { throw new InvalidOCSPResponseException("IOException: " + e.getMessage(), e); } Object respObject; try { respObject = ocspResp.getResponseObject(); } catch (OCSPException e) { throw new InvalidOCSPResponseException("responseObject is invalid"); } if (ocspResp.getStatus() != 0) { return ocspResp; } if (respObject instanceof BasicOCSPResp == false) { return ocspResp; } BasicOCSPResp basicOCSPResp = (BasicOCSPResp) respObject; if (nonce != null) { Extension nonceExtn = basicOCSPResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); if (nonceExtn == null) { throw new OCSPNonceUnmatchedException(nonce, null); } byte[] receivedNonce = nonceExtn.getExtnValue().getOctets(); if (Arrays.equals(nonce, receivedNonce) == false) { throw new OCSPNonceUnmatchedException(nonce, receivedNonce); } } SingleResp[] singleResponses = basicOCSPResp.getResponses(); final int countSingleResponses = singleResponses == null ? 0 : singleResponses.length; if (countSingleResponses != serialNumbers.length) { StringBuilder sb = new StringBuilder(100); sb.append("response with ").append(countSingleResponses).append(" singleRessponse"); if (countSingleResponses > 1) { sb.append("s"); } sb.append(" is returned, expected is ").append(serialNumbers.length); throw new OCSPTargetUnmatchedException(sb.toString()); } CertificateID certID = ocspReq.getRequestList()[0].getCertID(); ASN1ObjectIdentifier issuerHashAlg = certID.getHashAlgOID(); byte[] issuerKeyHash = certID.getIssuerKeyHash(); byte[] issuerNameHash = certID.getIssuerNameHash(); if (serialNumbers.length == 1) { SingleResp m = singleResponses[0]; CertificateID cid = m.getCertID(); boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID()) && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash()) && Arrays.equals(issuerNameHash, cid.getIssuerNameHash()); if (issuerMatch == false) { throw new OCSPTargetUnmatchedException("the issuer is not requested"); } BigInteger serialNumber = cid.getSerialNumber(); if (serialNumbers[0].equals(serialNumber) == false) { throw new OCSPTargetUnmatchedException("the serialNumber is not requested"); } } else { List<BigInteger> tmpSerials1 = Arrays.asList(serialNumbers); List<BigInteger> tmpSerials2 = new ArrayList<>(tmpSerials1); for (int i = 0; i < singleResponses.length; i++) { SingleResp m = singleResponses[i]; CertificateID cid = m.getCertID(); boolean issuerMatch = issuerHashAlg.equals(cid.getHashAlgOID()) && Arrays.equals(issuerKeyHash, cid.getIssuerKeyHash()) && Arrays.equals(issuerNameHash, cid.getIssuerNameHash()); if (issuerMatch == false) { throw new OCSPTargetUnmatchedException( "the issuer specified in singleResponse[" + i + "] is not requested"); } BigInteger serialNumber = cid.getSerialNumber(); if (tmpSerials2.remove(serialNumber) == false) { if (tmpSerials1.contains(serialNumber)) { throw new OCSPTargetUnmatchedException( "serialNumber " + serialNumber + "is contained in at least two singleResponses"); } else { throw new OCSPTargetUnmatchedException( "the serialNumber specified in singleResponse[" + i + "] is not requested"); } } } } return ocspResp; }
From source file:org.xipki.ocsp.client.shell.OCSPStatusCommand.java
License:Open Source License
@Override protected Object processResponse(final OCSPResp response, final X509Certificate respIssuer, final X509Certificate issuer, final List<BigInteger> serialNumbers, final Map<BigInteger, byte[]> encodedCerts) throws Exception { BasicOCSPResp basicResp = OCSPUtils.extractBasicOCSPResp(response); boolean extendedRevoke = basicResp.getExtension(OCSPRequestor.id_pkix_ocsp_extendedRevoke) != null; SingleResp[] singleResponses = basicResp.getResponses(); int n = singleResponses == null ? 0 : singleResponses.length; if (n == 0) { throw new CmdFailure("received no status from server"); }/* ww w . j av a 2 s .co m*/ if (n != serialNumbers.size()) { throw new CmdFailure("received status with " + n + " single responses from server, but " + serialNumbers.size() + " were requested"); } Date[] thisUpdates = new Date[n]; for (int i = 0; i < n; i++) { thisUpdates[i] = singleResponses[i].getThisUpdate(); } // check the signature if available if (null == basicResp.getSignature()) { out("response is not signed"); } else { X509CertificateHolder[] responderCerts = basicResp.getCerts(); if (responderCerts == null || responderCerts.length < 1) { throw new CmdFailure("no responder certificate is contained in the response"); } X509CertificateHolder respSigner = responderCerts[0]; boolean validOn = true; for (Date thisUpdate : thisUpdates) { validOn = respSigner.isValidOn(thisUpdate); if (validOn == false) { throw new CmdFailure("responder certificate is not valid on " + thisUpdate); } } if (validOn) { PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo()); ContentVerifierProvider cvp = KeyUtil.getContentVerifierProvider(responderPubKey); boolean sigValid = basicResp.isSignatureValid(cvp); if (sigValid == false) { throw new CmdFailure("response is equipped with invalid signature"); } // verify the OCSPResponse signer if (respIssuer != null) { boolean certValid = true; X509Certificate jceRespSigner = new X509CertificateObject(respSigner.toASN1Structure()); if (X509Util.issues(respIssuer, jceRespSigner)) { try { jceRespSigner.verify(respIssuer.getPublicKey()); } catch (SignatureException e) { certValid = false; } } if (certValid == false) { throw new CmdFailure( "response is equipped with valid signature but the OCSP signer is not trusted"); } } else { out("response is equipped with valid signature"); } } if (verbose.booleanValue()) { out("responder is " + X509Util.getRFC4519Name(responderCerts[0].getSubject())); } } for (int i = 0; i < n; i++) { if (n > 1) { out("---------------------------- " + i + " ----------------------------"); } SingleResp singleResp = singleResponses[i]; BigInteger serialNumber = singleResp.getCertID().getSerialNumber(); CertificateStatus singleCertStatus = singleResp.getCertStatus(); String status; if (singleCertStatus == null) { status = "good"; } else if (singleCertStatus instanceof RevokedStatus) { RevokedStatus revStatus = (RevokedStatus) singleCertStatus; Date revTime = revStatus.getRevocationTime(); Date invTime = null; Extension ext = singleResp.getExtension(Extension.invalidityDate); if (ext != null) { invTime = ASN1GeneralizedTime.getInstance(ext.getParsedValue()).getDate(); } if (revStatus.hasRevocationReason()) { int reason = revStatus.getRevocationReason(); if (extendedRevoke && reason == CRLReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) { status = "unknown (RFC6960)"; } else { StringBuilder sb = new StringBuilder("revoked, reason = "); sb.append(CRLReason.forReasonCode(reason).getDescription()); sb.append(", revocationTime = "); sb.append(revTime); if (invTime != null) { sb.append(", invalidityTime = "); sb.append(invTime); } status = sb.toString(); } } else { status = "revoked, no reason, revocationTime = " + revTime; } } else if (singleCertStatus instanceof UnknownStatus) { status = "unknown (RFC2560)"; } else { status = "ERROR"; } StringBuilder msg = new StringBuilder(); msg.append("serialNumber: ").append(serialNumber); msg.append("\nCertificate status: ").append(status); if (verbose.booleanValue()) { msg.append("\nthisUpdate: " + singleResp.getThisUpdate()); msg.append("\nnextUpdate: " + singleResp.getNextUpdate()); Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash); if (extension != null) { msg.append("\nCertHash is provided:\n"); ASN1Encodable extensionValue = extension.getParsedValue(); CertHash certHash = CertHash.getInstance(extensionValue); ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm(); byte[] hashValue = certHash.getCertificateHash(); msg.append("\tHash algo : ").append(hashAlgOid.getId()).append("\n"); msg.append("\tHash value: ").append(Hex.toHexString(hashValue)).append("\n"); if (encodedCerts != null) { byte[] encodedCert = encodedCerts.get(serialNumber); MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId()); byte[] expectedHashValue = md.digest(encodedCert); if (Arrays.equals(expectedHashValue, hashValue)) { msg.append("\tThis matches the requested certificate"); } else { msg.append("\tThis differs from the requested certificate"); } } } extension = singleResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff); if (extension != null) { ASN1Encodable extensionValue = extension.getParsedValue(); ASN1GeneralizedTime time = ASN1GeneralizedTime.getInstance(extensionValue); msg.append("\nArchive-CutOff: "); msg.append(time.getTimeString()); } AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID(); if (sigAlg == null) { msg.append(("\nresponse is not signed")); } else { String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg); if (sigAlgName == null) { sigAlgName = "unknown"; } msg.append("\nresponse is signed with ").append(sigAlgName); } // extensions msg.append("\nExtensions: "); List<?> extensionOIDs = basicResp.getExtensionOIDs(); if (extensionOIDs == null || extensionOIDs.size() == 0) { msg.append("-"); } else { int size = extensionOIDs.size(); for (int j = 0; j < size; j++) { ASN1ObjectIdentifier extensionOID = (ASN1ObjectIdentifier) extensionOIDs.get(j); String name = extensionOidNameMap.get(extensionOID); msg.append(name == null ? extensionOID.getId() : name); if (j != size - 1) { msg.append(", "); } } } } out(msg.toString()); } out(""); return null; }
From source file:org.xipki.ocsp.qa.impl.OcspQAImpl.java
License:Open Source License
@Override public ValidationResult checkOCSP(final OCSPResp response, final X509Certificate issuer, final List<BigInteger> serialNumbers, final Map<BigInteger, byte[]> encodedCerts, final OcspError expectedOcspError, final Map<BigInteger, OcspCertStatus> expectedOcspStatuses, final OcspResponseOption responseOption) { List<ValidationIssue> resultIssues = new LinkedList<ValidationIssue>(); int status = response.getStatus(); // Response status {/*from www.j av a 2 s . com*/ ValidationIssue issue = new ValidationIssue("OCSP.STATUS", "response.status"); resultIssues.add(issue); if (expectedOcspError != null) { if (status != expectedOcspError.getStatus()) { issue.setFailureMessage( "is '" + status + "', but expected '" + expectedOcspError.getStatus() + "'"); } } else { if (status != 0) { issue.setFailureMessage("is '" + status + "', but expected '0'"); } } } if (status != 0) { return new ValidationResult(resultIssues); } ValidationIssue encodingIssue = new ValidationIssue("OCSP.ENCODING", "response encoding"); resultIssues.add(encodingIssue); BasicOCSPResp basicResp; { try { basicResp = (BasicOCSPResp) response.getResponseObject(); } catch (OCSPException e) { encodingIssue.setFailureMessage(e.getMessage()); return new ValidationResult(resultIssues); } } SingleResp[] singleResponses = basicResp.getResponses(); { ValidationIssue issue = new ValidationIssue("OCSP.RESPONSES.NUM", "number of single responses"); resultIssues.add(issue); int n = singleResponses == null ? 0 : singleResponses.length; if (n == 0) { issue.setFailureMessage("received no status from server"); } else if (n != serialNumbers.size()) { issue.setFailureMessage("is '" + n + "', but expected '" + serialNumbers.size() + "'"); } if (issue.isFailed()) { return new ValidationResult(resultIssues); } } { boolean hasSignature = basicResp.getSignature() != null; { // check the signature if available ValidationIssue issue = new ValidationIssue("OCSP.SIG", "signature presence"); resultIssues.add(issue); if (hasSignature == false) { issue.setFailureMessage("response is not signed"); } } if (hasSignature) { { // signature algorithm ValidationIssue issue = new ValidationIssue("OCSP.SIG.ALG", "signature algorithm"); resultIssues.add(issue); String expectedSigalgo = responseOption.getSignatureAlgName(); if (expectedSigalgo != null) { AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID(); try { String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg); if (AlgorithmUtil.equalsAlgoName(sigAlgName, expectedSigalgo) == false) { issue.setFailureMessage( "is '" + sigAlgName + "', but expected '" + expectedSigalgo + "'"); } } catch (NoSuchAlgorithmException e) { issue.setFailureMessage("could not extract the signature algorithm"); } } } // signer certificate ValidationIssue sigSignerCertIssue = new ValidationIssue("OCSP.SIGNERCERT", "signer certificate"); resultIssues.add(sigSignerCertIssue); // signature validation ValidationIssue sigValIssue = new ValidationIssue("OCSP.SIG.VALIDATION", "signature validation"); resultIssues.add(sigValIssue); X509CertificateHolder[] responderCerts = basicResp.getCerts(); if (responderCerts == null || responderCerts.length < 1) { sigSignerCertIssue.setFailureMessage("No responder certificate is contained in the response"); sigValIssue.setFailureMessage("could not find certificate to validate signature"); } else { X509CertificateHolder respSigner = responderCerts[0]; ValidationIssue issue = new ValidationIssue("OCSP.SIGNERCERT.TRUST", "signer certificate validation"); resultIssues.add(issue); for (int i = 0; i < singleResponses.length; i++) { SingleResp singleResp = singleResponses[i]; if (respSigner.isValidOn(singleResp.getThisUpdate()) == false) { issue.setFailureMessage("responder certificate is not valid on the thisUpdate[ " + i + "]" + singleResp.getThisUpdate()); } } if (issue.isFailed() == false) { X509Certificate respIssuer = responseOption.getRespIssuer(); if (respIssuer != null) { X509Certificate jceRespSigner; try { jceRespSigner = new X509CertificateObject(respSigner.toASN1Structure()); if (X509Util.issues(respIssuer, jceRespSigner)) { jceRespSigner.verify(respIssuer.getPublicKey()); } else { issue.setFailureMessage("responder signer is not trusted"); } } catch (Exception e) { issue.setFailureMessage("responder signer is not trusted"); } } } try { PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo()); ContentVerifierProvider cvp = KeyUtil.getContentVerifierProvider(responderPubKey); boolean sigValid = basicResp.isSignatureValid(cvp); if (sigValid == false) { sigValIssue.setFailureMessage("signature is invalid"); } } catch (Exception e) { sigValIssue.setFailureMessage("error while validating signature"); } } } } { // nonce Extension nonceExtn = basicResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); resultIssues.add(checkOccurrence("OCSP.NONCE", nonceExtn, responseOption.getNonceOccurrence())); } boolean extendedRevoke = basicResp.getExtension(id_pkix_ocsp_extendedRevoke) != null; for (int i = 0; i < singleResponses.length; i++) { SingleResp singleResp = singleResponses[i]; BigInteger serialNumber = singleResp.getCertID().getSerialNumber(); OcspCertStatus expectedStatus = expectedOcspStatuses.get(serialNumber); byte[] encodedCert = null; if (encodedCerts != null) { encodedCert = encodedCerts.get(serialNumber); } List<ValidationIssue> issues = checkSingleCert(i, singleResp, expectedStatus, encodedCert, extendedRevoke, responseOption.getNextUpdateOccurrence(), responseOption.getCerthashOccurrence(), responseOption.getCerthashAlgId()); resultIssues.addAll(issues); } return new ValidationResult(resultIssues); }