-
Notifications
You must be signed in to change notification settings - Fork 6
Encrypted P2P Chat
Carter Perez edited this page Dec 9, 2025
·
1 revision
Real-time encrypted messaging application using Signal Protocol encryption with passwordless WebAuthn authentication.
A secure chat application implementing end-to-end encryption with forward secrecy and break-in recovery. Features passwordless authentication via WebAuthn/Passkeys and real-time messaging through WebSockets and SurrealDB live queries.
Status: Complete | Difficulty: Advanced
| Technology | Version | Purpose |
|---|---|---|
| FastAPI | 0.121+ | Async Python web framework |
| PostgreSQL | 16 | User auth & credentials |
| SurrealDB | 1.0 | Real-time messaging (live queries) |
| Redis | 7.1 | Challenge/session storage |
| SQLModel | 0.0.27 | SQLAlchemy + Pydantic hybrid |
| Alembic | 1.17+ | Async migrations |
| PyNaCl | 1.6 | Encryption primitives |
| liboqs-python | 0.14 | Post-quantum cryptography |
| Technology | Version | Purpose |
|---|---|---|
| SolidJS | 1.9 | Fine-grained reactivity |
| TypeScript | 5.9 | Type safety |
| Vite | 7.2 | Build tool (Node 20.19+) |
| Tailwind CSS | v4 | Styling |
| @tanstack/solid-query | 5.90 | Server state |
| nanostores | 1.1 | Lightweight state |
- Docker + Docker Compose
- Nginx reverse proxy
- Makefile automation
- Passwordless login with WebAuthn/Passkeys (FIDO2)
- Discoverable credentials (device-based)
- Multi-device support
- Signature counter verification
- Double Ratchet for message encryption
- X3DH key exchange for async messaging
- Forward secrecy
- Break-in recovery
- Out-of-order message handling
- Per-message AES-256-GCM
- WebSocket connections with management
- SurrealDB live queries
- Online/offline presence
- Typing indicators
- Read receipts
- Heartbeat keep-alive
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (SolidJS) β
β βββββββββββ ββββββββββββ βββββββββββ βββββββββββββ β
β β Auth β β Chat β β Rooms β β Crypto β β
β β WebAuthnβ β Messages β β List β β Service β β
β ββββββ¬βββββ ββββββ¬ββββββ ββββββ¬βββββ βββββββ¬ββββββ β
βββββββββΌβββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββ
β β β β
βΌ βΌ βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WebSocket + REST API (Nginx) β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ
β Backend (FastAPI) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Services β β
β β ββββββββββββ ββββββββββββ ββββββββββββββββ β β
β β β Auth β β Message β β Presence β β β
β β β WebAuthn β β Encrypt β β Tracking β β β
β β ββββββββββββ ββββββββββββ ββββββββββββββββ β β
β β ββββββββββββ ββββββββββββ ββββββββββββββββ β β
β β β Prekey β βWebSocket β β Ratchet β β β
β β β X3DH β β Manager β β State β β β
β β ββββββββββββ ββββββββββββ ββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Encryption Core β β
β β double_ratchet.py | x3dh_manager.py β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββ¬βββββββββββββββββββ¬βββββββββββββββββββ¬βββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β PostgreSQL β β SurrealDB β β Redis β
β Users/Creds β β Messages β β Sessions β
β Keys/Prekeysβ β Live Queriesβ β Challenges β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
Alice Bob
β β
β 1. Fetch Bob's prekey bundle β
β ββββββββββββββββββββββββββββββββββββββββββββββ>β
β β
β 2. Bundle: IdentityKey, SignedPrekey, β
β OneTimePrekey, Signature β
β <βββββββββββββββββββββββββββββββββββββββββββββββ
β β
β 3. Verify signature β
β 4. Generate ephemeral keypair β
β 5. Compute shared secrets (DH): β
β DH1 = DH(IK_A, SPK_B) β
β DH2 = DH(EK_A, IK_B) β
β DH3 = DH(EK_A, SPK_B) β
β DH4 = DH(EK_A, OPK_B) β
β 6. Derive root key: HKDF(DH1||DH2||DH3||DH4) β
β 7. Initialize Double Ratchet β
β β
β 8. Send initial message + EK_A public β
β ββββββββββββββββββββββββββββββββββββββββββββββ>β
β β
β 9. Bob computes same secrets β
β 10. Initializes Double Ratchetβ
β β
Each message uses a unique key derived from the ratchet state:
Root Key ββββββ¬βββββ> Chain Key 1 ββ> Message Key 1
β ββ> Message Key 2
β
ββββββ> Chain Key 2 ββ> Message Key 3
ββ> Message Key 4
- Symmetric ratchet: Derives new message keys
- DH ratchet: Updates root key on each reply
- Forward secrecy: Old keys deleted after use
- Break-in recovery: New DH ratchet heals compromise
cd PROJECTS/encrypted-p2p-chat
# Copy environment file
cp .env.example .env
# Start development environment
make dev
# Access at http://localhost:3000Key environment variables:
# PostgreSQL
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/chat
# SurrealDB
SURREAL_URL=ws://localhost:8000/rpc
SURREAL_NS=chat
SURREAL_DB=messages
# Redis
REDIS_URL=redis://localhost:6379
# WebAuthn
RP_ID=localhost
RP_NAME=Encrypted Chat
RP_ORIGIN=http://localhost:3000| Model | Database | Purpose |
|---|---|---|
| User | PostgreSQL | User accounts |
| Credential | PostgreSQL | WebAuthn credentials |
| IdentityKey | PostgreSQL | Long-term identity keys |
| SignedPrekey | PostgreSQL | Signed prekeys for X3DH |
| OneTimePrekey | PostgreSQL | One-time prekeys |
| RatchetState | PostgreSQL | Double ratchet state |
| SkippedMessageKey | PostgreSQL | Out-of-order handling |
| Messages | SurrealDB | Encrypted message storage |
| Store | Purpose |
|---|---|
| authStore | Authentication state |
| messagesStore | Message state |
| roomsStore | Chat room state |
| presenceStore | Online/offline status |
| typingStore | Typing indicators |
| settingsStore | User preferences |
# Backend
make backend-lint
make backend-test
# Frontend
make frontend-lint
make frontend-build
# Both
make lint
make test- All messages encrypted client-side before transmission
- Server never sees plaintext messages
- Keys stored securely, old keys deleted
- WebAuthn prevents phishing attacks
- No passwords to steal or crack
Β©AngelaMos | CertGames.com | CarterPerez-dev | 2025
Progress: 3/60