
로그인, 메모, API 키를 위한 로컬 우선 암호화 비밀번호 관리자로, Argon2id 및 XChaCha20-Poly1305로 봉인된 SQLite 볼트를 사용하며 클라우드나 텔레메트리가 없습니다.
GTK4 / gtkmm-4 · C++23 · CMake · SQLite · libsodium
lsPass는 로그인, 보안 메모 및 API 키를 로컬 암호화 볼트(vault)에 저장합니다. 네트워크 없음, 클라우드 없음, 원격 측정(telemetry) 없음. 어떤 비밀 정보도 일반 텍스트로 디스크에 기록되지 않습니다.
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
볼트는 ~/.local/share/lspass/vault.db에 저장됩니다(권한 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
.deb 파일은 packages/deb/에 생성되며 바이너리, com.lspass.App.desktop 런처 항목, 앱 아이콘(packaging/com.lspass.App.svg, hicolor 테마로 설치됨)을 포함합니다.
CPack 없이 실행하는 cmake --install은 기본 /usr/local 접두사를 사용합니다. 런타임 종속성(libgtkmm-4.0, libsodium, libsqlite3, …)은 dpkg-shlibdeps가 자동으로 해결하므로, apt --fix-broken install 또는 sudo apt install ./lspass_1.0.0_amd64.deb만으로 필요한 모든 항목이 설치됩니다.
OWASP 비밀번호 저장 치트 시트(Password Storage Cheat Sheet), libsodium 문서, 그리고 기존 비밀번호 관리자(Bitwarden, KeePassXC 스타일 키 래핑)에서 사용하는 봉투 암호화(envelope-encryption) 패턴을 기반으로 합니다:
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])
이러한 선택의 이유:
솔직한 절충: title, username, url은 모든 행을 복호화하지 않고도 목록/검색이 작동하도록 일반 텍스트로 저장됩니다. 비밀 자체(비밀번호, 메모, API 키)는 항상 봉인된 블롭(sealed blob)입니다. 단위 테스트 secrets_not_stored_in_plaintext는 볼트 파일(WAL 포함)을 바이트 단위로 스캔하여 카나리아(canary) 비밀이 저장되어 있지 않음을 증명합니다.
ctest는 GUI가 필요 없는 핵심 라이브러리를 대상으로 세 개의 스위트(41개 케이스)를 실행합니다. 전체 스위트는 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
릴리스 빌드는 -fstack-protector-strong, -D_FORTIFY_SOURCE=2, PIE 및 전체 RELRO(-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 — LICENSE 참조.
| 결정 | 근거 |
|---|
| Argon2id KDF | OWASP가 비밀번호 파생 키에 대해 최우선으로 권장하는 방식입니다. 메모리 하드(memory-hard) 방식으로 GPU/ASIC 크래킹에 저항합니다. 매개변수는 OWASP 최소 기준(m ≥ 19 MiB, t = 2)을 초과합니다. |
| 봉투 암호화(KEK로 래핑된 무작위 DEK) | 마스터 비밀번호를 변경해도 전체 볼트를 다시 암호화하는 대신 32바이트만 다시 래핑하면 됩니다. KEK 없이는 DEK를 손상시킬 수 없습니다. |
| XChaCha20-Poly1305 AEAD | 192비트 무작위 nonce 덕분에 nonce 재사용 문제가 없습니다. Poly1305가 모든 암호문을 인증하므로 잘못된 마스터 비밀번호는 인증 실패로 감지됩니다 — 비밀번호 해시나 검증자(verifier)는 어디에도 저장되지 않습니다. |
AAD 바인딩(lspass:v1:entry:<id>:<field>) | DB 파일에 쓰기 권한이 있는 공격자가 암호문을 다른 항목이나 필드로 옮겨 붙일 수 없습니다. |
| 쓰기마다 새 nonce | 저장할 때마다 새 무작위 nonce로 다시 봉인합니다. |
| 메모리 위생 | 키는 SecureBytes에 저장되며 파괴 시 sodium_memzero로 지워집니다. UI는 사용 직후 비밀번호 필드를 지우고, 클립보드는 복사 후 30초가 지나면 자동으로 지워집니다(여전히 우리의 비밀을 담고 있을 때만). |
| 파일 권한 | 볼트 파일은 chmod 0600입니다. |
| 비밀번호 생성기 | 거부 샘플링(rejection sampling)을 사용하는 커널 CSPRNG(모듈로 편향 없음), 활성화된 모든 문자 클래스를 보장하며 기본적으로 모호한 글리프(glyph)를 제외합니다. 기본 20자에서 약 128비트 엔트로피를 제공합니다. |