Verify an agent
A Whisper agent carries a verifiable address, not a bearer token — so anyone with dig and curl can check who it is in a second, with no account and without taking Whisper's word for it.
Seven independent, standards-based proofs converge on the same /128. A keyless endpoint runs them for you; an eighth mode re-derives the chain from the IANA DNSSEC root, trusting not even that endpoint. Run every command below against the public demo agent — address 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4, name acef2002a323d40d4.<tenant>.agents.whisper.online — or swap in any address. The mechanism is the same.
Why seven proofs and not one
A single fact is a single point of failure. If "verified" meant only "the forward DNS resolves," whoever compromised one zone could forge an identity outright.
Whisper spreads the claim across separately-populated DNS zones, an X.509 key pin, two registry protocols, and a signed document. An impostor has to win all of them at once — and any mismatch (a PTR whose forward AAAA doesn't point back, a TLSA pin the served cert fails) is visible instantly with stock tools. Identity is the derivation that ties the name to the address; this page is the checklist that proves it held.
Proofs 1–3: reverse, forward, and the friendly alias
# stock tools — no Whisper software anywhere in this block
dig -x 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 +short
# acef2002a323d40d4.<tenant>.agents.whisper.online. <- 1. PTR (RFC 3596 / RFC 1035 §3.3.12)
dig +short AAAA acef2002a323d40d4.<tenant>.agents.whisper.online
# 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 <- 2. forward AAAA (RFC 3596)
dig +short CNAME my-agent.<tenant>.agents.whisper.online
# acef2002a323d40d4.<tenant>.agents.whisper.online. <- 3. friendly alias (RFC 1035 §3.3.1)
Every answer carries AD=YES under DNSSEC on any validating resolver you already run — confirm with dig +dnssec or kdig +dnssec. The load-bearing property: the PTR zone (ip6.arpa) and the forward zone (agents.whisper.online) are two separate delegations, populated from opposite ends of Whisper's authoritative data. Forge one without the other and you get an inconsistency — dig -x names an agent whose AAAA doesn't point back — not a convincing fake.
# with Whisper — one call re-derives and cross-checks 1–3 for you
whisper verify 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
Proof 4: TLSA / DANE — the key pin
# stock tools
dig +dnssec TLSA _443._tcp.acef2002a323d40d4.<tenant>.agents.whisper.online
# ... 300 IN TLSA 3 1 1 b653a4ef...fcb82d1d
openssl s_client -connect acef2002a323d40d4.<tenant>.agents.whisper.online:443 \
-servername acef2002a323d40d4.<tenant>.agents.whisper.online </dev/null 2>/dev/null \
| openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256
# (stdin)= b653a4ef...fcb82d1d <- must equal the TLSA pin
3 1 1 is DANE-EE / SPKI / SHA-256 (RFC 6698, strict profile RFC 7671): the DNS record pins the exact key, no CA consulted. Byte layout and why usage 3 beats a CA chain: DANE & TLSA.
# with Whisper — the same comparison, done for you
whisper verify --trustless acef2002a323d40d4.<tenant>.agents.whisper.online
Proofs 5 & 6: RDAP and WHOIS — the registry record
# stock tools
curl -s https://rdap.whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 | jq '.handle, .parentHandle'
# "2A04:2A01:EB5A:CA74:CEF2:2A:323D:40D4/128"
# "2A04:2A01::/32"
whois -h whois.whisper.online 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
RDAP (RFC 9083) is the typed application/rdap+json object: startAddress/endAddress pinned to this one /128, and a links entry that refers up to the RIPE allocation covering 2a04:2a01::/32. WHOIS (RFC 3912) gives the same fact as legacy text on port 43. Full object model: RDAP.
Proof 7: the keyless full-chain verdict
Stitching proofs 1–6 together by hand is exactly the friction Postel's Law says to remove. Whisper runs the whole chain server-side and hands back one JSON answer — still keyless:
# stock tools — curl only, no API key
curl -s https://rdap.whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 | jq .
{
"is_whisper_agent": true,
"fqdn": "acef2002a323d40d4.<tenant>.agents.whisper.online",
"operator": "t9f3a1c2e7b4…",
"dane_ok": true,
"jws_ok": true,
"evidence": {
"ptr": "acef2002a323d40d4.<tenant>.agents.whisper.online",
"dane_tlsa_sha256": "b653a4ef...fcb82d1d",
"dane": {"usage": 3, "selector": 1, "matching": 1, "served_leaf_matches": true},
"identity_doc": "https://acef2002a323d40d4.<tenant>.agents.whisper.online/.well-known/whisper-identity"
}
}
The endpoint takes an address or an FQDN, at /verify-identity/<target> or ?ip=<target>, and is liberal in what it accepts, conservative in what it emits. A target that isn't a Whisper agent gets a clean 200 {"is_whisper_agent": false} — a negative verdict is a successful answer, not an error. Only genuinely malformed input draws a 400 with a helpful detail. Never a 500.
jws_ok reflects the signed identity document at /.well-known/whisper-identity: a compact ES256 JWS binding the address, FQDN, tenant, and issue time to the same per-agent key DANE pins. A peer with a JWT library and nothing else can validate it independently of this endpoint — the same shape as did:web VC-JWT.
# with Whisper — the CLI wraps the same call and grades it into a table
whisper verify acef2002a323d40d4.<tenant>.agents.whisper.online
agent yes
fqdn acef2002a323d40d4.<tenant>.agents.whisper.online
operator t9f3a1c2e7b4…
dane_ok yes
jws_ok yes
dane_tlsa_sha256 b653a4ef...fcb82d1d
whisper: acef2002a323d40d4.<tenant>.agents.whisper.online is a verified Whisper agent (DANE-anchored)
The exit code is the verdict — 0 for a fully-verified agent, non-zero otherwise — so a script can gate a firewall rule or an access-control decision on it directly, no JSON parsing required.
Proof 8: --trustless — proving it without trusting Whisper at all
Proof 7 is honest about what it is: Whisper's own server running the chain and reporting the result. That's a convenience, not a proof to someone who won't take Whisper's word for anything. --trustless removes Whisper from the trust path — it validates DNSSEC from the IANA root in-process, on your machine, with your own resolver:
whisper verify --trustless acef2002a323d40d4.<tenant>.agents.whisper.online
FIELD VALUE
address 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
fqdn acef2002a323d40d4.<tenant>.agents.whisper.online
tlsa_sha256 b653a4ef...fcb82d1d
served_spki b653a4ef...fcb82d1d
CHECK RESULT TRUST DETAIL
dnssec pass DNSSEC-root AAAA, PTR and TLSA(3 1 1) all DNSSEC-validated to the IANA root
dane pass DNSSEC-root served leaf SPKI-SHA256 == TLSA pin
transparency pass DNSSEC-root root kid ... (DNSSEC-anchored _whisper-identity TXT)
identity_doc pass DNSSEC-root claims match; signature verifies
whisper: acef2002a323d40d4.<tenant>.agents.whisper.online is CRYPTOGRAPHICALLY PROVEN
— trust anchor: DNSSEC root (IANA) + DANE-EE + DNSSEC-anchored transparency keys — Whisper API NOT trusted
Each row carries its own trust level, so the verdict is auditable rather than a black box:
| Trust level | Meaning |
|---|---|
DNSSEC-root |
fully trustless — chains to the IANA DNSSEC root anchor |
pin+DNSSEC |
the signing key is served over HTTPS, but the claims it signs are cross-checked against DNSSEC-validated DNS facts |
trust-on-pin |
verified, but the key came from a WebPKI-served JWKS, not from DNS |
The chain, in order: resolve and DNSSEC-validate AAAA, PTR, and TLSA, checking that address and name agree — a mismatch is a fail, a fraud signal, not a skip. Open the TLS connection and confirm the served leaf's SPKI hash equals the DNSSEC-proven TLSA pin (RFC 6698/7671, no CA). Then verify the transparency entry and the identity-document JWS against keys published in _whisper-identity/_whisper-ledger TXT records under the same DNSSEC chain.
When those validate, the HTTPS-served JWKS is demoted to a cross-check and the whole verdict anchors at the root. It reads true iff both load-bearing legs (dnssec, dane) pass and nothing reports a fail; the exit code mirrors it, and --json prints the structured report for a pipeline.
# --resolver points the in-process validator at a resolver you trust
whisper verify --trustless --resolver 9.9.9.9 acef2002a323d40d4.<tenant>.agents.whisper.online
There's no stock-tools column for proof 8 — being the stock-tools re-derivation, done once and correctly, is the point. By hand it's every command in proofs 1–6 plus a manual DNSSEC chain walk and an ES256 signature check, which is exactly what the flag automates so you don't have to trust that you did it right either.
Next
- DANE & TLSA — the TLSA record byte-for-byte, and the DNSSEC chain proofs 4 and 8 build on
- Access control — gate a connection or a firewall rule on this verdict