
مدير كلمات مرور مشفّر يعمل محليًا أولاً، لتسجيلات الدخول والملاحظات ومفاتيح API، يعتمد خزينة SQLite مؤمّنة بخوارزميتَي Argon2id وXChaCha20-Poly1305؛ دون أي سحابة أو تتبّع عن بُعد.
GTK4 / gtkmm-4 · C++23 · CMake · SQLite · libsodium
يخزّن lsPass بيانات تسجيل الدخول والملاحظات الآمنة ومفاتيح API في خزنة مشفّرة محلية. لا شبكة، لا سحابة، لا تتبع. لا يُكتب أي سر على القرص كنص صريح أبدًا.
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).
يستخدم cmake --install دون CPack البادئة الافتراضية /usr/local. ويتم حلّ التبعيات وقت التشغيل (libgtkmm-4.0, libsodium, libsqlite3, …) تلقائيًا بواسطة dpkg-shlibdeps، لذا فإن apt --fix-broken install أو sudo apt install ./lspass_1.0.0_amd64.deb يجلب كل ما يلزم.
استنادًا إلى ورقة OWASP لتخزين كلمات المرور، ووثائق libsodium، ونمط تشفير المغلف المستخدم في مديري كلمات المرور الراسخين (تغليف المفاتيح بأسلوب Bitwarden و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])
لماذا هذه الخيارات:
مفاضلة صريحة: تُخزَّن title وusername وurl كنص صريح حتى تعمل القائمة والبحث دون فك تشفير كل صف. أما الأسرار نفسها (كلمات المرور، الملاحظات، مفاتيح API) فهي دائمًا كتل مختومة. يفحص اختبار الوحدة secrets_not_stored_in_plaintext ملف الخزنة بايتًا بايت (بما في ذلك WAL) بحثًا عن سر كناري لإثبات ذلك.
يشغّل ctest ثلاث مجموعات (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 للمفاتيح المشتقة من كلمة المرور؛ كثيفة الذاكرة، ومقاومة لفك التشفير عبر GPU/ASIC. تتجاوز المعاملات الحد الأدنى في OWASP (m ≥ 19 MiB, t = 2). |
| تشفير المغلف (DEK عشوائي يغلّفه KEK) | تغيير كلمة المرور الرئيسية يعيد تغليف 32 بايتًا فقط بدل إعادة تشفير الخزنة كلها؛ يستحيل المساس بـ DEK دون KEK. |
| AEAD XChaCha20-Poly1305 | أرقام nonce عشوائية بطول 192 بت تجعل إعادة استخدام nonce أمرًا غير وارد؛ يوثّق Poly1305 كل نص مشفّر، لذا تُكتشف كلمة المرور الرئيسية الخاطئة عبر فشل المصادقة — لا تُخزَّن أي تجزئة أو موثِّق لكلمة المرور في أي مكان. |
ربط AAD (lspass:v1:entry:<id>:<field>) | لا يمكن لمهاجم يملك صلاحية الكتابة على ملف قاعدة البيانات نقل النصوص المشفّرة بين الإدخالات أو الحقول. |
| nonce جديد لكل كتابة | كل حفظ يعيد الختم بـ nonce عشوائي جديد. |
| نظافة الذاكرة | تعيش المفاتيح في SecureBytes وتُمحى عبر sodium_memzero عند الإتلاف؛ تمسح الواجهة حقول كلمات المرور فور الاستخدام؛ تُمسح الحافظة تلقائيًا بعد 30 ثانية من النسخ (وفقط إذا كانت ما تزال تحمل سرّنا). |
| صلاحيات الملف | ملف الخزنة يكون chmod 0600. |
| مولّد كلمات المرور | مولّد CSPRNG من النواة مع أخذ عينات بالرفض (بدون انحياز modulo)، يضمن تغطية جميع فئات المحارف المفعّلة، ويستبعد المحارف الغامضة افتراضيًا؛ إنتروبيا ~128 بت عند الطول الافتراضي 20 محرفًا. |