Security
Our design goal: even if our server were fully exposed, your files would be unreadable gibberish. Here is how, and where the limits are.
The pairing code is split in two
The first 4 characters are the room number, sent to the server to find the room. The last 6 characters are the secret and never leave your browser. Share links put the code after the # in the URL, which browsers never send to servers.
CPace key exchange
A newcomer runs a CPace handshake (a PAKE built on ristretto255) with an online member using the secret, followed by HMAC key confirmation. The server only relays messages: it cannot impersonate either side or brute-force the code offline from what it relays. Only after the handshake succeeds is the room key sent, encrypted, to the newcomer.
Everything is encrypted in the browser
Chat messages, file names, file types and file contents are encrypted with AES-256-GCM. Files are split into 8 MiB chunks; each chunk's index and a final-chunk flag are bound into the authenticated data so chunks cannot be reordered or truncated. The server verifies membership with a hash of a derived key, never the room key itself.
Length hiding
Short messages and file names are padded to multiples of 256 bytes (ISO/IEC 7816-4) before encryption. File sizes are padded with Padmé, adding at most about 12%.
Crypto-shredding
When a room expires the server deletes every object and its in-memory state, backed by a cleanup job every 10 minutes and a 1-day R2 retention limit. Cloud deletion cannot guarantee physical erasure of disks, but the real guarantee is crypto-shredding: the server only ever held ciphertext and the key never left the browsers, so whatever remains can never be decrypted.
Guessing and abuse protection
Pairing is protected by Cloudflare Turnstile and per-IP and per-room rate limits. A waiting code is discarded after 5 wrong guesses; a room stops accepting newcomers after 10.
What still leaks
To be honest: the server can see when messages are sent, how many files are shared, their approximate size class, and how many people are in a room. Newcomers cannot join while every member is offline. Redeploying the server ends all active rooms.
Storage in your browser
So you can reconnect after your phone sleeps, the room key is encrypted with a non-extractable device key and kept in IndexedDB, then deleted when the room ends or expires. A strict Content Security Policy limits which scripts can run and where the page may connect.