# Whisper NIC: the complete registry record.

> Everything a registry is expected to publish, kept current: the resources, the
> access endpoints, bring-your-own-domain proof, issuance under your own domain,
> the verification recipes, and the transparency-log policy. Conservative in what
> we state; clear about what is live versus on its way.

Every command below is run against
the live service and pasted exactly as it answers. The examples use a live resident,
`2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478`; swap in any agent's `/128` or its name.

## 1. Registry identity and resources

The registry is operated by **Whisper Security (viaGraph B.V.)**, Amsterdam, NL,
on infrastructure we hold ourselves. No third party sits in the trust path.

- **Autonomous system:** `AS219419`, IPv6-only, announced from <https://as219419.net/>.
- **Agent identity block:** `2a04:2a01::/32` - one `/128` per agent identity,
  within RIPE allocation `2a04:2a00::/31`.
- **Assignment model:** `inet6num`, `AGGREGATED-BY-LIR`, **assignment-size 128** -
  every agent is a normally-allocated, individually-recorded `/128`.
- **Resolver / DNS service:** authoritative `ns1.whisper.online` +
  `ns2.whisper.online`; the recursive upstream is the unbound resolver at
  `2a04:2a00::53`.
- **Routing posture:** RPKI ROA-covered origin, MANRS-compliant, dual-homed (two
  independent transits) for redundancy.

Every agent record refers up to RIPE's own record for `2a04:2a01::/32`, so the
ground under it is independently confirmable. Live counts: <https://nic.whisper.online/stats>.

## 2. Access endpoints

All read-only, all keyless.

- **RDAP, by address:** `https://rdap.whisper.online/ip/<addr>` (RFC 9083) - the
  canonical machine-readable object.
- **RDAP, by domain:** `https://rdap.whisper.online/domain/<apex-or-fqdn>`
  (RFC 9082/9083) - the served-zone object, with `secureDNS` and the parent referral.
- **WHOIS:** `whois.whisper.online`, port 43 (RFC 3912) - the same record in
  `inet6num` form.
- **Finger, by identity:** `finger.whisper.online`, port 79 (RFC 1288) - the same
  record in plain-text identity form, answerable by a `/128` or an agent FQDN.
- **FTP archive, anonymous:** `ftp.whisper.online`, port 21 (RFC 959) - anonymous
  read-only archive of the NIC registry documents (the same content served over
  RDAP / WHOIS / HTTP).
- **DNSSEC trust anchors:** the served zones are signed and chained; the parent
  carries a `DS` for `agents.whisper.online` and `whisper.online` (ECDSA P-256,
  algorithm 13).
- **Keyless verification:** `https://rdap.whisper.online/verify-identity/<addr>` -
  one call that checks the whole chain and returns a plain verdict.

Confirm the DNSSEC trust anchors yourself (the `DS` values rotate with the keys,
so read your own live answer):

```sh
$ dig +short DS agents.whisper.online @1.1.1.1
54705 13 2 99B88E7C1FD2A815F3DA0374D9FED2C4735F7EFDDB864CB1A79F9D55 43DFE06D
$ dig +short DS whisper.online @1.1.1.1
50855 13 2 3B33E9998425C1F43FCC3B8D4696DB587DB7CEA3F2A235E1556C4C4F 47E247D3
```

Add `+dnssec` to any forward query and require the `ad` flag (validated).

## 3. Verify any identity with stock tools

Eight independent checks, each run against the live service and pasted verbatim.

