# Verifiable agent identity

**Give every agent an identity anyone can verify — no leaky API keys.**

## The pain: an API key proves a string, not an identity

Every agent platform you've used answers "who is this agent?" with a bearer token. That answer is wrong in three ways, and they compound:

- **A leaked key *is* identity theft.** One log line, one careless `curl -v`, one committed `.env`, and whoever holds the string now **is** your agent — indistinguishable from the real one, until you notice and rotate.
- **The token only means something to its issuer.** Hand your key's traffic to a partner's firewall and they can't confirm which agent, or whose, is on the other end. They trust your say-so, or trust nothing.
- **Nobody outside your backend can check it at all.** A shared secret doesn't compose across organizational boundaries — exactly the boundary agent-to-agent traffic crosses constantly.

This is fine when you have three agents and one internal dashboard. It stops being fine at a hundred agents talking to services you don't operate, and it's actively dangerous at a thousand, because the blast radius of one leaked key is "everything that key could do," forever, until someone notices.

Whisper's fix is structural, not procedural: **the agent's address *is* its identity.** Every agent gets a real, routable IPv6 `/128` out of `2a04:2a01::/32` (announced by `AS219419`), anchored in signed DNS and a public registry — not a bearer token a relying party has to phone home to check. Anyone, with zero credentials and stock tools already in their terminal, can ask "is `2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de` a real Whisper agent, right now?" and get a cryptographically checkable answer. No API key changes hands to verify it. That's the whole point — verification and authorization are two different problems, and Whisper doesn't force you to leak a secret to solve the first one.

## The mechanism: seven keyless proofs, one address

An identity claim is only as good as the number of independent ways it can be checked. Whisper gives you seven, all rooted in open standards, all keyless, all checkable by a stranger who has never heard of Whisper before:

| # | Proof | Standard | What it shows |
|---|-------|----------|----------------|
| 1 | Reverse DNS (PTR) | RFC 1035 | The `/128` resolves back to a name under `agents.whisper.online` |
| 2 | Forward DNS (AAAA) | RFC 1035 | That name resolves forward to the same `/128` — the loop closes |
| 3 | Friendly CNAME | RFC 1035 | A human-chosen label aliases to the same canonical name |
| 4 | DANE TLSA pin | RFC 6698 | The TLS certificate the agent will present is pinned in DNS, under DNSSEC |
| 5 | RDAP record | RFC 9083 | A structured registry record for the `/128` — allocation, org, status |
| 6 | WHOIS record | RFC 3912 | The same registry fact over the decades-old protocol every tool still speaks |
| 7 | Full-chain verdict | Whisper keyless API | One JSON call that runs 1–6 for you and returns a verdict |

Every DNS answer above validates `AD=YES` under DNSSEC on any validating resolver — 1.1.1.1, 8.8.8.8, or your own; that's what makes proofs 1, 2, and 4 tamper-evident in transit, not just plausible. And because these are all just DNS, RDAP, and WHOIS, they degrade gracefully: a non-agent address returns a clean "not an agent," never an opaque error, and a revoked agent's PTR simply stops resolving — the same tools that proved the identity also prove the kill, publicly, without asking you to trust a dashboard.

For anyone who wants to skip re-typing all seven and re-derive the whole chain cryptographically — including a check against a public transparency ledger, so *Whisper's own API* isn't even in the trust path — there's an eighth, higher-level command: `whisper verify --trustless`. It's not a different mechanism, just the same seven proofs, automated and independently re-verified against the DNSSEC root. See [`/docs/dane`](/docs/dane) and [`/docs/transparency`](/docs/transparency) for how the trust anchor and the ledger work underneath it.

## Why an address beats a token

A bearer token is a **capability**: whoever holds it can act. An address anchored in signed DNS is a **fact**: it either resolves, forward and back, under keys the IANA root chain vouches for, or it doesn't. You cannot steal a fact by copying a string — there is no string. Compromising an agent's identity here would mean compromising DNSSEC itself, not grepping a log file. That's a categorically different security posture, and it's why Whisper's control-plane kill switch (`op:revoke`) tears down the address, the DNS records, and the DANE pin as one atomic act — after which every one of the seven proofs above independently confirms the agent is gone, with no token to quietly keep working somewhere.

## With stock tools — no Whisper software at all

Every proof below runs with tools your machine already has:

```bash
# 1: reverse DNS — the /128 resolves back to a name
dig -x 2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de +short
# -> aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online.

# 2: forward DNS — the name resolves back to the same address
dig +short AAAA aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online
# -> 2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de

# 3: friendly CNAME — a human label aliases to the same canonical name
dig +short CNAME scout.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online
# -> aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online.

# 4: DANE — the TLS leaf key this agent will present is pinned in DNS
dig +short TLSA _443._tcp.aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online
# -> 3 1 1 EF48BF1B0A1A9D584F0544E3A5FABA2B66F1234DB9604CDA3464E89F 80B40851

# ...and confirm the chain is DNSSEC-signed, not just present
kdig +dnssec AAAA aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online | grep -i "flags:.*ad"

# 5/6: registry record, two ways
curl -s https://rdap.whisper.online/ip/2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de
whois -h whois.whisper.online 2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de

# 7: the keyless full-chain verdict — no API key required
curl -s https://rdap.whisper.online/verify-identity/2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de | jq .
# -> {"is_whisper_agent": true, "dane_ok": true, "jws_ok": true, "evidence": {...}}
```

A target that isn't a Whisper agent returns `{"is_whisper_agent": false}` — never a 500, never an exception to catch. That's the Postel discipline applied to a verification API: liberal in what you hand it (address or FQDN, agent or not), strict and unambiguous in what it hands back.

## With Whisper — one command, cryptographically re-derived

```bash
whisper verify --trustless 2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de
```

```
✓ PTR   aa98d5d20fd7731de.ta8e69486f260c280b1134c868cc42fef.agents.whisper.online.
✓ AAAA  resolves back to 2a04:2a01:f29c:f6c5:a98d:5d20:fd77:31de
✓ TLSA  3 1 1 EF48BF1B0A1A...3464E89F 80B40851  (DANE-EE, usage 3 1 1)
✓ DNSSEC chain validates to the IANA root (AD=YES, no shortcuts)
✓ RDAP  allocation confirmed, status: active
✓ transparency-log inclusion proof verified (RFC 6962)
VERDICT: cryptographically proven Whisper agent — Whisper's own API not trusted
```

`whisper verify` doesn't call a Whisper "is this real" endpoint and take its word for it — it re-derives every proof itself against the public DNSSEC root and the transparency ledger, which is why it can honestly print "Whisper's own API not trusted." That's the difference between a platform *asserting* an identity and an identity that's independently checkable — the same distinction that separates a bearer token from a signed, resolvable address.

The same verdict is available as a library call for anything you're building — `pip install whisper-id` / `npm i whisper-id` — and as one of the two keyless tools (`verify`, `rdap`) exposed by the public MCP server (`whisper mcp`, registry `io.github.whisper-sec/whisper`), so an LLM agent can check another agent's identity mid-conversation without ever touching a key.

> Registering an agent (minting the address, the DANE pin, and the DNS records in the first place) does need a key — verification never does. See [`/docs/quickstart`](/docs/quickstart) to mint your own identity in one call.

## Next

Continue with [`/docs/dane`](/docs/dane) for exactly how the DANE/DNSSEC trust anchor is built, or [`/docs/transparency`](/docs/transparency) for the public Merkle log that makes every issuance and revocation independently auditable.
