Security model
This messenger is designed to be anonymous-by-default (no phone/email) and
end-to-end encrypted (E2EE) so that the server stores only ciphertext.
What the server can and can’t access
- Cannot read message text, reactions, or media contents (encrypted in your browser).
- Can see metadata required to route messages: chat IDs, user IDs, timestamps, sizes, and that a message exists.
- Can see your IP address and browser details (as with any website). Use a privacy network if you want to hide that.
How encryption works
- Your browser generates identity keys on first sign-up.
- Your private keys are encrypted with a key derived from your password and stored on the server (so you can sign in from another browser).
- Each chat has a symmetric “room key”. That room key is wrapped for each member using ECDH + HKDF + AES-GCM.
- Each message is encrypted with AES-GCM using a per-message key derived from the room key via HKDF.
- Files are encrypted client-side before upload. The server stores the encrypted blob only.
Key verification & trust
Like many secure messengers, this app uses a trust-on-first-use approach unless you verify a key fingerprint
with your contact out-of-band.
- Each account has a key fingerprint shown in UI (and warnings if it changes).
- For highest assurance, verify fingerprints via another channel (in person, another app, etc.).
Important limitations
- This project is not a substitute for a formally-audited protocol like Signal; it’s a strong baseline you can improve and audit.
- Metadata is not encrypted (who talked to whom, when, and how much).
- For production, run behind HTTPS (TLS) and consider adding rate limiting, abuse controls, and optional invite codes.
Tip: In production, set COOKIE_SECURE=1 and terminate TLS via Caddy or Nginx.