2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00
2026-03-11 16:54:14 +01:00

<<<<<<< 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)
  • Notifikacedevice_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)
  • ENVIRONMENTdev/development povolí TLS_INSECURE a TLS_AUTOGEN

Produkční nasazení s Let's Encrypt

# 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)

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

  • C1-C6: Všechny CRITICAL opraveny — readuntil DoS, sender key fast-forward, OPK permissions, upload size check, path traversal (UUID validace + is_relative_to)
  • 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)
  • 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
  • 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

  • Multi-device support — per-device sessions (Signal-like), device pairing, automatické prekey generování
  • Unread counts pro offline uživatele
  • Clickable HTTP links — HTTPS modré, HTTP oranžové s varováním
  • User profily (telefon, lokace, avatar, viditelnost)
  • Connection state indicator + auto-reconnect
  • Encrypted file sharing (až 50 MB)
  • Leave group + přenos creatora
  • Unread count badge
  • User avatars (upload/download, kruhový výřez)
  • Online/offline status (zelená tečka na avataru)
  • Mazání konverzací
  • Skupinové pozvánky (accept/decline)
  • 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)

Description
Šifrovaný messenger pro Desktop a Server Side
Readme 4.8 MiB
Languages
Python 99.3%
Shell 0.5%
Dockerfile 0.2%