This commit applies the actionable plan from docs/plans/2026-04-29-encrypted-p2p-chat-audit-fixes.md.
Backend
- Delete server-side X3DH/Double Ratchet (`app/core/encryption/*`); the server is now an opaque relay for client-encrypted messages.
- Drop `private_key` columns from IdentityKey/SignedPrekey/OneTimePrekey; prekey-bundle endpoint serves only public material.
- Remove RatchetState and SkippedMessageKey models and the deprecated server-encryption code path in message_service.
- Fix the broken `not OneTimePrekey.is_used` SQL filter (`Column.is_(False)` instead of Python `not`); repair the silent OPK-replenish amplification by deleting the server-generated path entirely.
- Stop calling `prekey_service.initialize_user_keys` from registration/login. Server never holds private key material again.
- Add session-cookie auth: opaque token issued in Redis on register/auth complete, `current_user` dependency on every protected route, `/auth/me`, `/auth/logout`. WebSocket authenticates via the same cookie.
- Add room membership checks to WS encrypted_message + typing handlers, GET/DELETE /rooms/{id}, GET /rooms/{id}/messages. broadcast_to_room now filters by participants, not presence.
- Add slowapi rate limits to register/auth/search; per-user sliding-window cap on WS messages.
- WebAuthn: replace username with a 64-byte random `webauthn_user_handle` for `user.id`; fix `backup_eligible` to read `credential_backup_eligible`; switch UserVerificationRequirement to REQUIRED; key authentication challenges by challenge bytes (no more "discoverable" collision).
- Implement GET /rooms/{id} and DELETE /rooms/{id} (cascade delete with ownership check) and fix the N+1 in list_rooms by batching User lookups.
- Remove broken/obsolete tests; add regression tests for the OPK filter bug and session-protected endpoints (401 without cookie).
- Sanitize WebSocket error responses; correlation IDs replace stack-trace leaks.
Frontend
- X3DH: prepend the 32-byte 0xff F prefix to the HKDF input per spec section 2.2.
- Double Ratchet: switch KDF_RK to spec form (HKDF salt=root_key, IKM=dh_output) and use 0x01/0x02 byte tags for KDF_CK.
- Replace base64 helpers in `crypto/primitives.ts` with the URL-safe codec from `lib/base64.ts` (single source of truth, no spread-stack hazard).
- Update auth.service to issue a session via cookies (no more dead token store), call `/auth/me` on app boot, clear crypto state on logout. Delete unused `session.store.ts`.
- Update room.service / Chat page to drop client-supplied user_id arguments; the cookie now identifies the caller.
- Better forward-secrecy UX text for messages predating the device.
- Add Vitest with X3DH and Double Ratchet round-trip + tamper-detection tests.
Tooling
- Add `slowapi>=0.1.9` to backend deps; add `vitest` to frontend devDeps with `pnpm test` script.
- justfile: `test-frontend`, `dev-reset`.
- Adjust `.gitignore` so the Python `lib/` rules no longer hide `frontend/src/lib`.
Migration: existing dev volumes hold private-key columns and KDF-incompatible ratchet states; run `just dev-reset` and re-register before hitting the new code path.
|
||
|---|---|---|
| .. | ||
| backend | ||
| conf | ||
| frontend | ||
| learn | ||
| .env.example | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
| compose.yml | ||
| dev.compose.yml | ||
| justfile | ||
README.md
██████╗ ██████╗ ██████╗ ██████╗██╗ ██╗ █████╗ ████████╗
██╔══██╗╚════██╗██╔══██╗ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝
██████╔╝ █████╔╝██████╔╝ ██║ ███████║███████║ ██║
██╔═══╝ ██╔═══╝ ██╔═══╝ ██║ ██╔══██║██╔══██║ ██║
██║ ███████╗██║ ╚██████╗██║ ██║██║ ██║ ██║
╚═╝ ╚══════╝╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
End-to-end encrypted peer-to-peer chat with Signal Protocol (Double Ratchet + X3DH) and WebAuthn/Passkey authentication.
This is a quick overview — security theory, architecture, and full walkthroughs are in the learn modules.
What It Does
- Double Ratchet protocol (Signal) with X3DH key exchange for end-to-end encryption
- WebAuthn/Passkey authentication with discoverable credentials and multi-device support
- Forward secrecy and break-in recovery with out-of-order message handling
- Real-time WebSocket messaging with SurrealDB live queries
- Presence tracking, typing indicators, read receipts, and heartbeat keep-alive
- Alembic database migrations with full test suite
Quick Start
docker compose up -d
Visit http://localhost:8080 to open the application.
[!TIP] This project uses
justas a command runner. Typejustto see all available commands.Install:
curl -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin
Stack
Backend: FastAPI, PostgreSQL + SQLModel, SurrealDB, Redis, Alembic
Frontend: SolidJS 1.9, TypeScript, Vite 6, Tailwind CSS v4
Learn
This project includes step-by-step learning materials covering security theory, architecture, and implementation.
| Module | Topic |
|---|---|
| 00 - Overview | Prerequisites and quick start |
| 01 - Concepts | Security theory and real-world breaches |
| 02 - Architecture | System design and data flow |
| 03 - Implementation | Code walkthrough |
| 04 - Challenges | Extension ideas and exercises |
License
AGPL 3.0