End-to-end encrypted messaging as a Progressive Web App, built with Elm and Erlang/OTP.
CipherPost is a zero-knowledge messaging system. All encryption and decryption happens in the browser using OpenPGP.js (RFC 9580). The backend — an Erlang/OTP server with Cowboy — stores only encrypted blobs and never sees plaintext messages.
How it works
- Each participant generates an OpenPGP keypair in their browser
- Public keys are published to the backend
- The sender encrypts a message with all recipients’ public keys, signs it with their own private key, and sends the encrypted blob to the server
- Recipients poll for new messages and decrypt them client-side
The backend is intentionally simple: it stores encrypted messages with a timestamp and serves public keys. Nothing more.
Architecture
| Component | Technology |
|---|---|
| Frontend | Elm PWA |
| Backend | Erlang/OTP with Cowboy |
| Crypto | OpenPGP.js (RFC 9580) — loaded as ESM module |
No npm or Node.js required. The frontend compiles to JavaScript via Elm, and OpenPGP.js is loaded directly from CDN.
API
| Method | Path | Description |
|---|---|---|
| GET | /api/keys |
List all public keys |
| GET | /api/keys/:fingerprint |
Get a specific public key |
| POST | /api/keys |
Register a public key |
| POST | /api/messages |
Store an encrypted message |
| GET | /api/messages/:fingerprint?since=ISO8601 |
Fetch messages for a recipient |
License
AGPL-3.0-or-later — if you run a modified version as a network service, you must make your source code available to users.
Source code on GitHub.