Files
crushdb/README.md
T
jhkaktus 2df603b32b style+docs: consistent pre-screen styling and first-start UX docs
Setup screen shares the unlock panel look; README gains an "Erster
Start (UX)" section explaining first visit vs returning visit behaviour.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-11 00:30:51 +02:00

81 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# crushdb – verschlüsselte Datensätze zwischen Personen
Sichere Datenbank für Transaktionen zwischen zwei Personen
(Person A, Person B, Timestamp-Start, Timestamp-Ende, Aktion).
Alle Datensätze werden **im Browser** verschlüsselt
(XChaCha20-Poly1305, Schlüsselableitung per Argon2id aus der Passphrase).
Der Server sieht ausschließlich Chiffretext – auch bei vollständiger
Serverkompromittierung bleiben die Inhalte ohne Passphrase vertraulich.
## Erster Start (UX)
- **Beim ersten Besuch** (Datenbank leer): Die App zeigt "Willkommen" und
fragt zweimal nach einer neuen Passphrase (mindestens 8 Zeichen).
Diese schützt ab sofort alle Datensätze – es gibt keine Zurücksetzung.
- **Bei weiteren Besuchen**: Die App bittet einmal um die bekannte
Passphrase ("Entsperren").
- Der Server speichert niemals die Passphrase selbst, nur verschlüsselte
Datensätze.
## Starten (HTTP; TLS über Reverse Proxy)
```bash
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python run.py
# → http://127.0.0.1:8085
```
Die App lauscht auf dem lokalen HTTP-Port (default `127.0.0.1:8085`,
überschreibbar via `HOST`/`PORT`). Ein vertrauenswürdiger Reverse Proxy
(nginx, caddy, …) beendet HTTPS und reicht intern an die App weiter.
Die App selbst muss von außen nicht erreichbar sein.
### Per systemd laufen lassen
Ein fertiges Unit-File liegt in `deploy/crushdb.service` (Reinheit:
nur `instance/` schreibbar, keine Capabilities, Restart on failure).
Nach dem Kopieren nach `/etc/systemd/system/` und `daemon-reload`
startet `systemctl enable --now crushdb` die App dauerhaft.
## Tests
```bash
./venv/bin/python -m pytest backend/test_integrity.py -v # Integrität/Replay
node .e2e.mjs # optional: End-to-End (siehe unten)
```
## Architektur
| Komponente |Datei | Aufgabe |
|---|---|---|
| Speicher | `backend/storage.py` | SQLite, speichert nur Chiffretext (uuid, ciphertext, nonce, salt, version) |
| API | `backend/app.py` | Flask REST API, Validierung nur von Form/Größe, Versions-Konfliktprüfung |
| Krypto (Client) | `backend/static/crypto.js` | Argon2id-KDF + XChaCha20-Poly1305, uuid+salt als AEAD-AAD gebunden |
| UI | `backend/static/ui.js` + `index.html`/`style.css` | Tabelle, Erstellen, Bearbeiten, Löschen; Passphrase bleibt im RAM |
| Server | `run.py` | HTTP intern hinter Reverse Proxy, DB-Init |
## Sicherheitsmodell
- Passphrase → Argon2id (t=2, m=16 MiB) → 256-Bit-Sitzungsschlüssel,
ausschließlich im Browser/im Arbeitsspeicher; niemals am Server.
- Jeder Datensatz: eigene zufällige 16-Byte-Salt + 24-Byte-Nonce.
uuid + salt sind als AEAD-Associated-Data gebunden – Vertauschen oder
Um-Salten wird beim Entschlüsseln sicher erkannt.
- Monotoner Versionszähler pro Datensatz: veraltete Updates/Deletes
(Replay alter Stände) → `409`, Duplikate → `409`.
- Klartexte werden clientseitig nie persistiert; beim Sperren/Beenden
wird der Schlüssel verworfen (`wipeKey`).
- HTTPS wird außen vom vertrauenswürdigen **Reverse Proxy** beendet
(nginx/caddy/…); die App lauscht nur intern auf HTTP.
## Bekannte Grenzen
- Datenverlust (Löschen/Überschreiben) durch Angreifer bleibt möglich –
Vertraulichkeit ist geschützt, Verfügbarkeit nicht.
- Backups der SQLite-Datei enthalten ausschließlich Chiffretext.
- Backups des Passphrasen-Verlusts = Datenverlust (by design).
Siehe `spezification.txt` für die Anforderungen.