Whisper · Docs
Recipes

The address as a universal anchor

One /128 you already hold exclusively can anchor every key, wallet, endpoint, and claim an agent has — checkable by a stranger with dig and zero accounts, forever.

Every team building agents eventually reinvents the same bad wheel: "how does someone verify this agent's payout wallet is really its wallet?" gets a Discord pin. "How does someone verify this is really the agent's SSH host key?" gets a Slack message and a screenshot. "How does someone verify this output actually came from the agent and wasn't edited after?" gets nothing at all — you just trust the log you were handed. Each of these is the same problem — bind a piece of data to an identity so a third party can check it without asking you — solved a different, worse way every time: a verified badge that only means something inside one platform, a tweet that disappears, a support ticket that says "yes that's really us." None of it survives the platform going away, and none of it is checkable by a machine.

DNS already solved this, generically, decades ago: publish a record at a name, sign the zone, let anyone with a resolver check it. Whisper's contribution isn't a new primitive — it's giving every agent a name it can publish records at, for free, the moment it exists. This page is the generalized pattern behind DANE, did:web, and RDAP individually — read together, they stop looking like three unrelated specs and start looking like one anchor with three doors.

The pattern, stated once

Three ingredients, always the same shape, no matter what you're pinning:

  1. A name that's provably yours. Whisper derives it mechanically from the address — see Identity for the five-step transform — so the name isn't a label in someone's database, it's a pure function of a /128 you hold exclusively out of 2a04:2a01::/32 (AS219419).
  2. A record — or a signed document — published under that name. TLSA for a TLS key, SSHFP for an SSH key, OPENPGPKEY for a PGP key, SRV/URI for an endpoint; or, for a richer claim (a wallet, a capability), a signed JSON document served over HTTPS at a did:web well-known path — still at your name, still anchored by the same DNSSEC chain and DANE-pinned TLS key. The container is just a container — the property that matters is that it lives at your name.
  3. DNSSEC signs the whole thing to the root. One chain of trust, RFC 4033–4035, the same chain that already proves the address is yours now proves the record is too — no separate PKI, no separate account, no separate "verified" badge to maintain.

Anyone who wants to check the pin does the same three-step read in reverse: resolve the name, validate the RRSIG to the IANA root, compare the payload. No API call to Whisper is required at any point — that's the keyless half of the two-tier design every Whisper surface follows (see Verify an agent).

Why this generalizes. A TLSA record is a key pin. A TXT record with a wallet address is an asset pin. A TXT record with a content hash is a provenance pin. They're all "a signed pointer at a name you own" — once you see the shared shape, you stop asking "does Whisper support pinning wallets?" and start asking "what haven't I pinned yet?"

Applying it: three concrete pins

1. A TLS key — the pin you already have

Every Whisper agent gets this one automatically. A TLSA record at _443._tcp.<name> pins the exact SPKI hash a client must see in the TLS handshake — no CA, no trust store, per RFC 6698. Full mechanism in DANE & TLSA; the short version:

# With stock tools
dig +short TLSA _443._tcp.acef2002a323d40d4.demo.agents.whisper.online
# 3 1 1 b653a4ef...fcb82d1d
# With Whisper
whisper verify --trustless acef2002a323d40d4.demo.agents.whisper.online
# dane   pass   DNSSEC-root   served leaf SPKI-SHA256 == TLSA pin

2. A payout wallet — the pin nobody's automating yet

An agent that gets paid needs a wallet address bound to its identity strongly enough that a counterparty doesn't have to trust a chat message. Publish it as a Verifiable Credential — a compact ES256 JWS whose issuer and subject are the agent's own did:web, signed with the same P-256 key family that backs its TLSA pin — served as a static file next to the agent's did.json:

https://acef2002a323d40d4.demo.agents.whisper.online/.well-known/wallets/eip155-1.jwt
# JWS payload: {"iss":"did:web:acef2002a…","vc":{"type":["VerifiableCredential","AgentWallet"],
#   "credentialSubject":{"chain":"eip155:1","address":"0x9F2b...c41A","purpose":"treasury"}}}

