# Revocation — OCSP and CRLs

A CRL is a signed list of revoked certificates that a client downloads in full; OCSP is a request asking a CA about one specific certificate. OCSP stapling improves on both by having the server fetch the answer itself and include it in the handshake, so the client makes no extra request. In practice browsers treat revocation checks as soft-fail — if the check cannot be completed they proceed anyway — which means revocation is far weaker than it appears, and the industry has responded by shortening certificate lifetimes instead.

Source: https://certguru.io/concepts/ocsp-vs-crl/
Last updated: 2026-08-19
Commands verified against OpenSSL 3.5.7.

---

## The two mechanisms

|  | CRL | OCSP |
| --- | --- | --- |
| Shape | A signed list of every revoked serial | A query about one certificate |
| Fetched by | The client, in full | The client, per certificate |
| Size | Can reach megabytes | A few hundred bytes |
| Freshness | Whatever the CRL's update interval is | Near real time |
| Privacy | Reveals nothing about which site you visit | Tells the CA which site you are visiting |

Where to find them, in the certificate itself:

```bash
openssl x509 -in certificate.crt -noout -ext crlDistributionPoints -ext authorityInfoAccess
```

Expected output:

```
X509v3 CRL Distribution Points:
    Full Name:
      URI:http://crl.example-ca.com/intermediate.crl
Authority Information Access:
    OCSP - URI:http://ocsp.example-ca.com
    CA Issuers - URI:http://crt.example-ca.com/intermediate.der
```

## Querying OCSP by hand

*Ask the CA about a specific certificate*

```bash
openssl ocsp -issuer chain.crt -cert certificate.crt \
  -url http://ocsp.example-ca.com \
  -header "Host=ocsp.example-ca.com" -no_nonce -text
```

Expected output:

```
certificate.crt: good
    This Update: Aug 19 10:00:00 2026 GMT
    Next Update: Aug 26 10:00:00 2026 GMT
```

`good`, `revoked` or `unknown`. The third is the interesting one — a responder that does not
recognise the certificate returns `unknown`, and most clients treat that as acceptable.

## Reading a CRL

*Download and inspect*

```bash
curl -sO http://crl.example-ca.com/intermediate.crl
openssl crl -inform der -in intermediate.crl -noout -text | head -n 20
```

CRLs are usually DER, so `-inform der` is normally required — see
[DER to PEM](/convert/der-to-pem/).

## Why neither really protects you

Browsers check revocation on a **soft-fail** basis: if the responder is slow, unreachable, or
returns `unknown`, the connection proceeds. That has to be the default, because hard-fail would take
a site offline whenever its CA had an outage.

But it means an attacker who has stolen a private key and can also interfere with the network —
which is the same position they need to be in to use the key — can simply block the revocation check
and the browser will accept the revoked certificate.

Chrome largely sidesteps the mechanism entirely, distributing its own curated revocation list
(CRLSets) rather than making live checks. Firefox uses CRLite. Both are pushed with browser updates.

> **What actually changed**
>
> Because revocation cannot be relied on, the industry shortened certificate lifetimes instead —
>   from three years, to two, to one, and continuing downward. A certificate that expires in weeks
>   limits the damage from a compromise regardless of whether anyone can revoke it.

## Enable OCSP stapling

It is the one piece of this that is unambiguously worth configuring:

#### nginx

```nginx
ssl_stapling            on;
ssl_stapling_verify     on;
ssl_trusted_certificate /etc/ssl/certs/chain.crt;
resolver                1.1.1.1 8.8.8.8 valid=300s;
```

    `ssl_trusted_certificate` must be the intermediates, not the full chain file.

#### Apache

```apache
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
```

    `SSLStaplingCache` belongs at server scope, not inside a `VirtualHost`.

*Confirm a response is being stapled*

```bash
openssl s_client -connect example.com:443 -servername example.com -status /dev/null \
  | grep -A2 "OCSP Response Status"
```

Expected output:

```
OCSP Response Status: successful (0x0)
Cert Status: good
```

`OCSP response: no response sent` means stapling is not working — usually a missing
`ssl_trusted_certificate` or a resolver the server cannot reach.


## Frequently asked questions

### Does revocation actually work?

Less well than most people assume. Browsers use soft-fail checking, so a client that cannot reach the responder proceeds as if the certificate were valid — which is exactly what an attacker who can block the check would arrange. Short certificate lifetimes are the real mitigation.

### What is OCSP stapling?

The server periodically fetches a signed OCSP response for its own certificate and includes it in the TLS handshake. The client gets a fresh revocation answer with no extra request, no latency cost and no privacy leak to the CA.

### Is stapling worth enabling?

Yes. It removes a round trip, stops leaking which sites a visitor is browsing to the CA, and is a few lines of configuration. There is no real downside beyond needing the intermediate available to the server.

### Why are certificate lifetimes getting shorter?

Because revocation is unreliable. If a compromised certificate cannot be dependably revoked, the next best thing is to make sure it expires soon. That reasoning is what took public certificates from three years to one and continues to push them shorter.


## References

- [RFC 6960: online certificate status protocol](https://www.rfc-editor.org/rfc/rfc6960) — OCSP request and response format
- [RFC 5280: X.509 and CRL profile](https://www.rfc-editor.org/rfc/rfc5280) — the specification every field on a certificate comes from

## Related pages

- https://certguru.io/concepts/certificate-chain/
- https://certguru.io/concepts/root-vs-intermediate-ca/
- https://certguru.io/openssl/view-certificate/
- https://certguru.io/openssl/check-tls-versions-and-ciphers/
- https://certguru.io/platforms/nginx/
- https://certguru.io/errors/certificate-has-expired/

--
CertGuru — https://certguru.io
