# Per-agent CA

**One certificate authority per identity — blast radius of exactly one.**

Every shared certificate authority is a single point of failure wearing a trust badge: compromise its signing key once and every certificate it ever issued is suspect, all at the same moment. That is the original sin of the CA model — it does not matter how careful the ten thousand leaf holders were, because none of them controlled the thing that actually failed. When your fleet is a thousand short-lived agents instead of a handful of long-lived servers, that shared blast radius is not a tail risk, it is the whole risk. Whisper answers it structurally: the credential that actually gets checked at connection time is never shared between two identities, so there is no single key whose loss ever cascades.

## The shared-CA problem, precisely

In classic X.509 (RFC 5280), a browser or client trusts a small set of root CAs; each root signs intermediates, each intermediate signs leaf certificates, and the client's trust decision is really "do I trust *some* CA in this chain." That's the whole model's leverage and its whole liability: one root or intermediate key covers an enormous population of unrelated leaves. Steal it, and you can mint a convincing certificate for *any* of them — DigiNotar (2011) and Comodo's registration-authority breach (2011) are the canonical case studies of exactly this failure mode. The chain is only as strong as the single key everyone shares.

## What Whisper does instead

Whisper gives every agent identity a certificate whose validity, at the point a peer actually checks it, does not depend on anyone else's key:

- **A leaf key minted per address, not stored at rest.** The certificate for an agent's own name is generated on demand for that specific `/128` and is not kept lying around as a long-lived secret to steal later — there is no vault of ten thousand private keys for an attacker to go after.
- **Pinned in the DNS, at the agent's own name.** The exact key an agent is allowed to present is published as a [`TLSA`](/docs/dane) record (DANE-EE, usage `3 1 1`, RFC 6698) directly under that agent's own DNSSEC-signed name — not in a shared bundle, not in a CA's certificate-transparency log you have to cross-reference. A verifier's real trust decision reduces to "does the presented key match *this one name's* pin," which is a question about a single record, not a shared root.
- **A public root exists purely for interoperability**, not because you need it. `whisper-ca.pem` / `whisper-ca-chain.pem` are published for stacks that only know how to trust a CA bundle (`NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, a Java truststore). But the trustless path never touches it: DANE lets you validate the exact leaf key independently, anchored at the IANA root via DNSSEC, with no CA in the loop at all. Because the interoperability root is optional rather than load-bearing, a compromise of *it* still doesn't buy an attacker anything against a DANE-validating peer — the per-name pin is what actually gets checked.

The practical result is the property the name promises: each identity's trust anchor is scoped to that identity alone. Compromise one agent's key and you have compromised **that agent** — not the thousand others sharing the same infrastructure, because there was never a shared secret protecting more than one of them in the first place.

## Make-before-break rotation, TTL-speed revocation

Because the pin lives in DNS rather than a certificate-revocation list or an OCSP responder, both lifecycle operations are just DNS operations:

- **Rotation** publishes the new `TLSA` record alongside the old one before the old key stops being presented — make-before-break, so a client mid-handshake never sees a hole. Once the new pin has propagated, the old record is withdrawn. No re-issuance ceremony, no CA round-trip.
- **Revocation** is a single record change. It is live everywhere the moment the record's TTL expires — no CRL fetch, no OCSP stapling to get right, no soft-fail fallback for clients that couldn't reach a revocation server. `CALL whisper.agents({op:'revoke', ...})` tears down the address, the DNS, the DANE pin, and egress together, in one step.

> Because the identity's authority is DANE-pinned, an agent's certificate is **self-proving**: a client validates it against the DNS, not against a public CA list. See [mTLS & DPoP](/docs/egress-auth) for how this pin becomes the credential an agent presents on egress.

## Inspect the pin — dual path

**With stock tools** (no Whisper software — just DNSSEC + TLS):

```bash
# the TLSA record the agent's leaf must match, DNSSEC-signed
dig TLSA _443._tcp.acef2002a323d40d4.demo.agents.whisper.online +dnssec +short
# 3 1 1 b653a4ef...fcb82d1d

# does the connection actually present that key?
openssl s_client -connect acef2002a323d40d4.demo.agents.whisper.online:443 \
  -dane_tlsa_domain acef2002a323d40d4.demo.agents.whisper.online \
  -dane_tlsa_rrdata "3 1 1 b653a4ef...fcb82d1d" </dev/null

# or, if you'd rather trust a bundle than DANE:
curl -s https://whisper.online/.well-known/whisper-ca.json    # SHA-256 fingerprints
curl -o whisper-ca.pem https://whisper.online/.well-known/whisper-ca.pem
NODE_EXTRA_CA_CERTS=./whisper-ca.pem node your-client.js
```

`openssl`'s own `-dane_tlsa_rrdata` flag does the RFC 6698 comparison for you — match means the certificate is exactly the one the DNS promised; anything else is a hard failure, not a warning.

**With Whisper** (the CLI runs every check above itself and adds a signed proof):

```bash
whisper verify --trustless 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# re-derives the PTR, AAAA, TLSA, RDAP and DNSSEC chain itself,
# anchored at the IANA root — the Whisper API is never consulted or trusted
```

`verify --trustless` is the keyless, adversary-proof path: it doesn't ask `graph.whisper.security` whether an identity is legitimate, it reconstructs the chain of DNSSEC signatures and the DANE pin itself and reports the verdict. See [Verify an agent](/docs/verify) for the full output shape and [Trustless identity](/docs/verifiable-identity) for why that independence matters.

## Shared CA vs. per-agent pin

| | Shared CA (classic X.509) | Whisper per-agent pin |
|---|---|---|
| Key an attacker needs | one root/intermediate, for the whole fleet | one leaf key, for one identity only |
| Blast radius of a key compromise | every certificate under that CA | exactly one agent |
| Revocation | CRL / OCSP, soft-fail prone | one DNS record, TTL-speed, everywhere at once |
| Rotation | re-issuance through the CA | a new `TLSA` record, make-before-break |
| Verification anchor | a CA trust store you must maintain | DNSSEC chain to the IANA root (no store to maintain) |

## Next

[DANE & DNSSEC](/docs/dane) — the signed-chain mechanics the per-agent pin relies on · [mTLS & DPoP](/docs/egress-auth) — how the pinned certificate becomes an egress credential
