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!


Tags: