March 7, 2020 (updated July 27, 2024)

Browsers mostly don't check whether a HTTPS certificate has been revoked so maybe you'd like to do it manually. There are a few ways how to query an Online Certificate Status Protocol (OCSP) server so let's see some of them. You'll need a browser (and the openssl tool).

If you have a hostname

When you want to check a certificate that has been deployed on a publicly accessible machine then this is the easiest way. Use a service like SSL Labs Server Test, enter the URL, wait a second or 95, and check the result. The information you're looking for is in the Revocation status row. “Good” means not revoked, “Revoked” means the certificate has been revoked, no surprise here.

Revoked certificate in SSL Labs Server Test

Revoked certificate in SSL Labs Server Test

If you have a certificate

You may have a TLS certificate that's not used anymore, and want to check whether it has been revoked. My favorite certification authority (CA), Let's Encrypt, has recently revoked a million certificates or two due to a CAA verification bug and you had to force-renew the affected certificates. Now you want to see, for whatever reason, whether your old certificates have already been revoked by the CA.

Due to the Let's Encrypt bug, I had to renew a certificate for canhas.report – my browser reporting demo site. We'll use crt.sh (“Certificate Search”) to see all the certificates for the domain and you'll notice that right now, there's a certificate issued on March 3rd, 2020 and that's the new one. The previous one, the one I had to replace, was issued on January 26th, and that's the one I'd like to check the revocation status for.

crt.sh shows the status in the Revocation area, listing several mechanisms and the status they provide, if any. The Let's Encrypt certification authority provides a Certificate Revocation List (CRL) since 2022, so checking newer certificates you'll see their status, but an older certificate CRL status will be shown as “Unknown”. My certificate hasn't made it yet to Google's, Microsoft's, Mozilla's pro­prietary revocation lists, and at this point most probably never will, so you'll see it listed as Not Revoked by these companies.

But even in newer certificates issued by Let's Encrypt, there's no “X509v3 CRL Distribution Points” part in the “X509v3 extensions” section. There's only OCSP in the Authority Information Access (AIA) section, see below, and even that will disappear soon as Let's Encrypt plans to end their OCSP service possibly as early as 2025.

Let's Encrypt doesn't add their CRL URL intentionally so that HTTPS clients don't need to download the relatively huge list with every connection saving traffic. The CRL address is listed in the Common CA Database (CCADB).

Certificate revocation status in crt.sh

Certificate revocation status in crt.sh

The Check link in the OCSP line queries the OCSP server (called OCSP responder) listed in the already mentioned Authority Information Access extension, and if you'd click it right now, then you'd see “Revoked”. Until yesterday, you'd see “Good” as in not revoked. Make sure you're checking the leaf certificate, not the precertificate (see the Summary line in the certificate details page).

Quoting the OCSP RFC Section 2.5, “OCSP responders MAY pre-produce signed responses specifying the status of certificates at a specified time.” What you may be seeing is the “cached” status response, let's verify that.

Getting a certificate

Let's manually query the OCSP responder using openssl which is readily available in Unix-based operating systems and can be downloaded for Windows too. You'll need a certificate that you want to check and its issuer certificate, in most cases it's the intermediate CA certificate, not the root CA one.

Let's Encrypt Authority X3 is an intermediate certificate

Let's Encrypt Authority X3 is an intermediate CA and is the issuer of the canhas.report leaf certificate

Both certificates must be in the PEM format. The file extension is irrelevant but the content has to start and end with a special header and footer:

-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----

If you have a certificate in binary DER format, you can convert it to PEM by running:

openssl x509 -inform der -in certificate.cer -out certificate.pem

There are many places where you can get the certificate from but let's get both from crt.sh as we're already using it. When viewing certificate details, click Certificate and save the file (2388791592.crt in this case).

Certificate download link in crt.sh

Certificate download link in crt.sh

Then click Issuer below and then select one of the certificates:

Issuer certificates in crt.sh

Issuer certificates in crt.sh

Then again click Certificate and save the file (15706126.crt).

OCSP pre-produced responses

We'll need the URI for the OCSP responder and you can again get it from the crt.sh details page or you can read it from the certificate file directly with

$ openssl x509 -noout -ocsp_uri -in 2388791592.crt

The URI for the responder in this case is http://ocsp.int-x3.letsencrypt.org.

Now we have everything to manually query the responder using OpenSSL's ocsp module:

$ openssl ocsp -issuer 15706126.crt -cert 2388791592.crt -url http://ocsp.int-x3.letsencrypt.org

This is the result (“revoked”):

WARNING: no nonce in response
Response verify OK
2388791592.crt: revoked
        This Update: Mar  6 23:00:00 2020 GMT
        Next Update: Mar 13 23:00:00 2020 GMT
        Reason: (UNKNOWN)
        Revocation Time: Mar  6 23:08:56 2020 GMT

Until yesterday, the result was “good”:

WARNING: no nonce in response
Response verify OK
2388791592.crt: good
        This Update: Mar  5 22:00:00 2020 GMT
        Next Update: Mar 12 22:00:00 2020 GMT

You see the response was pre-produced, is now cached, and the “This Update” field specifies the time at which the status (“revoked”) was known to be correct. The response is valid for 7 days, “Next Update” is the time at or before which newer information will be available about the status of the certificate.

If you'd like to know when the status was produced you can append -text:

$ openssl ocsp -issuer 15706126.crt -cert 2388791592.crt -url http://ocsp.int-x3.letsencrypt.org -text

The result is a bit longer with more details:

OCSP Request Data:
    Version: 1 (0x0)
    Requestor List:
        Certificate ID:
          Hash Algorithm: sha1
          Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
          Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
          Serial Number: 036A2B3D1A79345759AF487420119EF947BC
    Request Extensions:
        OCSP Nonce:
            0410113F6F29A10441061B371B7E2C294BDC
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
    Produced At: Mar  6 23:08:00 2020 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
      Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
      Serial Number: 036A2B3D1A79345759AF487420119EF947BC
    Cert Status: revoked
    Revocation Time: Mar  6 23:08:56 2020 GMT
    Revocation Reason: (UNKNOWN) (0x9)
    This Update: Mar  6 23:00:00 2020 GMT
    Next Update: Mar 13 23:00:00 2020 GMT

    Signature Algorithm: sha256WithRSAEncryption
         98:9c:85:95:60:15:2f:a8:7b:75:8b:00:69:82:57:28:1b:f9:
         10:4a:c1:fc:a9:37:9e:b7:4f:ce:d4:57:b0:16:f6:23:cc:39:
         fa:49:eb:ee:d7:19:57:d6:ca:5b:d9:c3:36:8d:60:25:14:93:
         aa:54:dc:b0:32:8f:52:8a:e3:60:37:d0:d2:9a:b3:33:8a:18:
         63:e9:b4:a9:ef:5f:9b:77:ad:d1:cc:60:b0:2c:38:8f:4c:fb:
         38:ee:91:b9:90:e0:ce:93:4b:8e:5c:c5:39:4a:1a:6e:0a:69:
         c2:ec:c6:fd:bf:44:c9:1b:18:f3:3a:63:ab:28:fb:b9:a3:52:
         49:b5:16:49:85:6e:e1:f0:ca:48:9c:80:f3:5b:f7:ec:ef:32:
         dd:27:fb:f3:59:e8:71:85:92:28:70:07:d5:c4:2e:54:9e:f9:
         d9:70:f2:ee:26:e9:d5:ea:2a:fb:ff:53:58:2d:fb:bc:fb:9c:
         74:dc:3d:30:b9:f4:59:57:d7:cd:d9:f5:74:62:92:bc:2e:b8:
         a2:ed:44:97:11:5e:03:d8:2b:f3:51:76:d2:e3:f4:37:ea:25:
         a6:f2:cc:54:d3:ec:98:d6:01:f0:16:fa:01:d9:27:58:53:39:
         37:21:3f:1e:91:e3:8c:3d:32:66:ca:c5:0c:cb:42:c7:44:e4:
         5e:70:43:9b
WARNING: no nonce in response
Response verify OK
2388791592.crt: revoked
        This Update: Mar  6 23:00:00 2020 GMT
        Next Update: Mar 13 23:00:00 2020 GMT
        Reason: (UNKNOWN)
        Revocation Time: Mar  6 23:08:56 2020 GMT

You'll see the time in the “Produced At” line. The revocation reason is “Unknown”, other reasons are defined in the CRL RFC section 5.3.1. Listing a reason is optional.

If you'd use an OCSP responder of a CA that has not issued the certificate, you'd get status “unknown” or “unauthorized” or some other error.

The same can happen if you'd use a wrong issuer certificate which can happen if you'd provide a certificate chain, an intermediate CA certificate and a root CA certificate together in one file, instead of just the one certificate. This can happen if you download your issuer certificate chain from SSL Labs Server Test for example so be careful.

Download server server chain in SSL Labs Server Test

Download server certificate chain in SSL Labs Server Test, not exactly what you need

Updates

July 27, 2024 Added info that Let's Encrypt started supporting CRL in 2022 and that they plan to turn off OCSP around 2025

Michal Špaček

Michal Špaček

I build web applications and I'm into web application security. I like to speak about secure development. My mission is to teach web developers how to build secure and fast web applications and why.

Public trainings

Come to my public trainings, everybody's welcome: