Add README with architecture overview
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
372a77754a
commit
1781b9f0ee
1 changed files with 69 additions and 0 deletions
69
README.md
Normal file
69
README.md
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Cipher
|
||||||
|
|
||||||
|
End-to-end encrypted messenger — a WhatsApp/Signal-style app running entirely on Cloudflare.
|
||||||
|
|
||||||
|
**Live:** https://cipher.theradicalparty.com
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
The server is a **dumb key directory + encrypted relay**. It never sees message
|
||||||
|
plaintext or private keys — only public keys and ciphertext. Real-time delivery
|
||||||
|
plus offline store-and-forward, so messages arrive even when the recipient is away.
|
||||||
|
|
||||||
|
| Concern | How |
|
||||||
|
|---|---|
|
||||||
|
| Encryption | **Signal Protocol** (X3DH + Double Ratchet) via libsignal, in the browser |
|
||||||
|
| Real-time + offline queue | Per-user **Mailbox Durable Object** (WebSocket + SQLite queue) |
|
||||||
|
| Key directory | **D1** — users, devices, prekey bundles (public keys only) |
|
||||||
|
| Media | Client-side AES-GCM, ciphertext stored in **R2**; key travels inside the E2E message |
|
||||||
|
| API | **Hono** on Workers |
|
||||||
|
| Client | Installable **PWA**, IndexedDB key store, Web Push wake-up |
|
||||||
|
| Identity | Username + password; QR device-linking planned |
|
||||||
|
|
||||||
|
Private keys are generated on the device and stored only in IndexedDB. They are
|
||||||
|
never transmitted. See `docs/` notes inline in each source file.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Alice (PWA) Cloudflare Worker Bob (PWA)
|
||||||
|
┌─────────────┐ publish pubkeys ┌──────────────┐
|
||||||
|
│ libsignal │ ──────────────────► │ D1 key dir │
|
||||||
|
│ IndexedDB │ ◄── prekey bundle ─ │ │
|
||||||
|
└─────┬───────┘ └──────────────┘
|
||||||
|
│ encrypt (X3DH/ratchet)
|
||||||
|
│ POST ciphertext ┌──────────────┐ WS push ┌──────────┐
|
||||||
|
└───────────────────────────► │ Mailbox DO │ ───────────► │ decrypt │
|
||||||
|
│ (queue+WS) │ or queue │ locally │
|
||||||
|
encrypt media (AES-GCM) ─► R2 └──────────────┘ └──────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Develop
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev # local Worker + assets
|
||||||
|
npm run db:migrate:local # apply schema to local D1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
Push to `main` → Forgejo post-receive hook runs `wrangler deploy`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pushall main # pushes to Forgejo (origin) + GitHub (backup)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vendored crypto
|
||||||
|
|
||||||
|
`public/js/vendor/libsignal.js` is a self-contained browser bundle of
|
||||||
|
`@privacyresearch/libsignal-protocol-typescript` (built with esbuild + a Buffer
|
||||||
|
shim). Rebuild with the esbuild command noted in the commit history if bumping
|
||||||
|
the library — loading crypto from a CDN at runtime is intentionally avoided.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Working: registration, login, key directory, E2E text + media, real-time and
|
||||||
|
offline delivery (both verified live). Planned: QR multi-device linking, group
|
||||||
|
chats (sender keys / MLS), WebRTC voice/video, Web Push fan-out, delivery/read
|
||||||
|
receipts, disappearing messages.
|
||||||
Loading…
Add table
Reference in a new issue