Because the signing key is the same key DANE pins under _443._tcp.<name>, the wallet claim inherits DNSSEC's chain and is independently signed by a key a verifier already trusts for a different reason. Two unrelated proofs pointing at the same identity is exactly the redundancy Identity is built on: forging the wallet binding means forging the identity underneath it — DNSSEC, DANE, and reverse DNS all have to lie in agreement, not guessing which Discord post is real.

# With stock tools — fetch the credential and the did:web key, verify the JWS with any JOSE library
curl -s https://acef2002a323d40d4.demo.agents.whisper.online/.well-known/did.json | jq '.verificationMethod[0].publicKeyJwk'
curl -s https://acef2002a323d40d4.demo.agents.whisper.online/.well-known/wallets/eip155-1.jwt
# then, in any JOSE library: jws.verify(credential, publicKeyJwk, algorithms=["ES256"])
# With Whisper — one call re-derives PTR/AAAA/TLSA/did:web from the IANA root, then folds the
# credential's ES256 signature check into that same chain walk — Whisper's API never in the trust path
whisper verify --trustless --credential ./eip155-1.jwt acef2002a323d40d4.demo.agents.whisper.online

The complete publish-and-verify recipe — including which key signs, how to rotate it, and how a payer checks it in CI before a transfer — is its own page: Pin a wallet.

3. A signed output — provenance without a platform

The hardest version of this problem: "prove this document/commit/API response actually came from this agent, at this address, and hasn't been altered since." The pattern is identical — sign a manifest (a content hash plus the issuer's did:web) with the agent's key as a detached JWS sidecar (report.md.jws), and let a verifier walk the same DANE-anchored key back to the address that produced it. (Use a JOSE library, not raw openssl, for the signature: ES256 is a 64-byte raw R‖S, not the DER OpenSSL emits.) Combined with OpenTimestamps's Bitcoin anchoring, you additionally get when — a claim that can't be back-dated by the agent, its operator, or Whisper.

# With stock tools — resolve the key from did:web, verify the detached JWS with any JOSE library
curl -s https://acef2002a323d40d4.demo.agents.whisper.online/.well-known/did.json | jq '.verificationMethod[0].publicKeyJwk'
# then: token.verify(publicKeyJwk, alg="ES256"); assert claim.sha256 == sha256(output.json)
# With Whisper — anchor the key to the DNSSEC root with one call, then hand it to the local check;
# a forged or MITM'd did.json fails closed instead of validating a forged signature against a forged key
whisper verify --trustless acef2002a323d40d4.demo.agents.whisper.online && python3 verify_output.py

Full mechanism, including how the signing key relates to the agent's per-agent CA leaf and how to structure a batch of outputs into one Merkle-anchored proof instead of one signature per file, lives at Sign agent outputs.

Why "anything" isn't hyperbole

Once a name is provably yours and DNSSEC signs whatever you put under it, the set of things you can pin is bounded only by imagination and record-type ergonomics, not by anything Whisper has to build per-asset:

Want to pin… Record Verifier does
A TLS/mTLS key TLSA at _443._tcp.<name> SPKI-SHA256 compare, RFC 6698
A wallet / payout address ES256 JWS credential at /.well-known/wallets/<chain>.jwt fetch + JWS check vs did:web key, see Pin a wallet
An SSH host key SSHFP at <name> RFC 4255, ssh -o VerifyHostKeyDNS=yes
A capability manifest / DID document did:web doc at <name>/.well-known/did.json fetch + JWS check, see did:web
A signed output or dataset hash detached JWS sidecar (<file>.jws) key-fetch via did:web/DANE, then signature verify, see Sign agent outputs
A PGP/age key for encrypted intake OPENPGPKEY at <hash>._openpgpkey.<name> RFC 7929

None of these need a new Whisper feature to exist as a conceptSSHFP and OPENPGPKEY are RFCs that predate Whisper by over a decade, sitting unused because nobody had a name worth publishing them under. An agent's Whisper address gives it that name for free the moment it's provisioned:

CALL whisper.agents({op:'register', args:{label:'my-agent'}})

— one control-plane call (Control plane) allocates the /128, which derives the name, which is now a place you can publish anything DNSSEC can sign. Whisper ships the TLS pin and the did:web document automatically; wallets, output signatures, and anything else in the table above are yours to add at the same name, using the same key, checked the same keyless way.

Next