Root CA Publisher
On this page
Root CA Publisher is a very small Python service that makes a root certificate authority reachable without making it touchable. It serves two files to anyone who asks — the root certificate and its certificate revocation list — and nothing else. The private key that signs them never comes near it: certificates for intermediate authorities and every new revocation list are signed on a host that is not connected to any network, and only the signed results are carried to the publisher.
I built it because a root CA has two needs that pull in opposite directions. Every validator in the world must be able to fetch its revocation list at the address written into the certificates below it, at any hour; and its key must be impossible to steal, which means it must not live on a machine the internet can reach. Splitting the root into an offline signer and an online publisher satisfies both, and the publisher is small enough to trust at a glance.
At a glance
| Language & framework | Python, with Flask |
|---|---|
| Architecture | Transaction Script Service |
| Version | 2.11.2 |
| Status | Stable, in production |
| Form | A publish-only HTTP service, shipped as a single executable, reusable by any project with its own certificate authority |
| Source code | Private |
What it does
A. Publishes the root certificate
The root certificate is served in DER at the root address, which is where the certificates of the intermediate authorities point when they tell a validator where to find their issuer.
B. Publishes the revocation list
The root's certificate revocation list is served at the address written into every intermediate certificate as its CRL distribution point. A validator that checks a signature walks up the chain, reaches an intermediate, and asks this service whether the root has revoked it.
C. Takes a new revocation list without a new release
The revocation list is read from a file mounted into the container. When the offline host signs a new list, the file is replaced and the next request serves it — no rebuild, no restart, no change to the service.
D. Reports that it is alive
A minimal health endpoint lets the container platform, and the services that depend on the root, see that the publisher is up.
Interface
| Capability | Purpose |
|---|---|
| Root certificate | in DER, as application/pkix-cert |
| Revocation list | the root's revocation list in DER, as application/pkix-crl |
| Liveness | for the container platform |
A validator, or an operator checking when the list must next be replaced, reads it with standard tools, here against a placeholder host:
Standards
| Standard | What it guarantees here |
|---|---|
| X.509 and RFC 5280 | a root certificate and revocation list that any validator can parse |
| CRL Distribution Points and Authority Information Access | the addresses written into each intermediate certificate lead straight to this service |
| RFC 2585 | the media types validators expect for certificates and revocation lists served over HTTP |
| DER encoding | the binary form validators fetch, byte for byte as the offline host signed it |
Inside
The service is a Transaction Script Service in its smallest form: one Flask file in which each endpoint is a short procedure — read the file, wrap it in the right response — and one helper module that knows how certificates and revocation lists must be served. It is bundled into a single executable together with the root certificate, so the container carries no source code.
Design decisions
The root key lives offline, and the publisher cannot sign anything. A root authority's key is the one secret that, if stolen, lets an attacker mint trust for everything below it, and the only reliable way to keep a key from the internet is to keep it on a machine that is never connected. So the root is split in two. Creating an intermediate authority, revoking one, and producing a new revocation list all happen on an offline host; the publisher holds no key, exposes no endpoint that writes, and cannot be persuaded to sign. Compromising it would let someone serve a stale list, but never a forged one, because validators check the signature the offline host made.
The certificate is part of the build; the revocation list is not. The root certificate changes once in two decades, so it is bundled into the executable and cannot drift from the image that serves it. The revocation list changes on a schedule, so it is a mounted file: replacing it is an operational task done without touching the service, and the offline host's output is published exactly as it was signed.
A revocation list with a deadline sets the rhythm of the offline ceremony. Each list the offline host signs is valid for ninety days. A validator that finds the list past its next-update date treats the whole chain under the root as unverifiable, so replacing the list well before that date is a recurring duty, not an emergency step. Ninety days means the offline host is needed only a few times a year, while a revocation still reaches every validator within a bounded time.
Served exactly the way validators expect, over plain HTTP. Certificates and revocation lists are served in DER with the media types defined for them, an explicit length, and a header that stops browsers from guessing a different type. The addresses written into the certificates are plain HTTP, as they are for the authorities beneath this root: checking revocation over TLS would require checking the TLS certificate's revocation first, a loop validators avoid, and the files are signed, so the transport does not need to vouch for them.
Small enough to reuse anywhere a CA is needed. Nothing in the service is specific to one project: it serves whatever root certificate it was built with and whatever revocation list it is given. The same publisher fits a document-signing hierarchy today and a VPN's certificate authority tomorrow, with the root and the addresses as the only things that change.
Specifications
| Inputs | The root certificate, bundled at build time; the revocation list, as a mounted DER file replaced by the operator |
|---|---|
| Outputs | The root certificate and revocation list in DER, with RFC 2585 media types |
| Signing | None: the root key and all signing stay on an offline host |
| Hierarchy it serves | A root valid for twenty years that issues intermediate authorities, each limited to issuing end certificates only; SHA-256 signatures |
| Revocation list lifetime | Ninety days per list, replaced before it expires |
| Runs as | A single executable in a multi-stage container image, with the revocation list mounted from a volume |
Related
The intermediate authority for signing certificates, issued by this root and checked against its revocation list.
The intermediate authority for timestamps, under the same root.
The signer that fetches this revocation list before every signature, so the proof embedded in each PDF is complete.
Terms
- Root certificate authority
- The authority at the top of a certificate hierarchy, whose certificate validators trust directly and which signs the authorities below it.
- Offline root
- A root authority whose private key is kept on a machine never connected to a network, used only when something must be signed.
- Certificate revocation list
- A signed list of certificates an authority has revoked, valid until a stated next-update time.
- CRL distribution point
- The address written into a certificate where validators can fetch the revocation list of the authority that issued it.
- DER
- The binary encoding in which certificates and revocation lists are signed and exchanged.
Technologies covered
- Python
- Flask
- X.509