Zertifikatsstatus per OCSP-Abfrage
Problem: Überprüfung eines X509-Zertifikates per OCSP-Abfrage, ob dieses gesperrt wurde:
Lösung:
Der OCSP-Client:
public class OcspClientBouncyCastle { /** root certificate */ private X509Certificate rootCert; /** check certificate */ private X509Certificate checkCert; /** OCSP URL */ private String url; private static final Logger logger = Logger.getLogger(OcspClientBouncyCastle.class); /** * Creates an instance of an OcspClient that will be using BouncyCastle */ public OcspClientBouncyCastle() { } /** * Generates an OCSP request using BouncyCastle. * @param issuerCert - certificate of the issues. * @param serialNumber - serial number. * @return an OCSP request * @throws OCSPException * @throws IOException */ private OCSPReq generateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber) throws OCSPException, IOException { // Generate the id for the certificate we are looking for CertificateID id = new CertificateID(CertificateID.HASH_SHA1, issuerCert, serialNumber); // basic request generation with nonce OCSPReqGenerator gen = new OCSPReqGenerator(); gen.addRequest(id); // create details for nonce extension // to prevent Replay-Attacks Vector oids = new Vector(); Vector values = new Vector(); oids.add(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); values.add(new X509Extension(false, new DEROctetString(new DEROctetString(PdfEncryption.createDocumentId()).getEncoded()))); gen.setRequestExtensions(new X509Extensions(oids, values)); return gen.generate(); } /** * Generates a {@link ErrorStatus}. * @return the statuscode. * @throws OCSPException */ public int getOCSPStatus() throws OCSPException { try { OCSPReq request = generateOCSPRequest(rootCert, checkCert.getSerialNumber()); byte[] array = request.getEncoded(); URL urlt = new URL(url); HttpURLConnection con = (HttpURLConnection)urlt.openConnection(); con.setRequestProperty("Content-Type", "application/ocsp-request"); con.setRequestProperty("Accept", "application/ocsp-response"); con.setDoOutput(true); OutputStream out = con.getOutputStream(); DataOutputStream dataOut = new DataOutputStream(new BufferedOutputStream(out)); dataOut.write(array); dataOut.flush(); dataOut.close(); if (con.getResponseCode() / 100 != 2) throw new OCSPException("Invalid HTTP response"); //Get Response InputStream in = (InputStream) con.getContent(); OCSPResp ocspResponse = new OCSPResp(in); if (ocspResponse.getStatus() != OCSPResponseStatus.SUCCESSFUL) throw new OCSPException(ocspResponse.getStatus(),"Error in OCSPRequest/Response"); BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject(); if (basicResponse != null) { SingleResp[] responses = basicResponse.getResponses(); if (responses.length == 1) { SingleResp resp = responses[0]; logger.info(" certificate number " + resp.getCertID().getSerialNumber()); Object status = resp.getCertStatus(); // Check the status of the response and adjust certificate if (status == CertificateStatus.GOOD) { logger.info("OCSP-Response-Status: OK!"); // Die Antwort good muss aber nicht bedeuten, dass ein Zertifikat gültig exis- // tiert und nicht widerrufen worden ist. Diese Aussage könnte nur formuliert werden, // wenn der OCSP-Responder direkten Zugriff auf die Datenbank der Zertifizierungsstelle // hätte. Ist nur der Zugriff auf eine CRL vorhanden, kann der Responder lediglich sagen, // dass ein Zertifkat nicht widerrufen worden ist return ErrorStatus.CERTIFICATE_OK; } else if (status instanceof org.bouncycastle.ocsp.RevokedStatus) { logger.info("Status Revoked"); //ergebnis:fehlgeschlagen return ErrorStatus.CERTIFICATE_REVOKED; } else if (status instanceof org.bouncycastle.ocsp.UnknownStatus) { logger.info("Status Unknown!"); //ergebnis:unbekannt return ErrorStatus.CERTIFICATE_UNKNOWN; } } } } catch (Exception ex) { logger.error(ex.getMessage()); } return ErrorStatus.CERTIFICATE_UNKNOWN; } public X509Certificate getRootCert() { return rootCert; } public void setRootCert(X509Certificate rootCert) { this.rootCert = rootCert; } public X509Certificate getCheckCert() { return checkCert; } public void setCheckCert(X509Certificate checkCert) { this.checkCert = checkCert; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
In Spring verdrahten und die getOCSPStatus()-Methode aufrufen. Vorher natürlich noch die Zertifikate sowie die URL für die Überprüfung übergeben. Diese steht im Zertifikat!