CRLite+
A Chrome extension that checks TLS certificate revocation locally, using Bloom filters.
Contents
The problem
Browsers have two standard ways to learn that a certificate was revoked. CRLs are large and updated slowly. OCSP asks the certificate authority about every site you visit, which adds latency and tells the CA where you browse. Firefox ships CRLite, which avoids both by checking a local filter. Chromium browsers have nothing like it.
Mozilla's CRLite shows that local Bloom filter checks work. This project asks whether the same idea fits in a Chrome extension.
Approach
Revoked certificates live in cascaded Bloom filters: one filter for revoked serial numbers and one for known-good ones, which removes the false positives a single Bloom filter would give. The extension checks every certificate against them locally, so there are no network calls and nothing about your browsing leaves the machine.
- Static filters cover the revocations we already know about and are built ahead of time.
- A smaller dynamic filter handles updates between rebuilds, so a new revocation does not wait for a full regeneration.
- Checks run in the browser: the extension reads the certificate, looks it up, and blocks the page if it is revoked.
Requirements
What the design had to satisfy
I started by reading how CRLs and OCSP fall short and how CRLite's cascade works, then wrote down what the extension had to do.
- Fast: a check in under 10 ms, so pages do not feel slower.
- Private: no network round trip per site.
- Small: filters well under 1 MB, so they fit in a browser extension.
- Compatible: runs on Chromium under Manifest V3.
- Accurate: catches every revoked certificate it knows about, without blocking good ones.
Architecture
Three parts that can be built and tuned on their own
A Python script generates the filter cascades. A Node.js backend retrieves certificates and keeps the revocation lists. The Chrome extension does the lookup in the browser. The filters use MurmurHash3 for speed and SHA-256 to hash certificate identifiers.
Keeping the parts separate means the filter generator can change without touching the extension.
Data pipeline
From certificate to filter to browser
- The Node.js backend opens raw TLS connections, pulls out each certificate's serial number and hashes it with SHA-256.
- It keeps the revocation lists up to date.
- The Python script reads those lists and generates the cascaded filters offline.
- The extension loads the static filters and asks a small JSON endpoint for dynamic updates, so new revocations do not need a full rebuild.
Implementation
- Extension: reads the certificate during the TLS handshake, looks it up in the cascade (revoked filter first, then the known-good one), and blocks the domain if it is revoked.
- Backend: raw TLS connections, certificate extraction and the revocation list, served over a REST API.
- Python: filter generation with configurable parameters.

Evaluation
What I measured
I simulated revocations by adding domains I trust, like github.com and uic.blackboard.com, to the revoked list and checking that the extension blocked them end to end. I tuned the filter parameters across a few rounds to shrink memory.
- revoked certificates caught in my tests
- 100%
- per check
- 2 to 5 ms
- false positives
- 0
- static / dynamic filters
- < 512 KB / < 200 KB
These are results on simulated revocations. I have not tested against live CA feeds.
Not done yet
- Real CA feeds, converted from live CRL and OCSP data.
- Revocations of intermediate CAs.
- Native browser integration instead of an extension.
- A transparency log for revocations.

