INVITE ONLY
OBSERVATORY

Docs · How-to

Prove who you're talking to.

Two devices, six groups of four characters. If they match, the keys on both ends are the same keys — no relay rewrote them.

Find the number

Open the conversation and tap your peer's name. The safety number sits one tap in, beside the session's live state — as six groups of four, as a longer eight-group form, and as an emoji fingerprint if you prefer to compare pictures.

A1B2-C3D4-E5F6-0718-293A-4B5C

FORMAT SPECIMEN — YOUR NUMBER IS DERIVED PER SESSION

Compare it out loud

Read the groups to each other in person, or over a channel you already trust. Both devices must show the same digits. The app compares in constant time; so should you — check every group, not just the first.

KTS · SAFETY NUMBERSHA3-256 WASM · LOADING

One number on two screens.

Your device and your peer’s each derive it from the session. If they match, your keys agree end to end — an interceptor cannot show you the same number.

YOUR DEVICE

Your safety number: BF4B-945F-A4B5-7A1E-D4D9-7C20

In the app: Q-Ratchet root key + both peers’ ML-DSA-87 public keys → HKDF-SHA512 → 16 bytes; the short form renders 12 of them as six groups of four hex characters.KTS-QUORUM SPEC

VERIFY A PEER

24 hex characters in six groups of four — paste is fine. 0/24

DEMO INPUTS

THE COMPARISON RUNS IN YOUR BROWSER — NOTHING LEAVES THIS PAGE

Demo scope: these numbers are derived with real SHA3-256 (WebAssembly) from an authored demo transcript, and this pane demonstrates the QERYX safety-number format and verify flow. It performs no ML-DSA-87 signature verification — the shipped app verifies peers with ML-DSA-87 (FIPS 204).

Real ChaCha20-Poly1305 (RFC 8439), compiled from Rust to WebAssembly, running in your browser. Same primitive family as the QERYX protocol; demo build, not the shipped crypto-core module.

Know what a match proves

The number is derived with HKDF-SHA512 over the session root key and both peers' ML-DSA-87 identity public keys, sorted so both devices compute the same bytes. The short form renders 12 of those bytes as six groups of four hex characters; the full form renders 16 bytes as eight groups.

A match means both devices hold the same session root and the same identity keys — the handshake you ran is the handshake your peer ran. A mismatch means the two devices were handed different identity keys. Stop, delete the session, and re-entangle in person.

Identity keys are also appended to KTS, an append-only key transparency log: a 2-of-3 multi-witness quorum (verify-only today — operator equivocation is detected, not prevented) plus three external Ed25519 auditor slots that ship dormant, holding placeholder keys until auditors are onboarded; registry expansion is release-gated by design. Identity signatures are ML-DSA-87 (FIPS 204).

During the in-person connect ceremony the witness is computed over the two ML-DSA-87 identity public keys alone — the session root is deliberately excluded, because each side has just bootstrapped its own handshake. Disagreement there means the relay handed the two devices different identity keys, not a session-state artifact.

Act when the number changes.

My peer's number changed — is that an attack?

Not necessarily. The number changes when identity keys rotate — a reinstall or a new device does that legitimately. Treat it as unverified again: ask your peer what happened, then re-verify. If nothing changed on their side, stop and re-entangle in person.

Every session is X25519 + ML-KEM-1024 hybrid-encrypted whether you verify or not. Verification removes the last assumption — that the key bundle the relay served you belongs to your peer. For anything sensitive, verify.

Four-character hex groups survive being read across languages and noisy channels, and they map one-to-one onto the derived bytes — what you read aloud is the cryptographic value itself, not an encoding of an encoding.