
Lokaler, verschlüsselter Passwortmanager für Anmeldungen, Notizen und API-Schlüssel, mit einem SQLite-Tresor, der mit Argon2id und XChaCha20-Poly1305 versiegelt ist; keine Cloud oder Telemetrie.
GTK4 / gtkmm-4 · C++23 · CMake · SQLite · libsodium
lsPass speichert Anmeldedaten, sichere Notizen und API-Schlüssel in einem lokalen verschlüsselten Tresor. Kein Netzwerk, keine Cloud, keine Telemetrie. Es wird nie ein Geheimnis im Klartext auf die Festplatte geschrieben.
sudo apt install libgtkmm-4.0-dev libsqlite3-dev libsodium-dev nlohmann-json3-dev
cmake -B build
cmake --build build -j
ctest --test-dir build --output-on-failure # 41 unit tests
./build/lspass
Der Tresor befindet sich unter ~/.local/share/lspass/vault.db (Berechtigungen 0600).
cmake -B build-rel -DCMAKE_BUILD_TYPE=Release
cmake --build build-rel -j
cd build-rel && cpack -G DEB # requires: dpkg-dev, file
sudo dpkg -i ../packages/deb/lspass_1.0.0_amd64.deb
Die .deb-Datei landet in packages/deb/ und enthält die Binärdatei, einen com.lspass.App.desktop-Launcher-Eintrag und das App-Icon (packaging/com.lspass.App.svg, installiert in das hicolor-Theme).
cmake --install ohne CPack verwendet das standardmäßige /usr/local-Präfix. Laufzeitabhängigkeiten (libgtkmm-4.0, libsodium, libsqlite3, …) werden automatisch von dpkg-shlibdeps aufgelöst, sodass apt --fix-broken install oder sudo apt install ./lspass_1.0.0_amd64.deb alles Notwendige nachzieht.
Basierend auf dem OWASP Password Storage Cheat Sheet, der libsodium-Dokumentation und dem Envelope-Encryption-Muster, das von etablierten Passwort-Managern verwendet wird (Bitwarden, Key Wrapping im KeePassXC-Stil):
master password
│ Argon2id (memory-hard KDF, random 128-bit salt,
▼ opslimit/memlimit = libsodium "moderate",
KEK (32 B) parameters stored in vault for future upgrades)
│ XChaCha20-Poly1305 (key wrap)
▼
DEK (32 B, random) ── wraps nothing else, RAM only, never on disk
│ XChaCha20-Poly1305 AEAD per field
▼
SQLite: entries(title, username, url [plaintext metadata],
secret, notes [sealed blobs: nonce‖ct‖poly1305 tag])
Warum diese Entscheidungen:
Ehrlicher Kompromiss: title, username und url werden im Klartext gespeichert, damit Liste/Suche funktionieren, ohne jede Zeile zu entschlüsseln. Die Geheimnisse selbst (Passwörter, Notizen, API-Schlüssel) sind immer versiegelte Blobs. Der Unit-Test secrets_not_stored_in_plaintext durchsucht die Tresordatei (inkl. WAL) byteweise nach einem Canary-Secret, um dies zu belegen.
ctest führt drei Suiten (41 Fälle) gegen die GUI-unabhängige Kernbibliothek aus. Die gesamte Suite wird außerdem unter AddressSanitizer + UBSan ausgeführt:
cmake -B build-san -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined"
cmake --build build-san -j && ctest --test-dir build-san
Release-Builds fügen -fstack-protector-strong, -D_FORTIFY_SOURCE=2, PIE und volles RELRO hinzu (-Wl,-z,relro,-z,now).
src/core/crypto.{hpp,cpp} SecureBytes, Argon2id KDF, XChaCha20-Poly1305, key wrap
src/core/vault.{hpp,cpp} SQLite vault, envelope encryption, CRUD
src/core/generator.{hpp,cpp} CSPRNG password/passphrase generator
src/ui/ gtkmm-4 UI (unlock screen, list, editor dialogs)
tests/ ctest suites (no external framework needed)
MIT — siehe LICENSE.
| Entscheidung | Begründung |
|---|
| Argon2id-KDF | Erste Wahl von OWASP für passwortabgeleitete Schlüssel; speicherhärtend, resistent gegen GPU/ASIC-Cracking. Die Parameter übertreffen das OWASP-Minimum (m ≥ 19 MiB, t = 2). |
| Envelope-Encryption (zufälliger DEK, vom KEK umhüllt) | Beim Ändern des Master-Passworts werden nur 32 Bytes neu umhüllt, statt den gesamten Tresor neu zu verschlüsseln; ein Kompromittieren des DEK ist ohne den KEK unmöglich. |
| XChaCha20-Poly1305-AEAD | 192-Bit-Zufallsnonces machen die Wiederverwendung von Nonces praktisch unmöglich; Poly1305 authentifiziert jeden Chiffretext, sodass ein falsches Master-Passwort durch einen Authentifizierungsfehler erkannt wird — nirgendwo wird ein Passwort-Hash oder Verifizierer gespeichert. |
AAD-Bindung (lspass:v1:entry:<id>:<field>) | Chiffretexte können von einem Angreifer mit Schreibzugriff auf die DB-Datei nicht zwischen Einträgen oder Feldern übertragen werden. |
| Frisches Nonce pro Schreibvorgang | Jedes Speichern versiegelt erneut mit einem neuen Zufallsnonce. |
| Speicherhygiene | Schlüssel leben in SecureBytes und werden bei der Zerstörung mit sodium_memzero gelöscht; die UI leert Passwortfelder unmittelbar nach der Verwendung; die Zwischenablage wird 30 s nach dem Kopieren automatisch geleert (und nur, wenn sie noch unser Geheimnis enthält). |
| Dateiberechtigungen | Die Tresordatei ist chmod 0600. |
| Passwortgenerator | Kernel-CSPRNG mit Rejection Sampling (kein Modulo-Bias), garantiert alle aktivierten Zeichenklassen, schließt standardmäßig mehrdeutige Zeichen aus; ~128-Bit-Entropie bei den standardmäßigen 20 Zeichen. |