jhkaktus 6c41779667 feat: systemd unit for deployment behind reverse proxy
Adds deploy/crushdb.service: plain HTTP on 127.0.0.1:5000 (HOST/PORT
env), auto-restart on failure, hardened with ProtectSystem/strict,
NoNewPrivileges, capability drop and restricted address families so
only the SQLite dir and private tmp are writable. Passes
systemd-analyze verify (the one reported warning is the expected
/path-in-this-repo venv path of the source checkout, not the deployed
one).

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-11 00:10:58 +02:00
2026-10-10 21:50:03 +00:00

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.

Starten (HTTP; TLS über Reverse Proxy)

python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python run.py
# → http://127.0.0.1:5000

Die App lauscht auf dem lokalen HTTP-Port (default 127.0.0.1:5000, ü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.

Tests

./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.

S
Description
a secure database for saving transaktions betwen persons
Readme MIT
208 KiB
Languages
Python 78.3%
JavaScript 19.1%
CSS 2.6%