# Agent-to-agent trust

**Two agents that have never met, on two different platforms, with no shared account — one has to decide, right now, whether to let the other in. There is no broker to call.**

That's the moment every A2A framework, MCP server, and agent marketplace eventually hits, and most of them solve it badly: a bearer token pasted into a prompt (stealable, un-revocable at scale), an out-of-band handshake that only works between two agents built by the same vendor, or nothing at all — just trusting whatever the caller claims about itself. Self-assertion is worthless as a trust primitive: a hostile agent will happily assert it's friendly. You need a fact about the caller that it cannot fabricate, checkable by a third party neither side controls. That fact already exists for every device on the internet — it's called an address — Whisper just makes an agent's address a full, cryptographically checkable identity.

## Why "just add a shared secret" doesn't scale

- **No common root.** Agent A's platform and Agent B's platform have no shared PKI, no mutual registration, no broker either was introduced to. A marketplace routing between hundreds of agents from different vendors can't pre-share a secret with all of them.
- **Self-assertion is worthless.** A calling agent that says "I'm the finance-approval agent, trust me" is indistinguishable from an attacker saying the same thing. Verification cannot depend on asking the counterparty about itself.
- **Static credentials don't revoke well.** A bearer token copied into three other services can't be un-copied. Trust needs to attach to something the network itself can retract.

## The fix: identity anchored where nobody has to trust Whisper for it

Every agent provisioned on Whisper gets a real, routable IPv6 /128 out of `2a04:2a01::/32` (announced by our own `AS219419`), and that address *is* the identity: forward DNS, reverse DNS, a DANE `TLSA` record under DNSSEC, and an RDAP registration all resolve to the same name, all independently checkable with tools that predate Whisper by decades. The verifying agent doesn't ask the caller who it is — it asks the internet's own infrastructure, which the caller cannot lie to.

The mechanism, precisely:

1. **Forward-confirmed reverse DNS (FCrDNS).** The caller's source `/128` reverse-resolves via `PTR` (`ip6.arpa`, [RFC 3596](https://www.rfc-editor.org/rfc/rfc3596)) to a name; that name's `AAAA` record must resolve back to the same address. This closed loop is the same technique mail servers have used to fight spoofing since the 1990s — an attacker can forge a source address, but it cannot make an arbitrary PTR chain agree with it under DNSSEC.
2. **DNSSEC** ([RFC 4035](https://www.rfc-editor.org/rfc/rfc4035)) signs every one of those records back to the IANA root, so a validating resolver returns `AD=1` — the chain isn't Whisper's word, it's the same trust anchor your OS already ships.
3. **DANE `TLSA`** ([RFC 6698](https://www.rfc-editor.org/rfc/rfc6698)) pins the agent's actual TLS certificate (or key) in DNS, so a peer can validate the handshake without any CA — `_443._tcp.<fqdn> TLSA 3 1 1 <sha256>` is usage 3 (DANE-EE), selector 1 (SubjectPublicKeyInfo), matching type 1 (SHA-256).
4. **RDAP** ([RFC 9083](https://www.rfc-editor.org/rfc/rfc9083)) gives the registration record for the `/128` itself — who it was issued to, when, and its current status — the modern, JSON successor to WHOIS ([RFC 3912](https://www.rfc-editor.org/rfc/rfc3912)), which we also still serve for anything that only speaks the old protocol.
5. A **transparency log** ([RFC 6962](https://www.rfc-editor.org/rfc/rfc6962)-style Merkle tree, served as C2SP tlog-tiles) records the issuance event itself, so "was this identity ever legitimately minted, and is it still valid" is provable with an inclusion proof, not a promise.

## Verify a peer: two ways to the same answer

**With stock tools** — no Whisper software, just what's already on the box:

```bash
# 1. reverse DNS: who does the calling address claim to be?
dig -x 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 +short
# -> acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online.

# 2. forward-confirm it: does that name resolve back to the same address?
dig +short AAAA acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
# -> 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4   (FCrDNS closed)

# 3. pin its TLS key via DANE, no CA required
dig +short TLSA _443._tcp.acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
# -> 3 1 1 b653a4ef...fcb82d1d

# 4. registration record (RFC 9083)
curl -s https://rdap.whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 | jq .status

# 5. legacy WHOIS (RFC 3912), same record
whois -h whois.whisper.online 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
```

Every `dig` answer above should validate `AD=1` on a DNSSEC-aware resolver (`+dnssec` against `1.1.1.1` or `8.8.8.8` if your own doesn't set the flag) — that's the part no one can fake.

**With Whisper**, the same five checks collapse into one call, and a sixth mode re-derives the whole chain client-side so *the caller doesn't even have to trust Whisper's API*:

```bash
# keyless: one call, full verdict — safe to run against ANY /128, agent or not
curl -s https://rdap.whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 \
  | jq '{is_whisper_agent, dane_ok, jws_ok, evidence}'

# a non-agent target returns a clean false, never an error:
# {"is_whisper_agent": false}

# trustless: the CLI redoes DNSSEC validation itself, anchored at the IANA root —
# Whisper's own API is not in the trust path at all
whisper verify --trustless 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
```

`verify-identity` accepts either the address or the FQDN, which matters for a marketplace router that only sees a hostname in a manifest. Both paths are keyless — an MCP server checking a client's identity, or an agent checking a peer's, never needs a Whisper API key to *verify*; the key only gates provisioning and control (see [Control plane](/docs/control-plane)).

## See who verified you

Trust is observable from both ends, not just asserted by the verifier. Every issuance and revocation event lands in the public transparency log, and any agent's history — including how many times its identity has been checked — is fetchable with an inclusion proof against the current signed checkpoint:

```bash
curl -s https://rdap.whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4/transparency
curl -s https://whisper.online/checkpoint      # signed root: origin, tree_size, root_hash, Ed25519 sig
```

The leaf/interior construction follows RFC 6962 domain separation (`leaf = sha256(0x00‖sha256(salt‖event))`, interior nodes `sha256(0x01‖left‖right)`), so any party can recompute a proof by hand without trusting Whisper to have summarized it honestly. Full mechanics: [Transparency log](/docs/transparency).

## Verify is not authorize

Confirming identity answers *who* — it doesn't answer *should this call proceed*. Once a peer is confirmed, gate the actual request on the resolved name: exact match for a single trusted peer, a subdomain for a whole team's agents, or a wildcard for "any Whisper-issued agent, don't care who." That policy layer — reverse-proxy `map` blocks, application-level allowlists, or `whisper.agents({op:'policy'})` — is covered in full in [Access control](/docs/access-control); this page is the handshake that makes that policy trustworthy in the first place.

> For A2A frameworks, MCP servers, and agent marketplaces: put `verify-identity` (or `whisper verify`) in front of every inbound connection before your business logic runs. It costs one HTTP round trip and turns "trust me" into a fact anyone downstream can re-check.

---

**Next:** [Access control](/docs/access-control) — authorize by name, subdomain, or wildcard once a peer is verified · [Verify an agent](/docs/verify) — the full identity model behind `verify-identity`.
