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!