The Proof Chain
Every record and endpoint a stranger can check, what each one asserts, and the command that reads it.
On this page (10)
The Proof Chain Documentation
Eight checks stand behind an identity. The first six read one record each with a stock tool. The seventh runs all of them server-side and returns one answer. The eighth re-runs the chain on your own machine. Every one of them is keyless.
Examples below use the documentation address 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478, whose derived name is ae3b051ff3bf7f478.t<tenant>.agents.whisper.online. Substitute your own target.
1. Reverse DNS
PTR under ip6.arpa says which name the address answers to. The zone is delegated to Whisper and signed, so a validating resolver sets AD on the answer.
dig -x 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 +short
2. Forward DNS
AAAA under the identity zone says which address the name resolves to. It sits in a different delegation from the PTR, populated independently, and the pair agreeing is forward-confirmed reverse DNS. A mismatch is the fraud signal.
dig +short AAAA ae3b051ff3bf7f478.t<tenant>.agents.whisper.online
3. The friendly alias
An identity may publish a short label as a CNAME pointing at the canonical name. It resolves the human-readable name to the derived one, so a label cannot be pointed at an address it was not allocated.
dig +short CNAME shipping-bot.t<tenant>.agents.whisper.online
4. The DANE pin
TLSA at _443._tcp.<name> with parameters 3 1 1 binds the name to one public key: DANE-EE usage, SPKI selector, SHA-256 match. Compare the record to a digest of the key the server actually serves.
dig +dnssec TLSA _443._tcp.ae3b051ff3bf7f478.t<tenant>.agents.whisper.online
openssl s_client -connect ae3b051ff3bf7f478.t<tenant>.agents.whisper.online:443 \
-servername ae3b051ff3bf7f478.t<tenant>.agents.whisper.online </dev/null 2>/dev/null \
| openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256
The two hex strings must be identical. Keys, Signing and Encryption covers what else that key signs.
5. The registry object
RDAP answers for the single /128 in RFC 9083 JSON: the handle, the object name, the type, the status and a referral up to the RIR that holds the covering block.
curl -s https://rdap.whisper.online/ip/2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 | jq '.handle, .name'
6. The WHOIS record
The same allocation on port 43, in RFC 3912 key-and-value lines, for tooling and abuse desks that speak WHOIS and nothing else.
whois -h whois.whisper.online 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478
RDAP and WHOIS documents both records field by field.
7. The keyless verdict
One call runs checks one through six server-side and returns a single boolean with the evidence it used, so a gateway does not have to speak DNS.
curl -s "https://rdap.whisper.online/verify-identity?ip=2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478" | jq .
is_whisper_agent, dane_ok and jws_ok are the three booleans to branch on. Verify an Identity reads the full response.
8. Client-side re-derivation
The CLI walks the chain itself from the IANA DNSSEC root, with the Whisper API out of the trust path, and prints a trust level per row.
whisper verify --trustless 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478
Verify Without Trusting Us explains the rows and the levels.
The signed identity document
Behind jws_ok sits a compact ES256 JWS served on the identity's own name at /.well-known/whisper-identity, binding the address, the name, the account and the issue time. It is signed by the key the TLSA record pins, and the zone's signing keys are published in a TXT record under _whisper-identity.whisper.online.
curl -s --cacert whisper-ca.pem \
https://ae3b051ff3bf7f478.t<tenant>.agents.whisper.online/.well-known/whisper-identity
A plain curl fails here, because the certificate is issued by the per-identity authority rather than a browser root. Pass the root from Keys, Signing and Encryption, or check the pin first and then fetch.
What the chain proves
The chain proves that one address, one name and one key were issued together by the operator of 2a04:2a01::/32 and still are. It says nothing about intent, and nothing about permission. Keep authorisation as its own step.