```sh
# 1. Reverse DNS names the address (signed):
$ dig -x 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 +short
ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online

# 2. The forward name points back to the same address (the loop closes):
$ dig +short AAAA ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online
2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478

# 3. The agent's key is pinned in DNS itself (DANE-EE 3 1 1, no CA in the path):
$ dig +short TLSA _443._tcp.ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online
3 1 1 9EC1EF18A1F15E5480A0FC3C8D6E9690B2CCF1A7FA7146201940F28C 422BB47D

# 4. The TLS leaf on the wire matches that pin (a DANE-aware client validates it):
$ openssl s_client -dane_tlsa_domain ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online \
    -dane_tlsa_rrdata "3 1 1 9EC1EF18A1F15E5480A0FC3C8D6E9690B2CCF1A7FA7146201940F28C 422BB47D" \
    -connect [2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478]:443 </dev/null 2>/dev/null | grep "DANE TLSA"
# -> DANE TLSA 3 1 1 ... matched EE certificate

# 5. One keyless call checks the whole chain and returns a plain verdict:
$ curl -s https://rdap.whisper.online/verify-identity/2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 | jq '{is_whisper_agent,dane_ok,jws_ok}'
# -> {"is_whisper_agent": true, "dane_ok": true, "jws_ok": true}

# 6. The registry knows it by address and by name (RDAP canonical; WHOIS mirrors):
$ curl -s https://rdap.whisper.online/ip/2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 | jq -r .name
scout
$ whois -h whois.whisper.online 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478
# -> inet6num / netname / origin AS219419 / aggregate 2a04:2a01::/32 / ...
$ curl -s https://rdap.whisper.online/domain/ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online
# -> the signed-DNS / referral view of the same identity

# 7. The signed identity document and the did:web record live under the agent's name,
#    at /.well-known/. There is no public CA in front of them: the certificate is pinned
#    by the DANE TLSA 3 1 1 record in the signed zone, so a bare curl refuses the
#    connection and is right to. Check the pin, then read the documents:
$ dig +short TLSA _443._tcp.ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online
3 1 1 <SHA-256 of the SubjectPublicKeyInfo this name is allowed to serve>

$ openssl s_client -connect ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online:443 -servername ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online </dev/null 2>/dev/null \
    | openssl x509 -pubkey -noout | openssl pkey -pubin -outform DER \
    | openssl dgst -sha256 -binary | xxd -p -c 64
<the same 32 bytes, lowercase>
# they match, so the key on the socket is the key the signed zone pins - no CA was consulted

# -k below is not skipping a check, it is declining one you have already done better:
$ curl -sk https://ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online/.well-known/whisper-identity   # signed JWS identity statement
$ curl -sk https://ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online/.well-known/did.json           # W3C did:web document (same key)

# 8. The agent's SSH host-key fingerprint is in DNS too (SSHFP):
$ dig +short SSHFP ae3b051ff3bf7f478.tdc38e7c55bad3306a92b830f9bb1e4f9.agents.whisper.online
3 2 <SHA-256 of this host's Ed25519 host key>
# compare it with what your SSH client is offered; signed DNS is the second opinion
```

Every check above is independent, runs against the live service, and depends on
signed DNS and your own tools rather than on trusting us. If you would rather not
do step 7 by hand, `whisper verify --trustless` does the same walk from the IANA
root in one command, and the keyless gateway check in step 5 returns the verdict
with no account at all.

## 4. Bring your own domain - onboarding and proof (coming)

You can put the registry under a domain you already own. You bring the domain; we
run the network and the registry that vouch for the identities inside it. Publish
the delegation and the DS at your parent (apex or a subdomain):

```
example.com.   NS   ns1.whisper.online.
example.com.   NS   ns2.whisper.online.
example.com.   DS   <digest 2 (SHA-256) and 4 (SHA-384)>
```

**Proof = delegation + DS, observed live in the wild. No TXT challenge.** We poll
your own authoritative servers, then public resolvers from several vantage points,
until the delegation and a matching `DS` are seen. Verification is **fail-closed**:
an unproven domain is never authorized. A daily continuity sweep re-checks every
delegated domain; if the chain moves away from us, the domain goes out of order on
its own. Keep your zone signed end to end; add no glue for our out-of-bailiwick
nameservers. This onboarding flow is being rolled out under this campaign; until it
lands for your account, your agents live under `agents.whisper.online`.

## 5. Issuance under a custom domain (coming)

Once a domain is onboarded and proven, new agents are minted directly under it, as
`a<hex>.<yourdomain>`, instead of under `agents.whisper.online`. The whole record -
reverse DNS, RDAP, WHOIS, DANE, and the signed identity document - follows the name
into your domain.

- **DANE-EE trust by your DNS:** each agent's per-agent leaf has a `TLSA` record
  under your now-signed zone; because your zone chains to the public root through
  your own `DS`, a DANE-aware peer trusts the agent with no Whisper CA and no public
  CA.
- **Coexistence:** identities already issued under `agents.whisper.online` keep
  resolving for good; the custom domain takes over only for new mints. The IPv6
  `/128` stays ours (AS219419, `2a04:2a01::/32`) - only the name moves.
- **Capacity:** a configurable per-operator cap keeps signing and replication load
  bounded, failing closed with a clear message rather than a surprise.

The multi-zone serving engine that makes this possible is live; the per-account
onboarding and full RDAP/WHOIS/reverse coverage for custom domains are rolling out
under this campaign.

## 6. The transparency log

Each identity carries an append-only, hash-chained record of its events -
issuance, rotation, revocation - signed by a dedicated log key with a published key
id. You can read it today, per `/128`:

