List of usage examples for org.bouncycastle.cert.ocsp SingleResp getThisUpdate
public Date getThisUpdate()
From source file:be.fedict.trust.ocsp.OcspTrustLinker.java
License:Open Source License
@Override public TrustLinkerResult hasTrustLink(X509Certificate childCertificate, X509Certificate certificate, Date validationDate, RevocationData revocationData, AlgorithmPolicy algorithmPolicy) throws TrustLinkerResultException, Exception { URI ocspUri = getOcspUri(childCertificate); if (null == ocspUri) { return TrustLinkerResult.UNDECIDED; }//from w w w . j a v a 2 s. c o m LOG.debug("OCSP URI: " + ocspUri); OCSPResp ocspResp = this.ocspRepository.findOcspResponse(ocspUri, childCertificate, certificate, validationDate); if (null == ocspResp) { LOG.debug("OCSP response not found"); return TrustLinkerResult.UNDECIDED; } int ocspRespStatus = ocspResp.getStatus(); if (OCSPResponseStatus.SUCCESSFUL != ocspRespStatus) { LOG.debug("OCSP response status: " + ocspRespStatus); return TrustLinkerResult.UNDECIDED; } Object responseObject = ocspResp.getResponseObject(); BasicOCSPResp basicOCSPResp = (BasicOCSPResp) responseObject; X509CertificateHolder[] responseCertificates = basicOCSPResp.getCerts(); for (X509CertificateHolder responseCertificate : responseCertificates) { LOG.debug("OCSP response cert: " + responseCertificate.getSubject()); LOG.debug("OCSP response cert issuer: " + responseCertificate.getIssuer()); } algorithmPolicy.checkSignatureAlgorithm(basicOCSPResp.getSignatureAlgOID().getId(), validationDate); if (0 == responseCertificates.length) { /* * This means that the OCSP response has been signed by the issuing * CA itself. */ ContentVerifierProvider contentVerifierProvider = new JcaContentVerifierProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(certificate.getPublicKey()); boolean verificationResult = basicOCSPResp.isSignatureValid(contentVerifierProvider); if (false == verificationResult) { LOG.debug("OCSP response signature invalid"); return TrustLinkerResult.UNDECIDED; } } else { /* * We're dealing with a dedicated authorized OCSP Responder * certificate, or of course with a CA that issues the OCSP * Responses itself. */ X509CertificateHolder ocspResponderCertificate = responseCertificates[0]; ContentVerifierProvider contentVerifierProvider = new JcaContentVerifierProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(ocspResponderCertificate); boolean verificationResult = basicOCSPResp.isSignatureValid(contentVerifierProvider); if (false == verificationResult) { LOG.debug("OCSP Responser response signature invalid"); return TrustLinkerResult.UNDECIDED; } if (false == Arrays.equals(certificate.getEncoded(), ocspResponderCertificate.getEncoded())) { // check certificate signature algorithm algorithmPolicy.checkSignatureAlgorithm( ocspResponderCertificate.getSignatureAlgorithm().getAlgorithm().getId(), validationDate); X509Certificate issuingCaCertificate; if (responseCertificates.length < 2) { // so the OCSP certificate chain only contains a single // entry LOG.debug("OCSP responder complete certificate chain missing"); /* * Here we assume that the OCSP Responder is directly signed * by the CA. */ issuingCaCertificate = certificate; } else { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); issuingCaCertificate = (X509Certificate) certificateFactory .generateCertificate(new ByteArrayInputStream(responseCertificates[1].getEncoded())); /* * Is next check really required? */ if (false == certificate.equals(issuingCaCertificate)) { LOG.debug("OCSP responder certificate not issued by CA"); return TrustLinkerResult.UNDECIDED; } } // check certificate signature algorithmPolicy.checkSignatureAlgorithm(issuingCaCertificate.getSigAlgOID(), validationDate); PublicKeyTrustLinker publicKeyTrustLinker = new PublicKeyTrustLinker(); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); X509Certificate x509OcspResponderCertificate = (X509Certificate) certificateFactory .generateCertificate(new ByteArrayInputStream(ocspResponderCertificate.getEncoded())); LOG.debug("OCSP Responder public key fingerprint: " + DigestUtils.sha1Hex(x509OcspResponderCertificate.getPublicKey().getEncoded())); publicKeyTrustLinker.hasTrustLink(x509OcspResponderCertificate, issuingCaCertificate, validationDate, revocationData, algorithmPolicy); if (null == x509OcspResponderCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId())) { LOG.debug("OCSP Responder certificate should have id-pkix-ocsp-nocheck"); /* * TODO: perform CRL validation on the OCSP Responder * certificate. On the other hand, do we really want to * check the checker? */ return TrustLinkerResult.UNDECIDED; } List<String> extendedKeyUsage = x509OcspResponderCertificate.getExtendedKeyUsage(); if (null == extendedKeyUsage) { LOG.debug("OCSP Responder certificate has no extended key usage extension"); return TrustLinkerResult.UNDECIDED; } if (false == extendedKeyUsage.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) { LOG.debug("OCSP Responder certificate should have a OCSPSigning extended key usage"); return TrustLinkerResult.UNDECIDED; } } else { LOG.debug("OCSP Responder certificate equals the CA certificate"); // and the CA certificate is already trusted at this point } } DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(); CertificateID certificateId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), new JcaX509CertificateHolder(certificate), childCertificate.getSerialNumber()); SingleResp[] singleResps = basicOCSPResp.getResponses(); for (SingleResp singleResp : singleResps) { CertificateID responseCertificateId = singleResp.getCertID(); if (false == certificateId.equals(responseCertificateId)) { continue; } DateTime thisUpdate = new DateTime(singleResp.getThisUpdate()); DateTime nextUpdate; if (null != singleResp.getNextUpdate()) { nextUpdate = new DateTime(singleResp.getNextUpdate()); } else { LOG.debug("no OCSP nextUpdate"); nextUpdate = thisUpdate; } LOG.debug("OCSP thisUpdate: " + thisUpdate); LOG.debug("(OCSP) nextUpdate: " + nextUpdate); DateTime beginValidity = thisUpdate.minus(this.freshnessInterval); DateTime endValidity = nextUpdate.plus(this.freshnessInterval); DateTime validationDateTime = new DateTime(validationDate); if (validationDateTime.isBefore(beginValidity)) { LOG.warn("OCSP response not yet valid"); continue; } if (validationDateTime.isAfter(endValidity)) { LOG.warn("OCSP response expired"); continue; } if (null == singleResp.getCertStatus()) { LOG.debug("OCSP OK for: " + childCertificate.getSubjectX500Principal()); addRevocationData(revocationData, ocspResp, ocspUri); return TrustLinkerResult.TRUSTED; } else { LOG.debug("OCSP certificate status: " + singleResp.getCertStatus().getClass().getName()); if (singleResp.getCertStatus() instanceof RevokedStatus) { LOG.debug("OCSP status revoked"); } addRevocationData(revocationData, ocspResp, ocspUri); throw new TrustLinkerResultException(TrustLinkerResultReason.INVALID_REVOCATION_STATUS, "certificate revoked by OCSP"); } } LOG.debug("no matching OCSP response entry"); return TrustLinkerResult.UNDECIDED; }
From source file:ee.ria.xroad.common.ocsp.OcspVerifier.java
License:Open Source License
private void verifyValidityAt(Date atDate, SingleResp singleResp) { // 5. The time at which the status being indicated is known // to be correct (thisUpdate) is sufficiently recent. if (isExpired(singleResp, atDate)) { throw new CodedException(X_INCORRECT_VALIDATION_INFO, "OCSP response is too old (thisUpdate: %s)", singleResp.getThisUpdate()); }/* w w w .j a v a 2 s . c om*/ if (options.isVerifyNextUpdate()) { // 6. When available, the time at or before which newer information will // be available about the status of the certificate (nextUpdate) is // greater than the current time. log.debug("Verify OCSP nextUpdate, atDate: {} nextUpdate: {}", atDate, singleResp.getNextUpdate()); if (singleResp.getNextUpdate() != null && singleResp.getNextUpdate().before(atDate)) { SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); throw new CodedException(X_INCORRECT_VALIDATION_INFO, String.format("OCSP nextUpdate is too old, atDate: %s nextUpdate: %s", fmt.format(atDate), fmt.format(singleResp.getNextUpdate()))); } } else { log.debug("OCSP nextUpdate verification is turned off"); } }
From source file:ee.ria.xroad.common.ocsp.OcspVerifier.java
License:Open Source License
/** * Returns true if the OCSP response is about to expire at the given date. * @param singleResp the response/*from w w w .j a va2s . co m*/ * @param atDate the date * @return true, if the OCSP response is expired */ public boolean isExpired(SingleResp singleResp, Date atDate) { Date allowedThisUpdate = new DateTime(atDate).minusSeconds(ocspFreshnessSeconds).toDate(); log.trace("isExpired(thisUpdate: {}, allowedThisUpdate: {}, " + "atDate: {})", new Object[] { singleResp.getThisUpdate(), allowedThisUpdate, atDate }); return singleResp.getThisUpdate().before(allowedThisUpdate); }
From source file:eu.europa.ec.markt.dss.validation102853.ocsp.OfflineOCSPSource.java
License:Open Source License
@Override final public BasicOCSPResp getOCSPResponse(final X509Certificate x509Certificate, final X509Certificate issuerX509Certificate) { /**// w w w . java2s. c om * TODO: (Bob 2013.05.08) Does the OCSP responses always use SHA1?<br> * RFC 2560:<br> * CertID ::= SEQUENCE {<br> * hashAlgorithm AlgorithmIdentifier,<br> * issuerNameHash OCTET STRING, -- Hash of Issuer's DN<br> * issuerKeyHash OCTET STRING, -- Hash of Issuer's public key<br> * serialNumber CertificateSerialNumber }<br> * * ... The hash algorithm used for both these hashes, is identified in hashAlgorithm. serialNumber is the * serial number of the cert for which status is being requested. */ Date bestUpdate = null; BasicOCSPResp bestBasicOCSPResp = null; final CertificateID certId = DSSRevocationUtils.getOCSPCertificateID(x509Certificate, issuerX509Certificate); for (final BasicOCSPResp basicOCSPResp : getContainedOCSPResponses()) { for (final SingleResp singleResp : basicOCSPResp.getResponses()) { if (DSSRevocationUtils.matches(certId, singleResp)) { final Date thisUpdate = singleResp.getThisUpdate(); if (bestUpdate == null || thisUpdate.after(bestUpdate)) { bestBasicOCSPResp = basicOCSPResp; bestUpdate = thisUpdate; } } } } return bestBasicOCSPResp; }
From source file:eu.europa.ec.markt.dss.validation102853.ocsp.SKOnlineOCSPSource.java
License:GNU General Public License
@Override public OCSPToken getOCSPToken(CertificateToken certificateToken, CertificatePool certificatePool) { if (listener != null) { listener.onGetOCSPToken(certificateToken, certificatePool); }/*from www . j a v a 2 s . c o m*/ if (dataLoader == null) { throw new DSSNullException(DataLoader.class); } try { final String dssIdAsString = certificateToken.getDSSIdAsString(); if (logger.isTraceEnabled()) { logger.trace("--> OnlineOCSPSource queried for " + dssIdAsString); } final X509Certificate certificate = certificateToken.getCertificate(); // final X509Certificate issuerCertificate = certificateToken.getIssuerToken().getCertificate(); X500Principal issuerX500Principal = certificateToken.getIssuerX500Principal(); List<CertificateToken> issuerTokens = certificatePool.get(issuerX500Principal); if (issuerTokens == null || issuerTokens.size() == 0) throw new DSSException("Not possible to find issuer " + issuerX500Principal + " certificate"); final X509Certificate issuerCertificate = issuerTokens.get(0).getCertificate(); final String ocspUri = getAccessLocation(); if (logger.isDebugEnabled()) { logger.debug("OCSP URI: " + ocspUri); } if (ocspUri == null) { return null; } Extension nonceExtension = createNonce(); final byte[] content = buildOCSPRequest(certificate, issuerCertificate, nonceExtension); final byte[] ocspRespBytes = dataLoader.post(ocspUri, content); final OCSPResp ocspResp = new OCSPResp(ocspRespBytes); BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); checkNonce(basicOCSPResp, nonceExtension); Date bestUpdate = null; SingleResp bestSingleResp = null; final CertificateID certId = DSSRevocationUtils.getOCSPCertificateID(certificate, issuerCertificate); for (final SingleResp singleResp : basicOCSPResp.getResponses()) { if (DSSRevocationUtils.matches(certId, singleResp)) { final Date thisUpdate = singleResp.getThisUpdate(); if (bestUpdate == null || thisUpdate.after(bestUpdate)) { bestSingleResp = singleResp; bestUpdate = thisUpdate; } } } if (bestSingleResp != null) { final OCSPToken ocspToken = new OCSPToken(basicOCSPResp, bestSingleResp, certificatePool); ocspToken.setSourceURI(ocspUri); certificateToken.setRevocationToken(ocspToken); return ocspToken; } } catch (NullPointerException e) { logger.error( "OCSP error: Encountered a case when the OCSPResp is initialised with a null OCSP response...", e); } catch (OCSPException e) { logger.error("OCSP error: " + e.getMessage(), e); } catch (IOException e) { throw new DSSException(e); } return null; }
From source file:eu.europa.ec.markt.dss.validation102853.OCSPCertificateVerifier.java
License:Open Source License
@Override public RevocationToken check(final CertificateToken toCheckToken) { if (ocspSource == null) { LOG.warn("OCSPSource null"); toCheckToken.extraInfo().infoOCSPSourceIsNull(); return null; }/*from ww w . ja va 2 s . c o m*/ try { final X509Certificate issuerCert = toCheckToken.getIssuerToken().getCertificate(); final X509Certificate toCheckCert = toCheckToken.getCertificate(); final BasicOCSPResp basicOCSPResp = ocspSource.getOCSPResponse(toCheckCert, issuerCert); if (basicOCSPResp == null) { String uri = ""; if (ocspSource instanceof OnlineOCSPSource) { uri = ((OnlineOCSPSource) ocspSource).getAccessLocation(toCheckCert); toCheckToken.extraInfo().infoNoOCSPResponse(uri); } if (LOG.isInfoEnabled()) { LOG.info("OCSP response not found for " + toCheckToken.getDSSIdAsString() + " [" + uri + "]"); } return null; } final BigInteger serialNumber = toCheckCert.getSerialNumber(); final X509CertificateHolder x509CertificateHolder = new X509CertificateHolder( DSSUtils.getEncoded(issuerCert)); final DigestCalculator digestCalculator = DSSUtils.getSHA1DigestCalculator(); final CertificateID certificateId = new CertificateID(digestCalculator, x509CertificateHolder, serialNumber); final SingleResp[] singleResps = basicOCSPResp.getResponses(); for (final SingleResp singleResp : singleResps) { if (!DSSRevocationUtils.matches(certificateId, singleResp)) { continue; } if (LOG.isDebugEnabled()) { LOG.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); LOG.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); } final OCSPToken ocspToken = new OCSPToken(basicOCSPResp, validationCertPool); if (ocspSource instanceof OnlineOCSPSource) { ocspToken.setSourceURI(((OnlineOCSPSource) ocspSource).getAccessLocation(toCheckCert)); } ocspToken.setIssuingTime(basicOCSPResp.getProducedAt()); toCheckToken.setRevocationToken(ocspToken); final Object certStatus = singleResp.getCertStatus(); if (certStatus == null) { if (LOG.isInfoEnabled()) { LOG.info("OCSP OK for: " + toCheckToken.getDSSIdAsString()); if (LOG.isTraceEnabled()) { LOG.trace("CertificateToken:\n{}", toCheckToken.toString()); } } ocspToken.setStatus(true); } else { if (LOG.isInfoEnabled()) { LOG.info("OCSP certificate status: " + certStatus.getClass().getName()); } if (certStatus instanceof RevokedStatus) { if (LOG.isInfoEnabled()) { LOG.info("OCSP status revoked"); } final RevokedStatus revokedStatus = (RevokedStatus) certStatus; ocspToken.setStatus(false); ocspToken.setRevocationDate(revokedStatus.getRevocationTime()); final int reasonId = revokedStatus.getRevocationReason(); final CRLReason crlReason = CRLReason.lookup(reasonId); ocspToken.setReason(crlReason.toString()); } else if (certStatus instanceof UnknownStatus) { if (LOG.isInfoEnabled()) { LOG.info("OCSP status unknown"); } ocspToken.setReason("OCSP status: unknown"); } } return ocspToken; } } catch (DSSException e) { LOG.error("OCSP DSS Exception: " + e.getMessage(), e); toCheckToken.extraInfo().infoOCSPException(e); return null; } catch (OCSPException e) { LOG.error("OCSP Exception: " + e.getMessage()); toCheckToken.extraInfo().infoOCSPException(e); throw new DSSException(e); } catch (IOException e) { throw new DSSException(e); } if (LOG.isInfoEnabled()) { LOG.debug("No matching OCSP response entry"); } toCheckToken.extraInfo().infoNoOCSPResponse(null); return null; }
From source file:eu.europa.esig.dss.client.ocsp.OnlineOCSPSource.java
License:Open Source License
private SingleResp getBestSingleResp(final BasicOCSPResp basicOCSPResp, final CertificateID certId) { Date bestUpdate = null;/* w w w .j a va 2 s. co m*/ SingleResp bestSingleResp = null; for (final SingleResp singleResp : basicOCSPResp.getResponses()) { if (DSSRevocationUtils.matches(certId, singleResp)) { final Date thisUpdate = singleResp.getThisUpdate(); if ((bestUpdate == null) || thisUpdate.after(bestUpdate)) { bestSingleResp = singleResp; bestUpdate = thisUpdate; } } } return bestSingleResp; }
From source file:eu.europa.esig.dss.x509.ocsp.OfflineOCSPSource.java
License:Open Source License
@Override final public OCSPToken getOCSPToken(CertificateToken certificateToken, CertificateToken issuerCertificateToken) { final List<BasicOCSPResp> containedOCSPResponses = getContainedOCSPResponses(); if (LOG.isTraceEnabled()) { final String dssIdAsString = certificateToken.getDSSIdAsString(); LOG.trace("--> OfflineOCSPSource queried for " + dssIdAsString + " contains: " + containedOCSPResponses.size() + " element(s)."); }/*from www. j a v a2 s . co m*/ /** * TODO: (Bob 2013.05.08) Does the OCSP responses always use SHA1?<br> * RFC 2560:<br> * CertID ::= SEQUENCE {<br> * hashAlgorithm AlgorithmIdentifier,<br> * issuerNameHash OCTET STRING, -- Hash of Issuer's DN<br> * issuerKeyHash OCTET STRING, -- Hash of Issuer's public key<br> * serialNumber CertificateSerialNumber }<br> * * ... The hash algorithm used for both these hashes, is identified in hashAlgorithm. serialNumber is the * serial number of the cert for which status is being requested. */ Date bestUpdate = null; BasicOCSPResp bestBasicOCSPResp = null; SingleResp bestSingleResp = null; final CertificateID certId = DSSRevocationUtils.getOCSPCertificateID(certificateToken, issuerCertificateToken); for (final BasicOCSPResp basicOCSPResp : containedOCSPResponses) { for (final SingleResp singleResp : basicOCSPResp.getResponses()) { if (DSSRevocationUtils.matches(certId, singleResp)) { final Date thisUpdate = singleResp.getThisUpdate(); if ((bestUpdate == null) || thisUpdate.after(bestUpdate)) { bestBasicOCSPResp = basicOCSPResp; bestSingleResp = singleResp; bestUpdate = thisUpdate; } } } } if (bestBasicOCSPResp != null) { OCSPToken ocspToken = new OCSPToken(); ocspToken.setOrigin(RevocationOrigin.SIGNATURE); ocspToken.setBasicOCSPResp(bestBasicOCSPResp); ocspToken.setBestSingleResp(bestSingleResp); return ocspToken; } return null; }
From source file:io.netty.example.ocsp.OcspServerExample.java
License:Apache License
public static void main(String[] args) throws Exception { // We assume there's a private key. PrivateKey privateKey = null; // Step 1: Load the certificate chain for netty.io. We'll need the certificate // and the issuer's certificate and we don't need any of the intermediate certs. // The array is assumed to be a certain order to keep things simple. X509Certificate[] keyCertChain = parseCertificates(OcspServerExample.class, "netty_io_chain.pem"); X509Certificate certificate = keyCertChain[0]; X509Certificate issuer = keyCertChain[keyCertChain.length - 1]; // Step 2: We need the URL of the CA's OCSP responder server. It's somewhere encoded // into the certificate! Notice that it's a HTTP URL. URI uri = OcspUtils.ocspUri(certificate); System.out.println("OCSP Responder URI: " + uri); if (uri == null) { throw new IllegalStateException("The CA/certificate doesn't have an OCSP responder"); }//from ww w . ja va 2s . c o m // Step 3: Construct the OCSP request OCSPReq request = new OcspRequestBuilder().certificate(certificate).issuer(issuer).build(); // Step 4: Do the request to the CA's OCSP responder OCSPResp response = OcspUtils.request(uri, request, 5L, TimeUnit.SECONDS); if (response.getStatus() != OCSPResponseStatus.SUCCESSFUL) { throw new IllegalStateException("response-status=" + response.getStatus()); } // Step 5: Is my certificate any good or has the CA revoked it? BasicOCSPResp basicResponse = (BasicOCSPResp) response.getResponseObject(); SingleResp first = basicResponse.getResponses()[0]; CertificateStatus status = first.getCertStatus(); System.out.println("Status: " + (status == CertificateStatus.GOOD ? "Good" : status)); System.out.println("This Update: " + first.getThisUpdate()); System.out.println("Next Update: " + first.getNextUpdate()); if (status != null) { throw new IllegalStateException("certificate-status=" + status); } BigInteger certSerial = certificate.getSerialNumber(); BigInteger ocspSerial = first.getCertID().getSerialNumber(); if (!certSerial.equals(ocspSerial)) { throw new IllegalStateException("Bad Serials=" + certSerial + " vs. " + ocspSerial); } // Step 6: Cache the OCSP response and use it as long as it's not // expired. The exact semantics are beyond the scope of this example. if (!OpenSsl.isAvailable()) { throw new IllegalStateException("OpenSSL is not available!"); } if (!OpenSsl.isOcspSupported()) { throw new IllegalStateException("OCSP is not supported!"); } if (privateKey == null) { throw new IllegalStateException( "Because we don't have a PrivateKey we can't continue past this point."); } ReferenceCountedOpenSslContext context = (ReferenceCountedOpenSslContext) SslContextBuilder .forServer(privateKey, keyCertChain).sslProvider(SslProvider.OPENSSL).enableOcsp(true).build(); try { ServerBootstrap bootstrap = new ServerBootstrap().childHandler(newServerHandler(context, response)); // so on and so forth... } finally { context.release(); } }
From source file:org.digidoc4j.impl.bdoc.ocsp.SKOnlineOCSPSource.java
License:GNU General Public License
@Override public OCSPToken getOCSPToken(CertificateToken certificateToken, CertificateToken issuerCertificateToken) { logger.debug("Getting OCSP token"); if (dataLoader == null) { throw new RuntimeException("Data loader is null"); }/*from w w w . j a v a 2 s . c om*/ try { final String dssIdAsString = certificateToken.getDSSIdAsString(); if (logger.isTraceEnabled()) { logger.trace("--> OnlineOCSPSource queried for " + dssIdAsString); } final String ocspUri = getAccessLocation(); logger.debug("Getting OCSP token from URI: " + ocspUri); if (ocspUri == null) { return null; } Extension nonceExtension = createNonce(); final byte[] content = buildOCSPRequest(certificateToken, issuerCertificateToken, nonceExtension); final byte[] ocspRespBytes = dataLoader.post(ocspUri, content); final OCSPResp ocspResp = new OCSPResp(ocspRespBytes); BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); if (basicOCSPResp == null) { logger.error("OCSP response is empty"); return null; } checkNonce(basicOCSPResp, nonceExtension); Date bestUpdate = null; SingleResp bestSingleResp = null; final CertificateID certId = DSSRevocationUtils.getOCSPCertificateID(certificateToken, issuerCertificateToken); for (final SingleResp singleResp : basicOCSPResp.getResponses()) { if (DSSRevocationUtils.matches(certId, singleResp)) { final Date thisUpdate = singleResp.getThisUpdate(); if (bestUpdate == null || thisUpdate.after(bestUpdate)) { bestSingleResp = singleResp; bestUpdate = thisUpdate; } } } if (bestSingleResp != null) { OCSPToken ocspToken = new OCSPToken(); ocspToken.setBasicOCSPResp(basicOCSPResp); ocspToken.setBestSingleResp(bestSingleResp); ocspToken.setSourceURL(ocspUri); certificateToken.addRevocationToken(ocspToken); return ocspToken; } } catch (OCSPException e) { logger.error("OCSP error: " + e.getMessage(), e); } catch (IOException e) { throw new DSSException(e); } return null; }