CrawlCheck
Signing keys

One key signs everything an agent can check.

The same Ed25519 key signs every request CrawlCheck sends under its own name and every document an agent relies on: Resolve answers, decision receipts, site staples, DNS records and the heads of the answer log. Verify against this key and nothing else; when it rotates, the history below says which key was valid when.

hcIAczGf

active key (JWK thumbprint)

7

days of overlap on rotation

3

key events, hash-chained

intact

chain, checked from the first entry

For agents

Three ways the key is used

Each check runs on your own machine.

1 · An answer

Verify before acting

Every Resolve answer and decision receipt carries signature.kid. Accept it only when that kid is in the signed directory, then check the signature over the document’s SHA-256.

The verifierThe directory

2 · Our crawler

Allow the key, not an IP

Requests made under CrawlCheck’s own name carry HTTP Message Signatures (Web Bot Auth). A site can verify the signature against this key instead of maintaining an address range.

Crawler policySignature-Agent

3 · An old signature

Which key, and when

A signature made before a rotation verifies against the key that made it. The log below says when each key started and stopped signing, and every entry hashes the one before it.

The key logAs JSON

Current

The active key

Thumbprint (JWK, SHA-256)hcIAczGf-8EFBnkunmZlvFWnD2nHHeHeC9cM4BTiBVo
Valid from2026-09-11 20:24 UTC
Signsevery request sent under our own name, the key directory, and every signed document: Resolve answers, decision receipts, site staples, DNS records and answer-log heads
Overlap on rotation7 days: a new key is published before the old one stops signing, and the old one stays listed after
Retired

Keys that no longer sign

ThumbprintValid fromStopped signingPrivate half erasedWhy
0zNVreNVKdaTFJjtRJtvcFiesmG2qgWvvIBL_zbgwko2026-08-21 03:072026-09-18 20:242026-09-19 01:17moved from KV storage to a Worker secret

Times are UTC. A key stops signing when the overlap ends; its private half is erased at the next sweep after that, and its public half stays listed so old signatures still verify.

History

Every key event

Chain intact (checked from the genesis entry); coverage complete: every key the directory publishes has an entry.

#When (UTC)EventKeyReasonEntry hash
22026-09-18 21:17:40retired0zNVreNVKdaTFJjt…moved from KV storage to a Worker secret8b9e4f47245c3324…
12026-09-16 12:26:27publishing0zNVreNVKdaTFJjt…published during overlap rotation; created 2026-08-21T03:07:11.000Z08d7e8ec87b75230…
02026-09-12 04:42:56activehcIAczGf-8EFBnku…e092e9199a0eee49…

Head 8b9e4f47245c3324f88704d7880d7e203acec175a7873421f8680f643c9ac5d6. The log began on 2026-09-12; its first entry records the key that was already active.

Check it yourself

Recompute the chain

Each entry hashes {at, event, prev, reason, seq, storage, thumbprint} as canonical JSON with sorted keys; its prev is the hash of the entry before it, and the first entry points at 64 zeroes. Recompute the chain and it must reach head. A key that signed something last month appears here even if it no longer appears in the directory.

Daily anchor: since 2026-10-04 the head hash is a leaf in each day’s sealed Merkle root, timestamped with OpenTimestamps: /api/seal/lookup?id=keys-head&day=YYYY-MM-DD.