```sh
$ curl -s https://rdap.whisper.online/ip/2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478/transparency | jq '{count,root_hash,root_signature_alg}'
# -> {"count": 1, "root_hash": "...", "root_signature_alg": "ES256"}
```

A revocation cannot be quietly erased from an identity's history. As of the
transparency-log rollout (live since `0.112.0`), this per-identity feed is anchored
in a single append-only **Merkle log of all identity commitments**, with the public
proof surface below.

### The public proof surface (live)

The whole log is published, keyless, on the same gateway:

- **Signed checkpoint:** `GET https://rdap.whisper.online/checkpoint` - the C2SP
  signed note (origin `whisper.online/ledger/g2`, `tree_size`, base64 root, one
  Ed25519 signature line per cosigner).
- **Published log key:** `GET https://rdap.whisper.online/checkpoint/key` - key id
  `d40e573a`, the Ed25519 public key and its SPKI form.
- **Merkle tiles:** `GET https://rdap.whisper.online/tile/<level>/<index>` - the
  immutable raw 32-byte node hashes.
- **Consistency proof:** `GET https://rdap.whisper.online/consistency?from=<a>&to=<b>`
  - the append-only-extension proof (tree `a` is a prefix of tree `b`).
- **Inclusion (per identity):** `GET https://rdap.whisper.online/ip/<addr>/transparency`
  now carries a `ledger` arm: `{tree_size, checkpoint, leaves:[{index, leaf_hash,
  inclusion_proof[]}]}` - opaque commitments only.
- **Inclusion (per leaf):** `GET https://rdap.whisper.online/inclusion?leaf=<N>`
  returns the RFC-6962 inclusion proof for any leaf index:
  `{leaf_hash, proof[], checkpoint}`.

```sh
# Pin the log's key set from signed DNS (DNSSEC-anchored, so trust the chain not the fetch):
$ dig +short TXT _whisper-ledger.whisper.online
# -> "v=whisper1; k=ed25519; n=whisper.online/ledger/g2; p=MCowBQYDK2VwAyEA7pSYYInKXm2TMjwAqEsoKon/d3E8SDq34V1VUrgTAm0="
#    ... two more n=whisper.online/ledger/g2 entries, the keys the log may roll to

# The published key + the signed checkpoint (the checkpoint Link header points at the key):
$ curl -s https://rdap.whisper.online/checkpoint/key
# -> {"object":"whisper-ledger-key","origin":"whisper.online/ledger/g2","alg":"Ed25519",
#     "key_id":"d40e573a","public_key":"7pSYYInKXm2TMjwAqEsoKon/d3E8SDq34V1VUrgTAm0=",
#     "public_key_spki":"MCowBQYDK2VwAyEA7pSYYInKXm2TMjwAqEsoKon/d3E8SDq34V1VUrgTAm0="}
$ curl -s https://rdap.whisper.online/checkpoint
# -> the current signed note: line 1 the origin whisper.online/ledger/g2, line 2 the
#    tree size, line 3 the base64 root, then a signature line for the log and one for
#    each witness. Fetch it yourself for the live root; a copy pasted here would be
#    stale the moment the next identity is minted.
```

Each signature line is `<origin> <base64(key-id || Ed25519 sig)>`; the first four
bytes of the log's own blob are the key id `d40e573a`, re-derivable as
`SHA-256(origin || 0x0A || 0x01 || pubkey)[:4]` - so the key the checkpoint is signed
with is the one at `/checkpoint/key`, nothing to trust in between.

### A worked example, from the tree

Ask any resident for its `ledger` arm and you get its leaf indices plus the inclusion
proof that folds them to the signed root. Fetch it live - the tree grows with every
mint, so a leaf's proof lengthens over time and any snapshot pasted here would go
stale:

```sh
$ curl -s https://rdap.whisper.online/ip/2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478/transparency | jq '.ledger'
# -> {
#      "object": "ledger-inclusion", "origin": "whisper.online/ledger/g2",
#      "tree_size": 39858,                       # your fetch shows the current size
#      "leaves": [{"index": <n>, "leaf_hash": "<hex>", "inclusion_proof": ["<hex>", ...]}]
#    }
```

Identities minted before the current genesis do not carry a leaf in it - their
`ledger.leaves` is `[]` until a back-fill folds them in. An empty `leaves` means "no
Merkle leaf in this tree yet," not "not an agent"; the per-`/128` hash-chained feed
still covers them.

### Verify it yourself, with stock tools

The leaf commitment is `sha256(salt || event)`; the Merkle leaf is `sha256(0x00 ||
commitment)`; interior nodes are `sha256(0x01 || left || right)`. Fetch a leaf's
`inclusion_proof`, fold it up to the root in the signed checkpoint, then verify the
Ed25519 signature with the published key - all stock crypto, no SDK:

