Wyvern
A privacy-first, Discord-style messenger with real end-to-end encryption.
Context
On most mainstream platforms the content of your conversations passes through — or is stored on — servers that can read it, and signing up usually means handing over part of your real identity. Wyvern flips that: a server that routes and keeps messages without ever being able to read them, and sign-up with no verifiable personal data.
The trigger was concrete: the controversy around Discord's age-verification plans pushed us to imagine a community messenger built differently. Two inspirations — Discord for the familiar UX, and Mullvad VPN for identity, where a simple numeric code replaces your email and profile.
Features
- Anonymous sign-up; log in by pseudonym or a 16-digit code.
- Servers and channels (public or private) with invite codes.
- Real-time messaging and private DMs over WebSockets.
- Polls, message pinning, edit/delete, keyword search.
- Roles (owner / admin / member), kick and ban.
- End-to-end encryption on every message, Discord-like dark UI.
End-to-end encryption
Every message is encrypted in the browser with a hybrid scheme: EC-ElGamal over the secp256k1 curve to exchange a one-time key, then AES-256-GCM to encrypt the content.
The private key never leaves the client — it's stored encrypted with a key derived from your password (PBKDF2, 100,000 iterations) and only decrypted in memory for the session. The server stores and routes ciphertext it cannot read.
Architecture
A dockerised client–server app: a Flask 3.1 backend with Flask-SocketIO (eventlet) and SQLAlchemy over MySQL 8, a vanilla-JavaScript front end talking REST + WebSockets, all orchestrated with Docker Compose.
A look at the app
Results
Wyvern works end to end. Every functional requirement is operational, real-time latency is imperceptible in testing, and the headline goal is verifiable: a message sent from the app is unreadable ciphertext in the database yet appears in clear for its recipient — while the server never sees the text.
Honest limits
Built for a course, with limits we own: the cryptography is hand-rolled for learning (not production-hardened, not constant-time, no forward secrecy), search runs client-side, and a member who joins a channel can't decrypt messages sent before they arrived.