11

I have googled around all over the place for this, and asked in other communities, and I keep getting forwarded to the oracle document that discusses the spec. However, that document more covers the naming of methods, and the overall architecture, and doesn't actually come up with a way to discuss how to actually write some code to check if an x509 cert is revoked or not.

Maybe this one is just way over my head? But I would definitely appreciate if someone could just help me out with a snippet, I have been banging my head against a wall on this for about a week.

MickeyThreeSheds
  • 986
  • 4
  • 23
  • 42

2 Answers2

8

Every CA publishes the list of the certificates it has revoked. This list includes the serial number of the certificates and the revocation date

to get the url of the certificate revocation list (CRL) follow the below steps

  • open the certificate
  • go to Details Tab and find the field "CRL Distribution Point" in the details list

It will show you the value something like this

[1]CRL Distribution Point Distribution Point Name: Full Name: URL=mscrl.microsoft.com/pki/mscorp/crl/msitwww2.crl URL=crl.microsoft.com/pki/mscorp/crl/msitwww2.crl

So in your code you need to download these files and check for the certificate serial number in them to see if it's revoked or not

Find below the sample code for it

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");
        }

    }


}

Please See

These lists are updated periodically

You can get these Revocation URL's from the certificate as well, i have just given an example

This is just a basic example to give you a head start

Update

I found this sample class to check certificate, it also verifies with the CRL issued by the certificate's CA and certification chain, so you don't need to provide the CRL url as well

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

Rajiv Kapoor
  • 315
  • 1
  • 7
  • Thanks! I will be back at my desk in about two hours and will give this a shot - Thanks so much, this was beginning to kill me! haha – MickeyThreeSheds Feb 02 '17 at 20:46
  • you can get certificate information using the getTBSCertificate method on certificate, it will return all that information in bytes and then you need to extract the urls. – Rajiv Kapoor Feb 03 '17 at 03:38
  • i have updated the answer with the link to class file which is doing all the required work, take help from that.kindly reply in case you need any clarification on the code given in link – Rajiv Kapoor Feb 03 '17 at 03:40
  • 1
    @RajivKapoor you omitted the OCSP revocation check. Some CAs do not publish CRL. Check this link https://blogs.oracle.com/xuelei/entry/enable_ocsp_checking. I advise against using a fixed URL instead of the one included in the certificate. A CA normally publishes multiple URLs, for each subCA or divided by size, you would not know which one to use. If you check a serial number with the incorrect CRL you will have a false negative. Also for security reasons you have to verify that the CA of the CRL is the same as the certificate. – pedrofb Feb 03 '17 at 06:57
  • agree with your points that's why i updated the answer with the link which includes all the checks, mine was just an example to give a headstart – Rajiv Kapoor Feb 03 '17 at 07:11
  • This really helped me out - I have it all working now! Thanks a million! – MickeyThreeSheds Feb 03 '17 at 15:48
2

A Certification Authority publish the status of the certificates using Online Certificate Service Protocol (OCSP) and Certificate Revocation Lists (CRL).

Check the revocation of a certificate involves several steps:

  1. Extract the CRL distribution point and OCSP url from AIA extension included in the X509Certificate

  2. Download the CRL and check if the serial number of your certificate is included. Verify the signing certificate of the CRL and ensure is trusted (root CA in your truststore)

  3. Query online the OCSP service sending the serial number and the issuer to get the status. Check the signature of the OCSP response and ensure signing certificate is trusted (root CA in your truststore).

  4. Certificate is revoked if it is present in CRL or OCSP status is revoked. OCSP is recommended over CRLs, but it usual to query both service because could be down.

As you can see the process is not simple at all. Check if a certificate is valid may consists in several invocations to OCSP service, downloading the certificate chain, verify signature of signing certificate of the CRLs and OCSP responses, and finally verify that the CA is trusted

So I recommend not to use Java native methods directly if you are not going to take into account all these factors

You can use BouncyCastle to manage CRL and query OCSP, but a better decision would be to use the SD-DSS framework (it uses also BouncyCastle), that pretty encapsulates all this stuff.

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


Example

Full example to validate a certificate checking revocation. Omit the steps of loading the trusted source and intermediates if you only want to check revocation

//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();
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • I just tested this code but it doesn't work using the DSS library. For example the CertificatePool object is not recognized – Mehdi Jan 31 '22 at 13:11
  • 1
    Hmm, not sure if you should first use the CRL and then the OCSP in serial. Checking the OCSP and then using CRL as fallback mech seems to make more sense to me. – Maarten Bodewes Sep 13 '22 at 14:17
  • So Java doesn't do CRL checking out of the box? – Diego Ramos Nov 08 '22 at 02:04