diora-web/tui
marwin 50f711831c TUI: Verschlüsselungs-Key per Benutzername+Passwort ableiten statt Konsolen-Export
diora_tui/crypto.py:derive_key_b64 reproduziert app.js' deriveAndStoreKey()
(PBKDF2-HMAC-SHA256, 200000 Iterationen, Salt "diora:"+username) — der
`sync`-Prompt bietet das jetzt als Standardweg zum Schlüssel an, als
Alternative zum bisherigen Weg über die Browser-Konsole (await
exportEncKey()). Funktioniert nur für Accounts, die den Key je über
diora's "Unlock with password"-Formular abgeleitet haben; ein falsches
Passwort/Account führt zu einem abgefangenen DecryptError ("falscher
Key?"), nie zu stillem Fehlverhalten.

Getestet: zwei unabhängige PBKDF2-Implementierungen (hashlib,
cryptography) stimmen für die verwendeten Parameter byte-genau überein;
vollständiger sync-Lauf gegen einen echten Dev-Server mit einem Buch, das
unter einem exakt so abgeleiteten Key verschlüsselt wurde, entschlüsselt
korrekt; falsches Passwort wird sauber als Fehler gemeldet statt
abzustürzen.
2026-08-15 16:55:03 +02:00
..
diora_tui TUI: Verschlüsselungs-Key per Benutzername+Passwort ableiten statt Konsolen-Export 2026-08-15 16:55:03 +02:00
pyproject.toml TUI: Bücher per diora-tui sync vom diora-Server holen und entschlüsseln 2026-08-15 16:41:50 +02:00
README.md TUI: Verschlüsselungs-Key per Benutzername+Passwort ableiten statt Konsolen-Export 2026-08-15 16:55:03 +02:00

diora-tui

Lokaler EPUB-Reader im Terminal — die erste Stufe einer TUI-Version von diora.

Läuft komplett offline gegen eine lokale Bibliothek aus .epub-Dateien und merkt sich den Lesefortschritt pro Buch (progress.json im plattformüblichen Datenverzeichnis, z.B. ~/.local/share/diora-tui/ unter Linux, via platformdirs). Der Fortschritt wird — genau wie im Web-Reader von diora (siehe books/models.py, save_progress) — nur vorwärts überschrieben ("furthest wins"), damit ein älterer/gestaffelter Lauf nie eine bereits weiter gelesene Position zurücksetzt.

diora-tui sync kann Bücher jetzt vom diora-Server holen und lokal entschlüsseln (siehe unten) — Lesefortschritt bleibt aber weiterhin rein lokal, siehe Grenzen unten.

Setup

cd tui
pip install -e .

Nutzung

diora-tui --library ~/Books   # Standard: ~/Books

Tastenkürzel:

  • /k, /j — zeilenweise scrollen
  • n / ] — nächstes Kapitel, p / [ — vorheriges Kapitel
  • Enter — markiertes Buch aus der Bibliothek öffnen
  • Escape / q — zurück zur Bibliothek (im Reader) bzw. beenden (in der Bibliothek)

Bücher vom Server holen (diora-tui sync)

diora-tui sync                              # nutzt gespeicherte Zugangsdaten, sonst interaktive Abfrage
diora-tui sync --server https://diora.creamfresh.xyz --save   # einmalig einrichten + speichern

Lädt alle EPUBs des Accounts über GET /api/sync/ + GET /books/<id>/data/ herunter, entschlüsselt sie lokal (AES-256-GCM, kompatibel zu static/js/app.js) und legt sie als normale .epub-Dateien in --library ab (Dateiname <id> - <Titel>.epub) — von da an funktionieren sie wie jedes andere lokale Buch. Bereits heruntergeladene Bücher werden beim nächsten Lauf übersprungen (kein erneuter Download).

Dafür nötig, beim ersten Lauf abgefragt (danach optional lokal gespeichert unter ~/.config/diora-tui/config.json, chmod 600):

  • Server-URL — z.B. https://diora.creamfresh.xyz.
  • API-Token — diora → Einstellungen (/accounts/settings/) → "Personal Access Token".
  • Verschlüsselungs-Key — der AES-256-Schlüssel, mit dem deine Bücher clientseitig verschlüsselt wurden. Der sync-Prompt bietet zwei Wege:
    1. Aus Benutzername + Passwort ableiten (Standard) — reproduziert exakt, was diora's "Unlock with password"-Formular im Browser tut (PBKDF2-HMAC-SHA256, 200.000 Iterationen, Salt "diora:" + username; siehe static/js/app.js:deriveAndStoreKey). Funktioniert nur, wenn der Account diesen Weg im Browser mindestens einmal benutzt hat — sonst wurde der Key ursprünglich zufällig im Browser erzeugt, und diese Ableitung trifft ihn nicht. sync meldet einen falschen Key als Entschlüsselungsfehler (harmlos, kein Datenverlust), nie als falsches Ergebnis.
    2. Base64-Key direkt einfügen — für den Fall, dass Weg 1 nicht passt. Der Export-Button dafür ist im Browser-UI aktuell nicht verdrahtet (exportEncKey() in app.js existiert, hat aber keinen sichtbaren Button); bis das nachgezogen ist, in der Browser-Devtools-Konsole auf der diora-Seite (nicht /accounts/settings/ — die lädt app.js nicht) ausführen: await exportEncKey() — kopiert den Key ins Clipboard, von dort ins sync-Prompt einfügen.

Der Key/Token wird genauso vertrauensvoll behandelt wie im Web-Client (dort liegt der Schlüssel unverschlüsselt in localStorage): lokal als Klartext in einer 0600-Datei.

Grenzen der aktuellen Version

  • Nur EPUB, kein PDF — sync lädt PDFs im Account gar nicht erst herunter (übersprungen, wird gemeldet), da der Reader sie ohnehin nicht darstellen kann.
  • Text wird pro Kapitel als Fließtext ohne Bild-/Layout-Rendering dargestellt.
  • Lesefortschritt bleibt rein lokal — sync holt nur Bücher, keinen Fortschritt. Der Web-Reader verankert Position als "blockIndex:innerFraction" in seiner eigenen, über das ganze Buch laufenden Absatz-Nummerierung; diese TUI zählt Position dagegen pro Kapitel. Ohne eine echte Übersetzung zwischen beiden Schemata würde ein naiver Abgleich falsche Positionen liefern — deshalb bewusst (noch) nicht gebaut.