# 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 came from the agent and wasn't edited after?" — gets nothing; you just trust the log you were handed.

Each 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](/docs/dane), [`did:web`](/docs/did-web), and [RDAP](/docs/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](/docs/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](https://www.rfc-editor.org/rfc/rfc4035), 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](/docs/verify)).

> **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](https://www.rfc-editor.org/rfc/rfc6698). Full mechanism in [DANE & TLSA](/docs/dane); the short version:

```bash
# With stock tools
dig +short TLSA _443._tcp.acef2002a323d40d4.demo.agents.whisper.online
# 3 1 1 b653a4ef...fcb82d1d
```

```bash
# 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](/docs/identity#the-seven-proofs-and-an-eighth-trustless-one) 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.

```bash
# 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"])
```

```bash
# 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](/docs/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](/docs/opentimestamps)'s Bitcoin anchoring, you additionally get *when* — a claim that can't be back-dated by the agent, its operator, or Whisper.

```bash
# 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)
```

```bash
# 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](/docs/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](/docs/sign-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](https://www.rfc-editor.org/rfc/rfc6698) |
| A wallet / payout address | ES256 JWS credential at `/.well-known/wallets/<chain>.jwt` | fetch + JWS check vs `did:web` key, see [Pin a wallet](/docs/pin-a-wallet) |
| An SSH host key | `SSHFP` at `<name>` | [RFC 4255](https://www.rfc-editor.org/rfc/rfc4255), `ssh -o VerifyHostKeyDNS=yes` |
| A capability manifest / DID document | `did:web` doc at `<name>/.well-known/did.json` | fetch + JWS check, see [`did:web`](/docs/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](/docs/sign-outputs) |
| A PGP/age key for encrypted intake | `OPENPGPKEY` at `<hash>._openpgpkey.<name>` | [RFC 7929](https://www.rfc-editor.org/rfc/rfc7929) |

None of these need a new Whisper feature to exist as a *concept* — `SSHFP` 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](/docs/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

- [Pin a wallet](/docs/pin-a-wallet) — the full publish-and-verify recipe for a payout address
- [Sign agent outputs](/docs/sign-outputs) — provenance and non-repudiation for what an agent produces
- [Identity](/docs/identity) — how the name is derived from the address and why the proofs stack
