<<<<<<< HEAD # Kecalek_python ======= # 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. ## Soubory ### Server | Soubor | Účel | |--------|------| | `server.py` | Asyncio TCP server, handler dispatch, rate limiting, notifikace | | `db.py` | MySQL CRUD, jedna connection na volání | | `schema.sql` | MySQL schéma (users, conversations, messages, ...) | ### Klient | Soubor | Účel | |--------|------| | `gui_client.py` | PyQt6 GUI | | `client.py` | CLI klient | | `chat_core.py` | Logika klienta — session management, šifrování, lokální klíče | ### Sdílené (server + klient) | Soubor | Účel | |--------|------| | `crypto_utils.py` | Ed25519, X25519, AES-256-GCM, HKDF, PBKDF2, X3DH, Double Ratchet (state rollback), Sender Keys (state rollback), ECP1 key encryption | | `protocol.py` | Newline-delimited JSON protokol, base64 encoding | ## Quick Start 1. `pip install -r requirements.txt` 2. Spustit `schema.sql` v MySQL (kompletní clean start). Pro migraci existující DB: `migration_multi_device.sql`. 3. `python server.py` 4. Klient: `python client.py` (CLI) nebo `python gui_client.py` (GUI, PyQt6) ## Jak funguje šifrování ### Klíče na uživatele | Klíč | Typ | Účel | |------|-----|------| | RSA-4096 | Asymetrický | Pouze login challenge-response. Šifrovaný PBKDF2 (600k iterací) + AES-256-GCM. | | Identity Key (IK) | Ed25519 | Podpisy, konverze na X25519 pro X3DH. Šifrovaný PBKDF2 (600k iterací) + AES-256-GCM. | | Signed Pre-Key (SPK) | X25519 | DH v X3DH, podepsaný IK. **Rotuje se každých 7 dní** s grace periodem pro in-flight X3DH. | | 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 1. Alice chce napsat Bobovi poprvé → stáhne jeho key bundle (IK, SPK, OPK) ze serveru. 2. X3DH: 4 DH výpočty → shared secret. 3. Double Ratchet inicializován ze shared secret. 4. Každá zpráva: symmetric ratchet (HMAC chain) → message key → AES-256-GCM. 5. Každá odpověď: DH ratchet (nový X25519 keypair) → nový root key + chain key. 6. Per-recipient ciphertext — každý recipient má vlastní šifrovaný blob. 7. Při selhání dešifrování: automatický rollback stavu ratchetu (snapshot/restore). ### Skupiny — Sender Keys 1. Každý člen má vlastní sender key chain pro skupinu. 2. Sender key se distribuuje ostatním členům přes pairwise Double Ratchet (jako DM). 3. Skupinové zprávy: symmetric ratchet na sender key → AES-256-GCM. 4. Jeden ciphertext pro celou skupinu (efektivní). ### Lokální úložiště klíčů ``` ~/.encrypted_chat/{email}/ private.pem # RSA (login) — ECP1 formát s heslem, PEM bez hesla public.pem # RSA (login) identity_private.bin # Ed25519 — ECP1 formát s heslem, 32B raw bez hesla identity_public.bin # Ed25519 device_id.txt # UUID tohoto zařízení spk_private.bin # Aktuální signed prekey (šifrovaný AES-256-GCM) spk_id.txt prev_spk_private.bin # Předchozí SPK, grace period (šifrovaný AES-256-GCM) prev_spk_id.txt opk_private/ # One-time prekeys (šifrované AES-256-GCM) {opk_id}.bin login_lockout.json # Brute-force lockout stav (failed_attempts, locked_until) sessions/ # Double Ratchet stavy (šifrované AES-256-GCM) {user_id}_{device_id}.bin sender_keys/ # Vlastní sender keys pro skupiny {conv_id}.bin sender_keys_recv/ # Přijaté sender keys od ostatních {conv_id}_{sender_id}_{device_id}.bin ``` ## Bezpečnostní hardening ### Šifrování privátních klíčů na disku (ECP1 formát) RSA a Ed25519 privátní klíče šifrované heslem používají vlastní formát ECP1 (Encrypted Chat PBKDF v1): - **PBKDF2-HMAC-SHA256** s 600 000 iteracemi (OWASP 2023 doporučuje 480k+) - **AES-256-GCM** pro šifrování, magic bytes "ECP1" jako AAD - **Formát:** `ECP1(4B) + salt(16B) + nonce(12B) + ciphertext+tag` - **Zpětná kompatibilita:** Staré PEM soubory (z `BestAvailableEncryption`) se načtou automaticky a při dalším uložení se přešifrují do ECP1. ### Šifrování SPK/OPK na disku SPK a OPK privátní klíče jsou šifrované AES-256-GCM klíčem `_local_key` (HKDF z Ed25519 identity key): - Při save: `_encrypt_local(raw, local_key)` → `nonce(12B) + tag(16B) + ciphertext` - Při load: `_decrypt_local()` s transparentní migrací — pokud dešifrování selže, načte jako plaintext a uloží šifrovaně - Aplikováno na `spk_private.bin`, `prev_spk_private.bin`, `opk_private/*.bin` ### Brute-force ochrana (client-side lockout) Po chybném zadání hesla se prodlužuje čas do dalšího pokusu: - **Vzorec:** `min(2^N, 300)` sekund, kde N = počet neúspěšných pokusů (2s, 4s, 8s, ... až 5 min) - **Stav:** `login_lockout.json` v adresáři klíčů (`failed_attempts`, `locked_until`) - **Aplikováno na:** `ChatClient.login()` (síťový login) + GUI privacy overlay unlock (`_on_unlock_attempt`) - **Reset:** Úspěšné přihlášení smaže lockout soubor - **Defense-in-depth:** Smazání souboru resetuje počítadlo, ale PBKDF2-600k stále zpomaluje každý pokus (~0.5s/pokus) ### SPK rotace (7 dní) Signed Pre-Key se rotuje periodicky: - Po přihlášení `_ensure_prekeys()` zjistí stáří SPK ze serveru (`spk_created_at`) - Pokud je SPK starší než 7 dní → vygeneruje nový, starý uloží jako grace period - **Grace period:** `prev_spk_private.bin` — pokud příchozí X3DH selže s aktuálním SPK, zkusí předchozí - Omezuje dopad kompromitace SPK — útočník může vytvářet nové sessions max 7 dní ### Odolnost ratchetu (state rollback) Double Ratchet i Sender Keys automaticky rollbackují stav při selhání dešifrování: - Před modifikací chain keys/counters se vytvoří snapshot - Pokud AES-GCM dešifrování selže (corrupted data, wrong key), stav se obnoví - Session zůstane funkční i po zpracování poškozené zprávy ## Registrace 1. `register` → server pošle 6-místný kód na email (nebo vrátí přímo v dev módu bez SMTP). 2. `register_confirm` → potvrzení kódu. 3. Automaticky se vygenerují a uploadnou prekeys (1 SPK + 50 OPKs). 4. Login. ## Multi-Device Support Pravý multi-device (Signal-like) — každé zařízení má nezávislé Double Ratchet sessions. Při posílání DM se zpráva šifruje zvlášť pro každé zařízení příjemce. Všechna zařízení uživatele sdílejí Ed25519 identity key (pro self-encryption kompatibilitu). ### Architektura - **Devices tabulka** — každé přihlášení registruje device (UUID), server mapuje writer→device - **Per-device prekeys** — každé zařízení má vlastní SPK + OPKs, server vrací `device_bundles` pole - **Per-device sessions** — sessions klíčované `"user_id:device_id"`, nezávislé Double Ratchet instance - **Self-encryption** — odesílatel šifruje vlastní kopii statickým klíčem z identity key (čitelné všemi vlastními zařízeními) - **Notifikace** — `device_entries` pole, klient vybere záznam odpovídající svému device_id ### Device Pairing (zjednodušený) Nové zařízení získá RSA + Ed25519 identity klíče od existujícího zařízení. Přenos šifrovaný RSA-OAEP + AES-GCM přes server (server nevidí klíče). Nové zařízení si po přihlášení automaticky vygeneruje vlastní SPK + OPKs. 1. Nové zařízení: `Link Device` → dostane 8-místný kód. 2. Existující zařízení: `Authorize Device` → zadá kód → odešle RSA + identity klíče. 3. Nové zařízení importuje klíče, přihlásí se, vygeneruje vlastní prekeys. ### Migrace - Existující DB: spustit `migration_multi_device.sql` (nebo `migration_multi_device_resume.sql` pro idempotentní re-run) - Čistá DB: `schema.sql` již obsahuje všechny multi-device sloupce ## Device Revocation (Key Rotation) Rotuje RSA login klíč. Odpojí ostatní sessions. Forward secrecy zajišťuje, že kompromitace jednoho session klíče neodhalí historii — není potřeba re-encryption. ## Konfigurace ### Server + DB - `SERVER_HOST` (default `127.0.0.1`), `SERVER_PORT` (default `9999`) - `MYSQL_HOST`, `MYSQL_PORT`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE` ### TLS - `TLS_ENABLED` — zapne TLS (default `false`) - `TLS_REQUIRED` — vyžaduje TLS_ENABLED, jinak server odmítne start - `TLS_CERT_FILE`, `TLS_KEY_FILE` — cesty k certifikátu a privátnímu klíči (PEM) - `TLS_AUTOGEN` — auto-generuje self-signed cert (**jen s `ENVIRONMENT=dev`**) - `TLS_CA_FILE` (klient) — vlastní CA certifikát pro ověření serveru - `TLS_INSECURE` (klient) — vypne ověření certifikátu (**jen s `ENVIRONMENT=dev`**) - `ENVIRONMENT` — `dev`/`development` povolí TLS_INSECURE a TLS_AUTOGEN #### Produkční nasazení s Let's Encrypt ```bash # 1. Nainstalovat certbot sudo apt install certbot # 2. Získat certifikát (port 80 musí být volný pro ověření) sudo certbot certonly --standalone -d chat.example.com # 3. V .env nastavit: TLS_ENABLED=true TLS_CERT_FILE=/etc/letsencrypt/live/chat.example.com/fullchain.pem TLS_KEY_FILE=/etc/letsencrypt/live/chat.example.com/privkey.pem # 4. Klient — stačí zapnout TLS (Let's Encrypt je v systémovém trust store): TLS_ENABLED=true ``` Certifikát funguje na jakémkoliv portu (9999, 443, ...) — je vázaný na doménu, ne port. Certbot automaticky obnovuje certifikát každých 90 dní. #### Dev/testování (self-signed) ```bash ENVIRONMENT=dev TLS_ENABLED=true TLS_AUTOGEN=true # server auto-generuje self-signed cert TLS_INSECURE=true # klient přeskočí ověření certifikátu ``` ### SMTP - `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM` - Bez SMTP = dev mód (kód se vrací přímo klientovi). ### Obrázky - `UPLOAD_DIR` (default `uploads`), `MAX_IMAGE_BYTES` (default 5 MB, `0` = bez limitu) ### Limity - `MAX_MESSAGE_BYTES` (default `65536`), `MAX_INPUT_CHARS` (GUI, default `2000`) - Rate limity: register 3/min, login 10/min, send_message 20/min, pairing_poll 10/min - Connection: 20 req/s per connection, max 10 per IP, 200 global - Pairing TTL: 120s, max 5 failed poll pokusů ### Logging - `LOG_LEVEL` (default `INFO`) ## Features - Registrace (2-step, SMTP), login (RSA challenge-response), key rotation - **Multi-device** — per-device sessions (Signal-like), device pairing (RSA + identity key transfer), automatické prekey generování na novém zařízení - DM s forward secrecy (X3DH + Double Ratchet) — per-device šifrování - Skupiny se Sender Keys (distribuované přes pairwise ratchet) - Skupinové pozvánky — přidání do skupiny vyžaduje souhlas (accept/decline) - Odpovědi na zprávy (reply_to) - Mazání zpráv (soft-delete pro všechny, real-time notifikace) - Mazání konverzací (pravý klik → smaže pro uživatele, pokud nezbývají členové smaže celou konverzaci) - Šifrované obrázky (AES-256-GCM, chunked upload, thumbnail v bublině) - Šifrované soubory (PDF, ZIP, atd. až 50 MB, chunked upload) - Read receipts (real-time, client-side resoluce) - Prekey replenishment (automatické doplňování OPKs po loginu + SPK rotace každých 7 dní) - Silné šifrování klíčů na disku (PBKDF2 600k iterací + AES-256-GCM, ECP1 formát) - Odolný ratchet — automatický rollback stavu při selhání dešifrování - TLS (volitelný, auto-gen self-signed) - Real-time notifikace konverzací — nové konverzace, přidání/odebrání členů se zobrazí okamžitě bez re-loginu - Connection state indicator — zelená/červená/oranžová tečka, automatický reconnect s exponential backoff - Online/offline status — zelená tečka na avataru v seznamu konverzací + v group info - User profily — telefon, lokace, avatar, nastavení viditelnosti (email, telefon, lokace) - Phantom users — anti user-enumeration: konverzace s neregistrovaným emailem funguje normálně (odesílatel vidí své zprávy), zprávy pro phantom příjemce se neukládají, phantom se smaže při skutečné registraci - Clickable links — HTTPS modré, HTTP oranžové s ikonou zámku + potvrzovací dialog ### GUI (PyQt6) - Dark theme (Catppuccin Mocha) - Seznam konverzací s kulatými avatary a online indikátorem (zelená tečka) - Unread count badge na konverzacích (číselný počet nepřečtených zpráv) - Message bubliny s barevným left border, timestamp vedle jména - Read receipts (checkmarks), group info dialog, add/remove member - Context menu: reply, delete, view image, download file - Attach button pro obrázky a soubory, thumbnail v bublině, full-size viewer + save - Pagination ("Load older messages") - Connection indicator (zelená=online, červená=offline, oranžová=reconnecting) - Auto-reconnect s exponential backoff (1s → 2s → 4s → ... → max 30s) - Tlačítko "My Profile" — editace vlastního profilu (telefon, lokace, avatar, viditelnost) - User profil dialog — klik na info tlačítko v group info → read-only profil uživatele - Avatar upload/download (JPEG/PNG, max 2 MB, kruhový výřez) - Leave group (červené tlačítko v group info, přenos creatora) - Pozvánky do skupin — seznam pending pozvánek nad konverzacemi, pravý klik → accept/decline - Periodický refresh avatarů a pozvánek (každé 2 minuty) ### CLI - Základní funkcionalita (DM, skupiny, šifrování). Profily a soubory pouze přes GUI. ## Závislosti - `cryptography` — Ed25519, X25519, AES-GCM, RSA, HKDF, PBKDF2 - `mysql-connector-python` — MySQL - `python-dotenv` — env vars - `PyQt6` — GUI - `Pillow` — resize/thumbnail obrázků ## Known Issues - Sender Keys pro skupiny se nedistribuují znovu při přidání nového člena (nový člen neuvidí staré skupinové zprávy). ## TODO ### Security — Zbývající - [ ] **H9: Self-encryption key** — statický/deterministický klíč (by-design pro cross-device, architektonické omezení) - [ ] M1: Nekonzistentní Ed25519 serializace (částečně vyřešeno M3 — ECP1 formát, ale 3 legacy formáty) - [ ] M6: TOCTOU race v membership checks - [ ] M7: MySQL spojení bez TLS - [ ] L1-L8: Low-priority hardening - [ ] **Penetrační testy** — manuální + automatizované ### Features — High Priority - [ ] Redistribuce sender keys při přidání nového člena do skupiny - [ ] Typing indicators ### Features — Medium Priority - [ ] Hledání zpráv v konverzacích - [ ] Group admin roles (více adminů) - [ ] Edit sent messages ### Features — Low Priority - [ ] Dark/light theme toggle - [ ] Desktop notifications (system tray) - [ ] Database connection pooling - [ ] Image gallery view - [ ] Systemd + Docker deployment ### Monetizace Oddělený platební server (Stripe, KYC/AML compliant) od chat serveru (anonymní). Platba → premium kód → aktivace na chat serveru. Žádný přímý link platba↔chat identita. - **Free tier:** 5 konverzací, 10 MB soubory, 1 zařízení, 30 dní retence, max 10 členů/skupina - **Premium:** neomezeno — aktivace jednorázovým kódem z platebního serveru - **Enterprise:** self-hosted, LDAP/SSO, admin dashboard, SLA — faktura na firmu - Detaily implementace viz `CLAUDE.md` ### Hotovo — Security - [x] **C1-C6: Všechny CRITICAL opraveny** — readuntil DoS, sender key fast-forward, OPK permissions, upload size check, path traversal (UUID validace + is_relative_to) - [x] **H1-H8, H10-H14: Většina HIGH opravena** — lokální šifrování dat (AES-256-GCM), TLS hardening (INSECURE/AUTOGEN jen v dev), anti-enumeration, race conditions (asyncio.Lock), protokol error handling, avatar path traversal, hesla v paměti (bytearray+zero), image validace, filename sanitizace, OPK race condition (SELECT FOR UPDATE) - [x] **M2-M5+M8-M13: Většina MEDIUM opravena** — HKDF salt, PBKDF2 600k iterací (ECP1 formát), SPK rotace 7 dní s grace periodem, rate limit cleanup, UUID validace, ratchet state rollback, message_ids cap, pairing poll token, upload check, chmod 0o700/0o600 - [x] **SPK/OPK šifrování + brute-force lockout** — všechny privátní klíče na disku šifrované (ECP1 nebo AES-256-GCM), exponenciální backoff po chybném hesle (2^N s, max 5 min) ### Hotovo — Features - [x] **Multi-device support** — per-device sessions (Signal-like), device pairing, automatické prekey generování - [x] Unread counts pro offline uživatele - [x] Clickable HTTP links — HTTPS modré, HTTP oranžové s varováním - [x] User profily (telefon, lokace, avatar, viditelnost) - [x] Connection state indicator + auto-reconnect - [x] Encrypted file sharing (až 50 MB) - [x] Leave group + přenos creatora - [x] Unread count badge - [x] User avatars (upload/download, kruhový výřez) - [x] Online/offline status (zelená tečka na avataru) - [x] Mazání konverzací - [x] Skupinové pozvánky (accept/decline) - [x] Graceful server shutdown ## 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 | **10** | 2 (M1 částečně, M6, M7) | | LOW | 8 | 0 | 8 | Detaily viz `CLAUDE.md`. >>>>>>> d506e65 (initial commit)