如何检查X509证书是否已在Java中被撤销?

时间:2017-02-02 17:31:45

标签: java ssl x509certificate

我已经在这里搜索了所有地方,并在其他社区询问,我不断转发到讨论规范的oracle文档。但是,该文档更多地涉及方法的命名和整体架构,并没有实际提出一种方法来讨论如何实际编写一些代码以检查x509证书是否被撤销。

也许这只是我的头脑?但我绝对会感激,如果有人可以用一个片段帮助我,我一直在用一块墙撞在我身上大约一个星期。

2 个答案:

答案 0 :(得分:2)

每个CA都会发布已撤消的证书列表。 此列表包括证书的序列号和撤销日期

获取证书吊销列表(CRL)的URL遵循以下步骤

  • 打开证书
  • 转到详细信息选项卡,在详细信息列表中找到“CRL分发点”字段

它会显示类似这样的值

[1] CRL分发点      分发点名称:           全名:                URL = mscrl.microsoft.com / PKI / mscorp / CRL / msitwww2.crl                URL = crl.microsoft.com / PKI / mscorp / CRL / msitwww2.crl

因此,在您的代码中,您需要下载这些文件并检查其中的证书序列号以查看它是否已被撤销

在下面找到它的示例代码

public class CertVerification {


    public static void main(String[] args) throws Exception {

        String certificatePath = "C:\\Users\\user1\\Desktop\\test.cer";

        CertificateFactory cf = CertificateFactory.getInstance("X509");

        X509Certificate certificate = null;
        X509CRLEntry revokedCertificate = null;
        X509CRL crl = null;

        certificate = (X509Certificate) cf.generateCertificate(new FileInputStream(new File(certificatePath)));

        URL url = new URL("http://<someUrl from certificate>.crl");
        URLConnection connection = url.openConnection();

        try(DataInputStream inStream = new DataInputStream(connection.getInputStream())){

            crl = (X509CRL)cf.generateCRL(inStream);
        }

        revokedCertificate = crl.getRevokedCertificate(certificate.getSerialNumber());

        if(revokedCertificate !=null){
            System.out.println("Revoked");
        }
        else{
            System.out.println("Valid");
        }

    }


}

请参阅

这些列表会定期更新

您也可以从证书中获取这些撤销网址,我刚刚举了一个例子

这只是一个让您先行的基本示例

<强>更新

我发现此示例类检查证书,它还使用证书的CA和证书链发布的CRL进行验证,因此您也不需要提供CRL URL

https://svn.cesecore.eu/svn/ejbca/branches/Branch_3_2_3_utf8/ejbca/doc/samples/ValidateCertUseCRL.java

答案 1 :(得分:0)

证书颁发机构使用在线证书服务协议(OCSP)和证书撤销列表(CRL)发布证书的状态。

检查证书的撤销涉及以下几个步骤:

  1. 从X509Certificate中包含的AIA扩展程序中提取CRL分发点和OCSP网址

  2. 下载CRL 并检查是否包含证书的序列号。验证CRL的签名证书并确保受信任(信任库中的根CA)

  3. 在线查询OCSP服务发送序列号和发卡行以获取状态。检查OCSP响应的签名并确保签名证书可信(您的信任库中的根CA)。

  4. 如果证书在CRL中出现或OCSP状态被撤销,则会被撤销。建议使用OCSP而不是CRL,但通常会查询这两项服务,因为可能会崩溃。

  5. 正如您所看到的,这个过程并不简单。检查证书是否有效可能包括对OCSP服务的多次调用,下载证书链,验证CRL签名证书和OCSP响应的签名,最后验证CA是否可信

    所以如果您不考虑所有这些因素,我建议不要直接使用Java原生方法

    您可以使用BouncyCastle来管理CRL和查询OCSP,但更好的决定是使用SD-DSS框架(它也使用BouncyCastle),它非常封装所有这些东西。

    Github SD-DSS:https://github.com/esig/dss 文档:http://dss.nowina.lu/doc/dss-documentation.html

    示例

    验证证书检查吊销的完整示例。如果您只想检查撤销

    ,请忽略加载受信任来源和中间人的步骤
    //Load the certification chain, including the intemediate certificates and the trusted root.    
    CertificateToken issuerCert = DSSUtils.loadCertificate("/trusted.crt");
    CommonTrustedCertificateSource trustedCertificateSource = new CommonTrustedCertificateSource();
    trustedCertificateSource.addCertificate(issuerCert);
    
    CommonCertificateSource adjunctCertificateSource = new CommonCertificateSource();
    CertificateToken intermediateCert = DSSUtils.loadCertificate("/intermediate.cer");
    adjunctCertificateSource.addCertificate(intermediateCert);
    
    //Load the certificate to verify
    CertificateToken toValidateX509Certificate = DSSUtils.loadCertificate("/toValidate.crt");
    CertificateToken toValidateCertificateToken = adjunctCertificateSource.addCertificate(toValidateX509Certificate);
    
    //Configure the certificate verifier using the trust store and the intermediate certificates
    //OnlineOCSPSource and OnlineCRLSource will invoke the OCSP service and CRL
    //distribution point extracting the URL  from the certificate
    CertificateVerifier certificateVerifier = new CommonCertificateVerifier();
    certificateVerifier.setTrustedCertSource(trustedCertificateSource);
    certificateVerifier.setAdjunctCertSource(adjunctCertificateSource);     
    certificateVerifier.setCrlSource(new OnlineCRLSource());
    certificateVerifier.setOcspSource(new OnlineOCSPSource());
    
    //Perform validation 
    CertificatePool validationPool = certificateVerifier.createValidationPool();
    SignatureValidationContext validationContext = new SignatureValidationContext(validationPool);
    validationContext.addCertificateTokenForVerification(toValidateCertificateToken);
    validationContext.validate();
    
    //Get revocation status
    Boolean isRevoked = toValidateCertificateToken.isRevoked();
    RevocationToken revocationToken = toValidateCertificateToken.getRevocationToken();