// interactive cryptography guide

See the cryptography in motion.

These browser demos show local encryption, ciphertext relay, key distribution, and substitution detection. Each demo identifies where it simplifies the production design.

01 - sealing

Encryption happens before transmission

Type a message and the widget encrypts it locally with browser AES-256-GCM. Pock chat uses XChaCha20-Poly1305 for message bodies, with the same device-to-server boundary. The server receives ciphertext and has no channel key with which to decrypt it.

live · AES-256-GCM · in your browser

Encryption runs in this page. The demo sends no network request.

ciphertext view

This is the ciphertext produced by the demo. Its key remains in this page.

02 - message path

Where a message actually goes

Follow a message from the sender's device to the recipients. Pock stores the ciphertext for history and distributes it over WebSockets. Recipient devices hold the channel key required to recover the plaintext.

step 1 / 4
you
"see you at 8"
pock (relay)
🔒 u7F2·9aQ1·kR0x·Lm4z·pV8t
friends
"see you at 8"
You seal it on your device

Before transmission, your device encrypts the message with the channel key (XChaCha20-Poly1305) and signs its digest with your identity key.

03 - the keys

Who makes which key, and when

The map identifies each key in a conversation, who creates it, and what it protects. It also shows how an existing member grants a channel key to a newcomer and how an admin rotates that key after removing a member.

🪪Your identity keypairX-Wing KEM + Ed25519 signing
who Youwhen Once, when you create your vault

Others wrap channel keys to your public KEM key so only you can open them; your Ed25519 key signs your messages so friends know they're really from you. The public halves go into the public key log; the private halves never leave your devices.

🔑The channel keyXChaCha20-Poly1305 symmetric key
who Whoever creates the channel (or DM)when A fresh random key at channel creation

This key encrypts every message in the channel. Channel members share it, while the server stores only wrapped copies and ciphertext.

📦Wrapped copiesone X-Wing-sealed copy per member
who The creator / an existing memberwhen When the key is minted, and on every membership change

The channel key is sealed separately to each member's public KEM key. Each ciphertext can be opened by its intended member. The server stores the ciphertexts without the private keys.

🤝A grant (someone joins)a re-wrap to the newcomer's key
who An existing member who's onlinewhen Shortly after a newcomer joins

A newcomer cannot read history or send until they receive a wrapped copy. An existing member's app wraps the channel key to the newcomer's public key and publishes the result. The server lacks the plaintext key needed to create that grant.

🔄Rotation (someone leaves)a fresh channel key
who An admin's appwhen When a member is removed

An admin's app creates a new channel key and wraps it to the remaining members. The removed member receives no copy of the new key and cannot read later messages.

🎲A per-message noncerandom, one per message
who Your devicewhen Every single message

Each message gets a fresh random nonce. Repeated plaintext therefore produces different ciphertext.

04 - agreeing on a secret

How two devices derive a shared secret

A key exchange lets two devices derive the same secret without transmitting that secret. The widget runs P-256 ECDH as a compact analogy. Pock's Rust core uses X-Wing, which combines X25519 and ML-KEM-768 in a hybrid KEM.

live · ECDH (P-256) · key-agreement analogy
alice
public key
generate to begin
private key
•••••••• never leaves alice
bob
public key
generate to begin
private key
•••••••• never leaves bob

This widget runs P-256 ECDH as a compact analogy. Pock uses X-Wing = X25519 ⊕ ML-KEM-768. The Rust core runs both KEM components and combines their outputs. This browser demo does not run either deployed component.

05 - trust

Detecting a substituted public key

Pock records public keys in an append-only Merkle log. Clients verify signed tree heads, inclusion proofs, and consistency proofs. If the chat server supplies a different logged key, the client excludes it from new channel-key wraps. The widget below compresses the proof structure into one SHA-256 root for demonstration.

live · SHA-256 · simplified key-log model
alicekey95c465bb
bobkeye24dcd0f
carolkey93d8765b
demo root · changes when any key changes
These demo keys produce the pinned root. Change an entry and the next comparison will fail.

The trust boundary is your device.

Messages are encrypted before upload, and recipient keys are checked against the public log. The service relays ciphertext and public-key material.