11

我使用 Bouncy castle API 创建了一个 OCSP 客户端。我无法从收到的 OCSP 响应中找到证书状态(说明其是否已撤销)。从 resp.getCertStatus() 返回的值始终为空。这就是我创建 OCSP 请求的方式。

    private OCSPReq generateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber)
        throws CertificateVerificationException {

    //Add provider BC
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    try {
        //  CertID structure is used to uniquely identify certificates that are the subject of
        // an OCSP request or response and has an ASN.1 definition. CertID structure is defined in RFC 2560
        CertificateID id = new CertificateID(CertificateID.HASH_SHA1, issuerCert, serialNumber);

        // basic request generation with nonce
        OCSPReqGenerator generator = new OCSPReqGenerator();
        generator.addRequest(id);

        // create details for nonce extension. The nonce extension is used to bind
        // a request to a response to prevent replay attacks. As the name implies,
        // the nonce value is something that the client should only use once within a reasonably small period.
        BigInteger nonce = BigInteger.valueOf(System.currentTimeMillis());
        Vector objectIdentifiers = new Vector();
        Vector values = new Vector();

        //to create the request Extension
        objectIdentifiers.add(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
        values.add(new X509Extension(false, new DEROctetString(nonce.toByteArray())));
        generator.setRequestExtensions(new X509Extensions(objectIdentifiers, values));

        return generator.generate();
    }
    catch (OCSPException e) {
        e.printStackTrace();
        throw new CertificateVerificationException("Cannot generate OSCP Request with the given certificate",e);
    }
}

我从服务 URL 获得 OCSP 响应,如下所示。

    private OCSPResp getOCSPResponce(String serviceUrl, OCSPReq request) throws CertificateVerificationException {

    try {
        byte[] array = request.getEncoded();
        if (serviceUrl.startsWith("http")) {
            HttpURLConnection con;
            URL url = new URL(serviceUrl);
            con = (HttpURLConnection) url.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();

            //Get Response
            InputStream in = (InputStream) con.getContent();
            OCSPResp ocspResponse = new OCSPResp(in);
            return ocspResponse;
        }
        else {
            throw new CertificateVerificationException("Only http is supported for ocsp calls");
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw new CertificateVerificationException("Cannot get ocspResponse from url: "+ serviceUrl, e);
    }
}

撤销状态检查如下。这里从 BasicOCSPResp 对象 (basicResponse) 获取的 SingleResp 对象 (resp) 应该具有证书的状态(良好、已撤销或未知)。但是这里的状态总是空的。

public void checkRevocationStatus(X509Certificate peerCert, X509Certificate issuerCert) 
throws CertificateVerificationException {

    try {

        OCSPReq request = generateOCSPRequest(issuerCert, peerCert.getSerialNumber());
        List<String> locations = getAIALocations(peerCert);
        Iterator it = locations.iterator();

        if (it.hasNext()) {

            String serviceUrl = (String) it.next();   
            OCSPResp ocspResponse = getOCSPResponce(serviceUrl, request);
            if(OCSPRespStatus.SUCCESSFUL==ocspResponse.getStatus())
                System.out.println("server gave response fine");

            BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject();
            SingleResp[] responses = (basicResponse==null) ? null : basicResponse.getResponses();

            if (responses!=null && responses.length == 1) {
                SingleResp resp = responses[0];
                Object status = resp.getCertStatus();
                if(status!=null) {
                    if (status == CertificateStatus.GOOD) {
                        System.out.println("OCSP Status is good!");
                    } else if (status instanceof org.bouncycastle.ocsp.RevokedStatus) {
                        System.out.println("OCSP Status is revoked!");
                    }  else if (status instanceof org.bouncycastle.ocsp.UnknownStatus) {
                        System.out.println("OCSP Status is unknown!");
                    }
                }
            }
        }
    }
    catch (Exception e) {
        System.out.println(e);
    }
}

我真的很感谢你的帮助。非常感谢。

4

1 回答 1

9

实际上,如果您查看 CertificateStatus.GOOD 的实际值,您会发现它实际上是 null。换句话说,resp.getCertStatus() 返回 null,意思是 GOOD。

所以你可能只需要拿出那个 (status != null) 检查。

于 2013-02-26T07:12:57.227 回答