Zertifikatsstatus per OCSP-Abfrage
Problem: Überprüfung eines X509-Zertifikates per OCSP-Abfrage, ob dieses gesperrt wurde:
Lösung:
Der OCSP-Client:
001 | public class OcspClientBouncyCastle |
002 | { |
003 | /** root certificate */ |
004 | private X509Certificate rootCert; |
005 | /** check certificate */ |
006 | private X509Certificate checkCert; |
007 | /** <b style="color: black; background-color: rgb(255, 255, 102);">OCSP</b> URL */ |
008 | private String url; |
009 |
010 | private static final Logger logger = Logger.getLogger(OcspClientBouncyCastle. class ); |
011 |
012 | /** |
013 | * Creates an instance of an OcspClient that will be using BouncyCastle |
014 | */ |
015 | public OcspClientBouncyCastle() |
016 | { |
017 |
018 | } |
019 |
020 | /** |
021 | * Generates an <b style="color: black; background-color: rgb(255, 255, 102);">OCSP</b> request using BouncyCastle. |
022 | * @param issuerCert - certificate of the issues. |
023 | * @param serialNumber - serial number. |
024 | * @return an <b style="color: black; background-color: rgb(255, 255, 102);">OCSP</b> request |
025 | * @throws OCSPException |
026 | * @throws IOException |
027 | */ |
028 | private OCSPReq generateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber) throws OCSPException, IOException |
029 | { |
030 | // Generate the id for the certificate we are looking for |
031 | CertificateID id = new CertificateID(CertificateID.HASH_SHA1, issuerCert, serialNumber); |
032 |
033 | // basic request generation with nonce |
034 | OCSPReqGenerator gen = new OCSPReqGenerator(); |
035 |
036 | gen.addRequest(id); |
037 |
038 | // create details for nonce extension |
039 | // to prevent Replay-Attacks |
040 | Vector oids = new Vector(); |
041 | Vector values = new Vector(); |
042 |
043 | oids.add(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); |
044 | values.add( new X509Extension( false , new DEROctetString( new DEROctetString(PdfEncryption.createDocumentId()).getEncoded()))); |
045 |
046 | gen.setRequestExtensions( new X509Extensions(oids, values)); |
047 |
048 | return gen.generate(); |
049 | } |
050 |
051 | /** |
052 | * Generates a {@link ErrorStatus}. |
053 | * @return the statuscode. |
054 | * @throws OCSPException |
055 | */ |
056 | public int getOCSPStatus() throws OCSPException |
057 | { |
058 | try |
059 | { |
060 |
061 | OCSPReq request = generateOCSPRequest(rootCert, checkCert.getSerialNumber()); |
062 | byte [] array = request.getEncoded(); |
063 | URL urlt = new URL(url); |
064 | HttpURLConnection con = (HttpURLConnection)urlt.openConnection(); |
065 | con.setRequestProperty( "Content-Type" , "application/<b style=" color: black; background-color: rgb( 255 , 255 , 102 ); ">ocsp</b>-request" ); |
066 | con.setRequestProperty( "Accept" , "application/<b style=" color: black; background-color: rgb( 255 , 255 , 102 ); ">ocsp</b>-response" ); |
067 | con.setDoOutput( true ); |
068 |
069 | OutputStream out = con.getOutputStream(); |
070 | DataOutputStream dataOut = new DataOutputStream( new BufferedOutputStream(out)); |
071 | dataOut.write(array); |
072 | dataOut.flush(); |
073 | dataOut.close(); |
074 |
075 | if (con.getResponseCode() / 100 != 2 ) |
076 | throw new OCSPException( "Invalid HTTP response" ); |
077 |
078 | //Get Response |
079 | InputStream in = (InputStream) con.getContent(); |
080 | OCSPResp ocspResponse = new OCSPResp(in); |
081 |
082 | if (ocspResponse.getStatus() != OCSPResponseStatus.SUCCESSFUL) |
083 | throw new OCSPException(ocspResponse.getStatus(), "Error in OCSPRequest/Response" ); |
084 |
085 | BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject(); |
086 | if (basicResponse != null ) |
087 | { |
088 | SingleResp[] responses = basicResponse.getResponses(); |
089 | if (responses.length == 1 ) |
090 | { |
091 | SingleResp resp = responses[ 0 ]; |
092 | logger.info( " certificate number " + resp.getCertID().getSerialNumber()); |
093 | Object status = resp.getCertStatus(); |
094 |
095 | // Check the status of the response and adjust certificate |
096 | if (status == CertificateStatus.GOOD) |
097 | { |
098 | logger.info( "<b style=" color: black; background-color: rgb( 255 , 255 , 102 ); ">OCSP</b>-Response-Status: OK!" ); |
099 | // Die Antwort good muss aber nicht bedeuten, dass ein Zertifikat gültig exis- |
100 | // tiert und nicht widerrufen worden ist. Diese Aussage könnte nur formuliert werden, |
101 | // wenn der <b style="color: black; background-color: rgb(255, 255, 102);">OCSP</b>-Responder direkten Zugriff auf die Datenbank der Zertifizierungsstelle |
102 | // hätte. Ist nur der Zugriff auf eine CRL vorhanden, kann der Responder lediglich sagen, |
103 | // dass ein Zertifkat nicht widerrufen worden ist |
104 |
105 | return ErrorStatus.CERTIFICATE_OK; |
106 | } |
107 | else if (status instanceof org.bouncycastle.<b style= "color: black; background-color: rgb(255, 255, 102);" >ocsp</b>.RevokedStatus) |
108 | { |
109 | logger.info( "Status Revoked" ); |
110 | //ergebnis:fehlgeschlagen |
111 | return ErrorStatus.CERTIFICATE_REVOKED; |
112 |
113 | } else if (status instanceof org.bouncycastle.<b style= "color: black; background-color: rgb(255, 255, 102);" >ocsp</b>.UnknownStatus) |
114 | { |
115 | logger.info( "Status Unknown!" ); |
116 | //ergebnis:unbekannt |
117 | return ErrorStatus.CERTIFICATE_UNKNOWN; |
118 | } |
119 | } |
120 | } |
121 |
122 | } |
123 | catch (Exception ex) |
124 | { |
125 | logger.error(ex.getMessage()); |
126 | } |
127 | return ErrorStatus.CERTIFICATE_UNKNOWN; |
128 | } |
129 |
130 | public X509Certificate getRootCert() |
131 | { |
132 | return rootCert; |
133 | } |
134 |
135 | public void setRootCert(X509Certificate rootCert) |
136 | { |
137 | this .rootCert = rootCert; |
138 | } |
139 |
140 | public X509Certificate getCheckCert() |
141 | { |
142 | return checkCert; |
143 | } |
144 |
145 | public void setCheckCert(X509Certificate checkCert) |
146 | { |
147 | this .checkCert = checkCert; |
148 | } |
149 |
150 | public String getUrl() |
151 | { |
152 | return url; |
153 | } |
154 |
155 | public void setUrl(String url) |
156 | { |
157 | this .url = url; |
158 | } |
159 |
160 | } |
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!