
Gestor de contraseñas cifrado local-first para inicios de sesión, notas y claves API, que utiliza una bóveda SQLite sellada con Argon2id y XChaCha20-Poly1305; sin nube ni telemetría.
GTK4 / gtkmm-4 · C++23 · CMake · SQLite · libsodium
lsPass guarda inicios de sesión, notas seguras y claves de API en un almacén cifrado local. Sin red, sin nube, sin telemetría. Nunca se escribe nada secreto en disco en texto plano.
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
El almacén se encuentra en ~/.local/share/lspass/vault.db (permisos 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
El .deb se genera en packages/deb/ e incluye el binario, una entrada de lanzador com.lspass.App.desktop y el icono de la aplicación (packaging/com.lspass.App.svg, instalado en el tema hicolor).
cmake --install sin CPack usa el prefijo /usr/local por defecto. Las dependencias en tiempo de ejecución (libgtkmm-4.0, libsodium, libsqlite3, …) se resuelven automáticamente mediante dpkg-shlibdeps, por lo que apt --fix-broken install o sudo apt install ./lspass_1.0.0_amd64.deb instala todo lo necesario.
Basado en la OWASP Password Storage Cheat Sheet, la documentación de libsodium y el patrón de cifrado en sobre (envelope encryption) utilizado por gestores de contraseñas consolidados (Bitwarden, envoltura de claves estilo KeePassXC):
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])
Por qué estas decisiones:
| Decisión | Justificación |
|---|---|
| KDF Argon2id | Primera opción de OWASP para claves derivadas de contraseña; con uso intensivo de memoria, resistente al craqueo por GPU/ASIC. Los parámetros superan el mínimo de OWASP (m ≥ 19 MiB, t = 2). |
| Cifrado en sobre (DEK aleatorio envuelto por KEK) | Cambiar la contraseña maestra solo re-envuelve 32 bytes en lugar de re-cifrar todo el almacén; el compromiso del DEK es imposible sin el KEK. |
| AEAD XChaCha20-Poly1305 | Los nonces aleatorios de 192 bits hacen que la reutilización de nonces no sea un problema; Poly1305 autentica cada texto cifrado, por lo que una contraseña maestra incorrecta se detecta por un fallo de autenticación — no se almacena ningún hash o verificador de contraseña en ningún lugar. |
Vinculación AAD (lspass:v1:entry:<id>:<field>) | Un atacante con acceso de escritura al archivo de la base de datos no puede trasplantar textos cifrados entre entradas o campos. |
| Nonce nuevo en cada escritura | Cada guardado vuelve a sellar con un nonce aleatorio nuevo. |
| Higiene de memoria | Las claves viven en SecureBytes y se borran con sodium_memzero al destruirse; la interfaz limpia los campos de contraseña inmediatamente después de usarlos; el portapapeles se vacía automáticamente 30 s después de copiar (y solo si aún contiene nuestro secreto). |
| Permisos de archivo | El archivo del almacén tiene chmod 0600. |
| Generador de contraseñas | CSPRNG del kernel con muestreo por rechazo (sin sesgo de módulo), garantiza todas las clases de caracteres habilitadas y excluye glifos ambiguos por defecto; entropía de ~128 bits con los 20 caracteres predeterminados. |
Compromiso honesto: title, username y url se almacenan en texto plano para que la lista/búsqueda funcione sin descifrar cada fila. Los secretos en sí (contraseñas, notas, claves de API) son siempre blobs sellados. La prueba unitaria secrets_not_stored_in_plaintext escanea byte a byte el archivo del almacén (incl. WAL) buscando un secreto canario para demostrarlo.
ctest ejecuta tres suites (41 casos) contra la biblioteca central independiente de la interfaz gráfica. Toda la suite también se ejecuta bajo AddressSanitizer + UBSan:
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
Las compilaciones Release añaden -fstack-protector-strong, -D_FORTIFY_SOURCE=2, PIE y RELRO completo (-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 — consulta LICENSE.