// 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.
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.
Encryption runs in this page. The demo sends no network request.
This is the ciphertext produced by the demo. Its key remains in this page.
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.
Before transmission, your device encrypts the message with the channel key (XChaCha20-Poly1305) and signs its digest with your identity key.
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.
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.
This key encrypts every message in the channel. Channel members share it, while the server stores only wrapped copies and ciphertext.
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 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.
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.
Each message gets a fresh random nonce. Repeated plaintext therefore produces different ciphertext.
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.
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.
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.
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.