f0666ea6ac39d474c8d4822904ed2a0294f637cb
ProtocolReader discarded the entire chunk containing the newline delimiter while draining an oversized message, including bytes after the newline that belong to the next pipelined message. This corrupted framing for the rest of the connection (affects server and client). Salvaged bytes are now kept in a _leftover buffer that read_message() consumes before touching the stream. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Encrypted Chat
End-to-end encrypted chat s forward secrecy (X3DH + Double Ratchet, Signal Protocol). Server ukládá a přeposílá šifrované bloby — nikdy nevidí plaintext.
Architektura
┌─────────────┐ TLS/TCP ┌─────────────┐ MySQL ┌─────────┐
│ GUI/CLI │◄───────────────►│ Server │◄──────────────►│ DB │
│ klient │ JSON + base64 │ (asyncio) │ │ │
└─────────────┘ └─────────────┘ └─────────┘
│ │
│ X3DH + Double Ratchet │ Opaque blobs
│ Sender Keys (skupiny) │ (server nevidí plaintext)
▼ ▼
Lokální klíče Šifrované zprávy
(~/.encrypted_chat/) + metadata
Soubory
Server
| Soubor | Řádky | Účel |
|---|---|---|
server.py |
~2 900 | Asyncio TCP server, 45 handlerů, rate limiting, 5 asyncio.Lock guardů, real-time notifikace |
db.py |
~1 700 | MySQL CRUD, connection pooling (pool_size=10), phantom users, reactions/pins CRUD |
schema.sql |
~190 | MySQL schéma (14 tabulek) |
Klient
| Soubor | Řádky | Účel |
|---|---|---|
gui_client.py |
~6 300 | PyQt6 GUI — dark/light téma, widget-based message bubbles, verifikace kontaktů, privacy overlay |
client.py |
~900 | CLI klient — 23 menu opcí |
chat_core.py |
~3 500 | Sdílená logika — session management, X3DH/ratchet šifrování, lokální klíče, multi-device |
theme.py |
~540 | Catppuccin dark + Signal-inspired light téma, live switching |
Sdílené (server + klient)
| Soubor | Účel |
|---|---|
crypto_utils.py (~935 ř.) |
Ed25519, X25519, AES-256-GCM, HKDF, PBKDF2, X3DH, Double Ratchet (state rollback), Sender Keys (state rollback), ECP1 key encryption, contact verification (fingerprints, safety numbers, QR), message padding |
protocol.py (~140 ř.) |
Newline-delimited JSON protokol, base64 encoding, verze (0.8.4) |
iOS klient
| Složka | Účel |
|---|---|
ios_client/ (47 Swift souborů, ~5 000 ř.) |
Nativní iOS port — CryptoKit + pure Swift GF(2^255-19) + Security.framework RSA, SwiftUI views, wire-kompatibilní s Python serverem |
Testy
| Soubor | Účel |
|---|---|
tests/pentest_client.py (~340 ř.) |
Automatizované security regresní testy (AuthZ, malformed headers, session reset, rate limits) |
Quick Start
pip install -r requirements.txt- Spustit
schema.sqlv MySQL python server.py- Klient:
python gui_client.py(GUI) nebopython client.py(CLI)
Jak funguje šifrování
Klíče na uživatele
| Klíč | Typ | Účel |
|---|---|---|
| RSA-4096 | Asymetrický | Pouze login challenge-response. Šifrovaný ECP1 (PBKDF2 600k + AES-256-GCM). |
| Identity Key (IK) | Ed25519 | Podpisy, konverze na X25519 pro X3DH. Šifrovaný ECP1. |
| Signed Pre-Key (SPK) | X25519 | DH v X3DH, podepsaný IK. Rotuje se každých 7 dní s grace periodem. |
| One-Time Pre-Keys (OPK) | X25519 | Jednorázové, spotřebuje se při X3DH, automaticky doplňované (< 20 → +50). |
DM (1:1 zprávy) — X3DH + Double Ratchet
- Alice stáhne Bobovy per-device key bundles (IK, SPK, OPK) → X3DH per device → shared secret per device.
- Double Ratchet inicializován ze shared secret — jedna session per (user, device).
- Každá zpráva: symmetric ratchet (HMAC chain) → message key → AES-256-GCM.
- Každá odpověď: DH ratchet (nový X25519 keypair) → nový root key + chain key.
- Per-device ciphertext — každé zařízení příjemce dostane individuálně šifrovaný blob.
- Self-encrypted kopie s SELF_DEVICE_ID sentinel, čitelná všemi vlastními zařízeními.
Skupiny — Sender Keys
- Každý odesílatel má vlastní SenderKeyState per group.
- Sender key distribuován členům přes pairwise Double Ratchet (jako control DM).
- Skupinové zprávy: symmetric ratchet na sender key → AES-256-GCM.
- Stejný ciphertext pro všechny příjemce (efektivní).
Kontaktní verifikace (Signal-style)
- Safety numbers — 60-digit číslo (12 skupin × 5 číslic), deterministické pro každý pár.
- QR kódy — binární payload zakódovaný jako base64.
- Fingerprints — 30-digit per-user číslo.
- TOFU — Trust On First Use + explicit verification + key change warning.
Lokální úložiště klíčů
~/.encrypted_chat/{email}/
private.pem / public.pem — RSA (login, ECP1 formát)
identity_private.bin / _public.bin — Ed25519 (ECP1 formát)
device_id.txt — UUID tohoto zařízení
spk_private.bin / spk_id.txt — Aktuální SPK (AES-256-GCM)
prev_spk_private.bin / prev_spk_id.txt — Předchozí SPK, grace period
opk_private/{opk_id}.bin — One-time prekeys (AES-256-GCM)
sessions/{uid}_{did}.bin — Double Ratchet stavy (AES-256-GCM)
sender_keys/{conv_id}.bin — Vlastní sender keys
sender_keys_recv/{conv}_{uid}_{did}.bin — Přijaté sender keys
known_identity_keys.bin — TOFU registr (AES-256-GCM)
verified_contacts.bin — Explicitní verifikace (AES-256-GCM)
message_cache/{conv_id}.bin — Šifrovaný message cache
login_lockout.json — Brute-force lockout stav
Bezpečnostní hardening
Šifrování privátních klíčů (ECP1 formát)
- PBKDF2-HMAC-SHA256 s 600 000 iteracemi (OWASP 2023)
- AES-256-GCM, magic bytes "ECP1" jako AAD
- Formát:
ECP1(4B) + salt(16B) + nonce(12B) + ciphertext+tag - Zpětná kompatibilita: staré PEM se migrují automaticky
Lokální šifrování dat
- Session/sender key soubory, OPK, SPK, message cache, verifikační soubory — AES-256-GCM klíčem z HKDF(identity_key)
chmod 0o700na adresáře,0o600na soubory
Brute-force ochrana
- Exponenciální backoff:
min(2^N, 300)sekund po N chybných pokusech - Aplikováno na login + privacy overlay unlock
SPK rotace (7 dní)
- Automatická rotace s grace periodem pro in-flight X3DH
- Omezuje dopad kompromitace SPK
Ratchet state rollback
- Snapshot/restore při selhání dešifrování (DoubleRatchet + SenderKeyState)
Secure deletion
- Overwrite
os.urandom()+fsync+unlinkna smazané citlivé soubory
Message padding
- Bucketed padding (64B–64KB) maskuje délku zpráv
Metadata privacy
- Log sanitizace (žádná PII), metadata retention (90 dní), sender chain minimalizace
Anti-enumeration
- Phantom users pro neregistrované emaily
- Generické odpovědi na register/login/get_user_info
Multi-Device Support
Pravý multi-device (Signal-like) — každé zařízení má nezávislé Double Ratchet sessions.
- Devices tabulka — každé přihlášení registruje device (UUID)
- Per-device prekeys — každé zařízení má vlastní SPK + OPKs
- Per-device sessions — klíčované
"user_id:device_id" - Self-encryption — statický klíč z identity key (čitelné všemi vlastními zařízeními)
- Pairing — přenos RSA + Ed25519, nové zařízení generuje vlastní SPK + OPKs
Features
Protokol & šifrování
- X3DH + Double Ratchet (DM) s forward secrecy
- Sender Keys (skupiny) s distribucí přes pairwise ratchet
- Per-device šifrování (multi-device)
- SPK rotace (7 dní) + grace period
- Ratchet state rollback při selhání
- ECP1 šifrování klíčů (PBKDF2 600k)
- Message padding (bucketed 64B–64KB)
- Kontaktní verifikace (safety numbers, fingerprints, QR kódy)
Komunikace
- DM + skupinové konverzace
- Reakce na zprávy (thumbsup, heart, laugh, surprised, sad, thumbsdown)
- Přeposílání zpráv (text, obrázky, soubory)
- Připnuté zprávy (pin/unpin + dialog)
- @Mentions s autocomplete
- Odpovědi na zprávy (reply_to)
- Hledání zpráv (client-side, Ctrl+F)
- Šifrované obrázky (AES-256-GCM, chunked upload, thumbnail)
- Šifrované soubory (až 50 MB, chunked upload)
- Read receipts (real-time)
Skupiny
- Skupinové pozvánky (accept/decline)
- Leave group + přenos creatora
- Rename group (creator only)
- Delete conversation (DMs per-user, groups creator-only)
- Group avatar
Správa
- Multi-device support (per-device sessions, pairing)
- User profily (telefon, lokace, avatar, viditelnost)
- Online/offline status
- Session reset (při poškození ratchetu)
- Key rotation (revokace zařízení)
- Brute-force lockout
GUI (PyQt6)
- Dark (Catppuccin Mocha) + Light (Signal) téma s live switching
- Widget-based message bubbles s ConversationDelegate
- Cirkulární avatary + online zelená tečka
- Unread count badges
- Privacy overlay / lock screen (30s timeout + heslo)
- Drag & drop souborů
- Frameless dialogy
- Connection indicator (green/red/orange) + auto-reconnect
- VerificationDialog (safety numbers, QR, fingerprints)
- Key change warning dialog
CLI
- 23 menu opcí (DM, skupiny, soubory, reakce, piny, forwarding, verifikace, zařízení, search)
iOS (SwiftUI)
- Wire-kompatibilní s Python serverem
- Kompletní Signal Protocol (X3DH, Double Ratchet, Sender Keys)
- CryptoKit + pure Swift field arithmetic + Security.framework RSA
- SwiftUI views (login, chat, groups, profiles, search)
Konfigurace
Server + DB
SERVER_HOST(default127.0.0.1),SERVER_PORT(default9999)MYSQL_HOST,MYSQL_PORT,MYSQL_USER,MYSQL_PASSWORD,MYSQL_DATABASEDB_POOL_SIZE(default10)
TLS
TLS_ENABLED— zapne TLS (defaultfalse)TLS_REQUIRED— vyžaduje TLS_ENABLEDTLS_CERT_FILE,TLS_KEY_FILE— cesty k certifikátu (PEM)TLS_AUTOGEN— auto-generuje self-signed cert (jen sENVIRONMENT=dev)TLS_CA_FILE(klient) — vlastní CA certifikátTLS_INSECURE(klient) — vypne ověření certifikátu (jen sENVIRONMENT=dev)
SMTP
SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS,SMTP_FROM- Bez SMTP = dev mód (kód se vrací přímo klientovi)
Limity
MAX_MESSAGE_BYTES(default65536),MAX_IMAGE_BYTES(5 MB),MAX_FILE_BYTES(50 MB)MAX_INPUT_CHARS(GUI, default2000)METADATA_RETENTION_DAYS(default90)- Rate limity: register 3/min, login 10/min, send_message 20/min
- Connection: 20 req/s, max 10/IP, 200 global
Logging
LOG_LEVEL(defaultINFO)
Bezpečnostní audit
Dva bezpečnostní audity provedeny (kód review). Nalezeno 6 CRITICAL, 12 HIGH, 12 MEDIUM, 8 LOW nálezů.
| Závažnost | Celkem | Opraveno | Zbývá |
|---|---|---|---|
| CRITICAL | 6 | 6 | 0 |
| HIGH | 12 | 11 | 1 (H9 — by-design) |
| MEDIUM | 12 | 11 | 1 (M7) |
| LOW | 8 | 1 | 7 |
Detaily viz SECURITY_AUDIT.md a CLAUDE.md.
Known Issues
- Sender Key Redistribution: Nový člen skupiny nedešifruje staré skupinové zprávy (sender keys se nedistribuují znovu při přidání).
- iOS: Contact Key Verification — safety numbers, QR kódy, TOFU zatím neimplementovány v iOS klientu.
Docker a CI/CD
Lokální vývoj s Docker Compose
# Spustit server + MySQL
docker compose up
# Rebuild po změně kódu
docker compose up --build
# Zastavit a smazat data
docker compose down -v
Server bude dostupný na localhost:5000. MySQL na localhost:3306.
Schéma se automaticky importuje při prvním spuštění.
Ruční build Docker image
docker build -t encrypted-chat-server .
docker run -p 5000:5000 \
-e MYSQL_HOST=host.docker.internal \
-e MYSQL_USER=chat \
-e MYSQL_PASSWORD=chatpassword \
-e MYSQL_DATABASE=encrypted_chat \
-e ENVIRONMENT=dev \
encrypted-chat-server
Produkční deployment
- Získat TLS certifikát (Let's Encrypt / vlastní CA)
- Nastavit env vars — viz
.env.example - Spustit:
docker compose -f docker-compose.yml up -d - Ověřit health:
docker compose ps
Kritické produkční proměnné:
TLS_ENABLED=true,TLS_CERT_FILE,TLS_KEY_FILEMYSQL_PASSWORD— silné hesloENVIRONMENT=production(nedev)SMTP_*— pro registrační emaily
CI/CD (GitHub Actions)
Pipeline v .github/workflows/ci.yml spouští při každém push/PR:
- Lint —
ruff checkna všechny Python soubory - Crypto testy —
test_crypto_integration.py(bez serveru) - Integration testy — spustí MySQL + server, pak
test_server_integration.py - Docker build — ověří že se image builduje bez chyb
Závislosti
cryptography— Ed25519, X25519, AES-GCM, RSA, HKDF, PBKDF2mysql-connector-python— MySQL s connection poolingpython-dotenv— env varsPyQt6— GUIPillow— resize/thumbnail obrázkůqrcode— generování QR kódůpyzbar(volitelné) — skenování QR kódů
Description
Languages
Python
99.3%
Shell
0.5%
Dockerfile
0.2%