```sh
# 1. the raw 32-byte Merkle leaf for index 0 (the tile IS the leaf hash):
$ curl -s https://rdap.whisper.online/tile/0/0 | xxd -p -c64
# -> the leaf hash for leaf 0, i.e. sha256(0x00 || commitment)

# 2. that leaf's inclusion proof, plus the root in the signed checkpoint (base64 line 3):
$ curl -s "https://rdap.whisper.online/inclusion?leaf=0"   # {leaf_hash, proof[], checkpoint}
$ curl -s https://rdap.whisper.online/checkpoint | sed -n '3p' | base64 -d | xxd -p -c64

# 3. fold each proof step up to the root, then verify the signature:
#      node = sha256( 0x01 || left || right )    # RFC 6962 interior hash; sha256sum does it
#    keep folding until you reach the checkpoint root, then check the Ed25519 signature
#    line with the key from /checkpoint/key. Nothing to trust in between.
```

Or one command with the keyless CLI verifier (same stock crypto - Ed25519 +
SHA-256 + RFC 6962 folding):

```sh
$ whisper ledger checkpoint                       # fetch + verify the signed checkpoint
# -> whisper: checkpoint VERIFIED - signed tree of <n> leaves
$ whisper ledger verify 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478 --salt <hex> --event-file event.bin
# -> whisper: VERIFIED - the disclosed commitment is in the signed ledger at leaf <i> of <n>
```

**The claim.** This is a **tamper-evident, independently-witnessed transparency
log** (cross-witnessed by MarkovianProtocol; Bitcoin-anchored underneath): every
checkpoint is signed, openly published, and Bitcoin-anchored, so anyone can verify
the proofs today, and the served claim reaches publicly verifiable / split-view-resistant
once a quorum of at least two genuinely independent witnesses is cosigning the
served checkpoint (gated in code, self-reverting; the live `X-Whisper-Ledger-Claim`
header is the source of truth).
**Independently witnessed today by MarkovianProtocol**, one such witness, and
additional witnesses are welcome: run one and we'll cosign back, so the log grows
mutually, independently verifiable for everyone who takes part, and each new
independent witness brings the quorum. MarkovianProtocol's cosignature on the current
checkpoint is verifiable at <https://witness.markovianprotocol.com/checkpoints>.
Verification is by
**selective disclosure** - the tree holds only opaque salted commitments, so the
public proofs show that a commitment is in the signed tree, not what it attests. See
the policy (<https://nic.whisper.online/policy#transparency>) and the witness-policy
ADR
(<https://github.com/whisper-sec/whisper-ns/blob/main/docs/adr/0018-ledger-witness-policy-and-claim-gate.md>).

- **Live today:** the per-`/128` signed event feed at `/ip/<addr>/transparency`
  (now with a `ledger` inclusion arm), the signed `/checkpoint` and its published
  key (id `d40e573a`), the immutable `/tile/<level>/<index>` Merkle tiles, the
  `/consistency` append-only proof, and the keyless `whisper ledger` verifier - all
  stock crypto, no SDK.
- **An open invitation:** independently witnessed by MarkovianProtocol; more
  **witnesses are welcome**: run one against the checkpoints and we'll cosign back,
  so the log is mutually, independently verifiable for everyone who takes part (ADR
  0018, #151 WB4). The genesis back-fill that folds pre-log identities into the tree
  is also in flight.

## 7. Policies, sources, and contact

- **Registry rulebook:** policy (<https://nic.whisper.online/policy>), naming
  (<https://nic.whisper.online/naming>), reserved & premium names
  (<https://nic.whisper.online/names>), statistics
  (<https://nic.whisper.online/stats>), data licence
  (<https://nic.whisper.online/data-license>).
- **Open decisions (ADRs):** transparency-log witness policy
  (<https://github.com/whisper-sec/whisper-ns/blob/main/docs/adr/0018-ledger-witness-policy-and-claim-gate.md>);
  full set (<https://github.com/whisper-sec/whisper-ns/tree/main/docs/adr>).
- **Network and company:** AS219419 (<https://as219419.net/>), Whisper Security
  (<https://whisper.security>), the home for your agents (<https://whisper.online/>).
- **Abuse / contact:** <abuse@whisper.security>.

---

- **Overview:** <https://nic.whisper.online/>
- **Bring your agent home:** <https://console.whisper.security/sign-up>
- **Verify an agent (the living nest):** <https://agents.whisper.online/>

© viaGraph B.V. (dba Whisper Security)
