A local-first password manager for Linux and Android. No cloud, no server, no telemetry. Your vault is a single encrypted file on your device; nothing ever leaves it unless you explicitly opt in to prefix-only breach monitoring.
Zero-Recovery by design: if you lose your master password AND your Shamir recovery shares, your data is gone. There is no backdoor, no vendor reset, no cloud copy. This is a feature, not a bug.
- Zero-Cloud - the only egress is opt-in breach monitoring (5-char SHA-1 prefix, or an offline corpus). No server, no relay, no telemetry.
- Zero-Trust - every input (MP, TOTP, backup code, PIN, peer, clock, file) is treated as hostile until math proves otherwise.
- Zero-Recovery-by-design - no backdoor. Inheritance is opt-in and fully self-custodied.
- No home-rolled crypto - audited bindings only (libsodium FFI).
- Sync optional - removing the entire sync module leaves a fully working offline password manager.
- Per-entry DEK hierarchy - each entry has its own CSPRNG DEK wrapped under a VRK derived from your master password. Destroying one DEK shreds exactly one entry.
- Single-file GEN4 format - one encrypted file, two slots (primary + decoy), structurally deniable. No separate decoy file exists on disk, ever.
- Duress vault - a secondary password opens an isolated, plausible-looking vault. The UI never reveals the mechanism.
- KDF-bound 2FA - TOTP is folded into the key derivation (math, not a check). Backup codes release the second-factor material through the real KDF path.
- Companion-device push approval - 2-digit number-matching challenge with 3 options, rate-limited (defeats relay/phishing).
- FIDO2 hardware-key factor - a P-256 signature is folded into the KDF (keylogger-immune; wrong key fails at GCM).
- Shamir recovery kit - split your master key into N shares; any K reconstruct it. Fully offline.
- True SSE search - searchable symmetric encryption with bucket-padded tags; no domain decryption during search.
- Honeypot canaries - realistic fake entries that trigger lock + lockdown on access.
- Atomic MP change - re-wraps all DEKs + recomputes all search tags in one temp-file-then-rename save.
- Group shred + deferral - duress shred is a group operation across paired devices, with cancellation propagation and offline deferral.
- Liveness/inheritance - signed epoch tokens + K-of-N shares + friction chain for opt-in inheritance.
- Sensitive clipboard MIME - Linux copies set
text/plain;charset=utf-8;sensitive=trueso clipboard managers (CopyQ/Diodon/Klipper) don't log password history. - Local security dashboard - duplicate/weak/old password analysis, fully local.
- Seccomp deny-list - blocks only the scraping/attach syscalls (ptrace, process_vm_*, kcmp, perf_event_open); Dart-VM-safe.
V6.5 adds features required for mass adoption while preserving the zero-cloud doctrine. The full suite is 325+ tests, all passing.
Per-entry security classification with progressive authentication requirements:
- Standard (streaming, forums): Autofill immediate, reveal with single tap, edit requires biometric.
- Sensitive (email, shopping): Autofill with 5-second delay + re-auth prompt, reveal requires biometric, edit requires biometric.
- Critical (banking, crypto, government): Manual autofill only (user must type), reveal requires master password + biometric, export blocked.
Tier assignment is user-controlled (advisory suggestions based on domain). Downgrades require explicit confirmation. Tiers are stored in the encrypted vault blob (attacker cannot silently downgrade).
Enforcement points:
- Android Autofill Service respects tier (critical entries never autofill)
- UI blocks export for critical entries
- TOTP auto-copy disabled for critical tier
Native TOTP (Time-based One-Time Password) generator compliant with RFC 6238:
- Import methods: QR code scanner (otpauth:// URI), manual entry, bulk import from Google Authenticator export format
- Algorithms: SHA1 (default), SHA256, SHA512
- Digits: 6 or 8 (configurable per entry)
- Period: 30 seconds (configurable)
- Display: Current code with circular countdown timer, next code preview, copy to clipboard with 30-second auto-clear
- Validation: ±1 window tolerance for clock drift
- Security: TOTP secrets stored in vault (encrypted with per-entry DEK), never logged or exposed in plaintext after import
Doctrine compliance: No cloud dependency. TOTP codes generated locally. Secrets stored in encrypted vault.
Peer-to-peer device synchronization via Bluetooth Low Energy (10-meter range):
- Pairing protocol: 8-character alphanumeric passphrase shared between devices
- PSK derivation: Argon2id(passphrase, salt, 64 MiB, 3 iterations) raises offline dictionary cost
- Transport: BLE for discovery + WiFi Direct for bulk transfer (Android Nearby Connections API)
- Security: Noise NNpsk0 handshake with TOFU (Trust-On-First-Use) pinning, 60-second pairing window, max 3 attempts before cooldown
- Conflict resolution: Manual (user chooses which version to keep), no auto-merge
- UI Architecture: Pure
SyncStore+SyncStatetypestate enforces State/View separation, preventing UI-layer memory leaks of Noise session keys.
Honest limitations:
- Both devices must be online simultaneously (no async sync)
- 10-meter BLE range enforced by physics (not software)
- Pairing passphrase must be kept secret (if leaked, nearby attacker could sync)
Doctrine compliance: No cloud relay. Data never leaves local network. User controls pairing.
Native Android Autofill Framework integration:
- Domain extraction: Trusted source (
AssistStructure.webDomain), not spoofable page title - Lookalike detection: Homoglyph check (0/o, 1/l/i, 5/s), edit distance ≤1, subdomain impersonation detection, RFC 1035 length guards (prevents algorithmic DoS)
- Tier enforcement: Critical tier -> null FillResponse (hard stop, user must type manually)
- Secure Transit: Dart-side
AndroidAutofillBridgeuses MethodChannel to pull domain and push credentials. No Binder transit leaks (P0-2 closed). - Security: Vault must be unlocked (biometric/master) before credentials released
- Digital Asset Links: App-domain association prevents phishing
Permissions (Android 13+):
BLUETOOTH_CONNECT,BLUETOOTH_SCAN,BLUETOOTH_ADVERTISE(BLE sync)NEARBY_WIFI_DEVICES(WiFi Direct bulk transfer)USE_BIOMETRIC(fingerprint unlock)CAMERA(TOTP QR import)
Doctrine compliance: allowBackup=false in manifest prevents Android auto-backup to Google Drive.
Native passkey support for modern authentication, keeping private keys strictly in hardware-backed Keystores:
- Android 14+ CredentialManager:
PasskeyPlugin.ktbridges the OS-level biometric prompt to the Flutter core. - Pure Core Math:
PasskeyChallengegenerates 32-byte CSPRNG entropy, strictly base64url encoded (no padding) per WebAuthn Level 2 spec. - Domain Isolation:
PasskeyManager.verifyRpIdmathematically enforces exact Relying Party ID matching, preventing cross-domain phishing (Mutation tested M124-M126). - Schema Evolution:
VaultEntrysafely extends the V4 JSON schema with an optionalpasskeyCredentialId, maintaining backward compatibility with legacy vault blobs (Mutation tested M121-M123).
Byte-identical Linux ELF binaries from source, enabling community verification of the release binary:
- Deterministic Timestamps:
SOURCE_DATE_EPOCHpins build time to the last git commit. - Path Stripping:
-ffile-prefix-mapand-fdebug-prefix-mapstrip absolute build directory paths from DWARF debug info and__FILE__macros. - Archive Normalization:
ZERO_AR_DATE=1ensures deterministicararchive timestamps.
Native global hotkey support for Wayland compositors (Ubuntu 22.04+, Fedora):
- xdg-desktop-portal: Falls back to
org.freedesktop.portal.GlobalShortcutsvia GDBus when X11XGrabKeyis unavailable. - Layout-Safe Trigger: Hotkey changed to
Ctrl+Alt+Spaceto avoid conflicts with OS-level keyboard layout switchers (e.g., GermanStrg+Shift).
Progressive disclosure wizard enforcing the Zero-Knowledge doctrine at compile time:
- Pure Core:
OnboardingStoremanages state transitions (Welcome -> Doctrine -> CreateMP -> DecoyOptIn). - Memory Safety:
SecureBufferlifecycle explicitly managed by the store; native memory wiped if user navigates back from the MP creation step (Mutation tested M127-M129). - Doctrine Enforcement: Users cannot bypass the "Zero-Recovery" warning screen.
Following the initial security audit, the following hardening was applied to the Trusted Computing Base (TCB):
sodium_memzero added before calloc.free in all FFI wrappers:
argon2id.dart: MK, password copy, salt copyaes_gcm.dart: key, plaintext, ciphertext buffershkdf.dart: PRK (native path), IKM (native path)
Dart-side zeroing via fillRange(0, length, 0):
key_hierarchy.dart: IKM (MK || TOTP)vault_crypto_v4.dart: MK, VRK, DEK after usesecond_factor.dart: candidate hash, SFMsearch_tag.dart: SearchKey
header.dart: Added sanity checks for DEK length (max 1024), ciphertext length (max 1MB), tag count (max 100), vector clock length (max 256)header.dart: AddedcheckBounds()helper to prevent buffer overflow on malformed inputtier_autofill_enforcer.dart: RFC 1035 domain length guard (253 chars) prevents O(N*M) algorithmic DoS in edit-distance calculations.- Fuzzing campaigns (
tool/fuzz_parsers.dart,tool/fuzz_enforcer.dart) run 100k+ iterations with 0 crashes and 0 timeouts.
aes_gcm.dart: Addedcrypto_aead_aes256gcm_is_available()check, fail-closed if unsupported
- Unified all parsing/decryption errors to
CorruptBlobErrororDecryptionFailedError(no information leakage via exception types) padding.dart: AllFormatExceptionreplaced withCorruptBlobError
search_tag.dart: Added stripping ofhttp://,https://,ftp://schemes- Added minimum query length (3 chars) to prevent FP flood
Install dependencies (see linux/DEPS.md):
sudo apt update && sudo apt install -y \
clang cmake ninja-build pkg-config \
libgtk-3-dev liblzma-dev libstdc++-12-dev \
libsodium-dev libseccomp-dev \
libx11-dev libxtst-dev libayatana-appindicator3-dev libglib2.0-devRun (dev):
flutter pub get
flutter run -d linuxInstall as a desktop app (builds release, installs to /opt/vault_crypto, creates a menu launcher + icon):
./install_linux.sh
# Launch from the app menu ("Vault Crypto"), or run: /opt/vault_crypto/vault_cryptoRelease build with integrity hash (Hermetic):
./build_linux.sh # builds --release + writes build_hash.txt (byte-identical)Note: P2P BLE sync is Android-only (Nearby Connections). On Linux the Sync screen shows a "not available" message; the rest of the app is fully functional. Global hotkeys work on both X11 and Wayland.
Install dependencies (see android/DEPS.md):
sudo apt install openjdk-17-jdk
# Install Android SDK, NDK, platform-tools
# Set ANDROID_HOME, JAVA_HOMEBundle libsodium (required - Android has no system libsodium). The Dart
crypto layer loads libsodium.so via dart:ffi; it must be present in
android/app/src/main/jniLibs/<abi>/. Prebuilt .so for arm64-v8a and
armeabi-v7a are committed. To rebuild them from source (uses your NDK):
./build_android_sodium.shBuild APK:
flutter pub get
flutter build apk --releaseInstall on device:
adb install build/app/outputs/flutter-apk/app-release.apkUpdate on device:
adb install -r build/app/outputs/flutter-apk/app-release.apkFirst-run setup:
- Enable Autofill Service: Settings -> System -> Languages & input -> Autofill service -> Vault Crypto
- Grant permissions: Biometric, Bluetooth, Camera (for TOTP QR import)
- Create master password (zxcvbn score ≥3 recommended)
- Setup recovery (Shamir shares or encrypted backup)
flutter test # 325+ tests (all pass)
flutter analyze # 0 errors (remaining items are pre-existing info/warnings)
dart run tool/mutation_campaign.dart # mutation kill score (100%, 137/137 applied)Test coverage:
- 325+ unit + integration tests (all passing)
- 137 mutations covering the entire Trusted Computing Base (TCB) + V6.5 + vault data + passkey + onboarding + shamir + adaptive posture
- 100% mutation kill score (all security invariants verified)
- Full security gate suites:
security.md(gates 1-20) andsecurity2.md(gates 21-32) - RFC 6238 compliance tests for TOTP (SHA1/SHA256/SHA512)
- Security tier policy tests (21 tests)
- P2P pairing protocol tests (state machine, PSK derivation)
- Lookalike domain detection tests
- Fuzzing (vault, grammar, sync protocol, TOTP import, parsers, enforcer) — 0 crashes, 0 timeouts
- Differential testing against reference implementations (HKDF, HMAC, TOTP, Argon2id)
Full registry: See
TESTING.mdfor the complete list of test suites, mutation runs (M01-M137), fuzzers, and verification tools.
See v6_delta.md for detailed roadmap:
- P0: External cryptographic audit (recruiting auditors)
- P1: Publish project + gather community feedback
- P2: Onboarding flow design (DONE - Typestate Wizard)
- P3: Recovery UX design (guided Shamir reconstruction)
- P4-P5: Android device verification (DONE)
- P6: TPM sealing (Linux hardware-backed key storage)
- P7: Noise PQ-hybrid transport (post-quantum future-proofing)
- P8: Runtime integrity attestation (advisory)
- A knowledgeable attacker can suspect deniability exists but cannot prove it.
- A coercer holding BOTH passwords defeats the scheme.
- Behavioral biometrics is an anomaly deterrent, never authentication; FP/FN are measured empirically, not fabricated.
- Mutation testing covers only what is encoded as a mutation. It does not replace external cryptographic audit.
V4VaultEntry.passwordremains a DartStringin the UI model (unavoidable Flutter limitation). The crypto core never holds it as String.- V6.5: P2P sync requires both devices online simultaneously (no async sync). BLE range ~10m is a physical limitation, not software-enforced. TOTP secrets stored in vault (single point of failure if vault compromised). Security tiers are advisory (determined user can bypass UI).
- Passkeys: Native Android CredentialManager integration requires Android 14+. Older devices fall back to password/biometric unlock.
See CONTRIBUTING.md for development discipline and how to contribute.
MIT License. See LICENSE for details.
See SECURITY.md for threat model, vulnerability reporting, and security contacts.
See SECURITY_AUDIT.md for internal audit results and hardening applied.
Current status: Internal audit complete (137/137 mutation kill). External audit pending (recruiting auditors).
This is a pre-audit release. To publish the current state to GitHub:
# 1. Verify everything passes
flutter test
flutter analyze
dart run tool/verify_mutations.dart # all 137 mutation search strings present
# 2. Commit
git add -A
git commit -m "V6.5.2: Passkeys, Hermetic Builds, Wayland Shortcuts, Typestate Onboarding, 137/137 mutations"
# 3. Tag the pre-audit release
git tag v1.0.0-pre-audit
# 4. Push
git push origin main --tagsThen create a GitHub Release from the v1.0.0-pre-audit tag with the
AUDIT_PACKAGE/ docs attached.
- Security: See
SECURITY.md - Audit Brief: See
AUDIT_BRIEF_V65.md - Testing Registry: See
TESTING.md - Audit Package: See
AUDIT_PACKAGE/