Built for paranoid
engineers.
Every layer of ConfPass was designed under the assumption that the server is compromised. Your vault stays encrypted and private regardless. Here's exactly how.
Zero-Knowledge Authentication
SRP-6a protocol — your password never travels over the wire.
Secure Remote Password version 6a. The server stores only a mathematical verifier derived from your password. Authentication is proven via a challenge-response exchange — your actual password never leaves your device, even in hashed form.
Two-tier Argon2id configuration: PIN hashing uses 64MB / 3 iterations / 1 thread. Vault key derivation uses 128MB / 4 iterations / 1 thread — GPU and ASIC resistant. Automatic Bcrypt → Argon2id migration on first login. Vault key path hard-enforced: PBKDF2 fallback entirely removed (hard throw).
A 128-bit device-bound Secret Key supplements your master password. Even if your master password is compromised, an attacker cannot authenticate without your device-specific Secret Key. Stored encrypted with OS-level DPAPI.
Multi-signal anomaly detection scores each authentication attempt: new device fingerprint, IP geolocation anomaly, impossible travel velocity, concurrent session detection. High-risk score triggers automatic step-up MFA regardless of previous authentication state.
Client-Side Vault Encryption
AES-256-GCM with a unique nonce per entry. Server receives only ciphertext.
Every vault entry (title, username, password, URL, notes, custom fields) is encrypted with AES-256-GCM before upload. A cryptographically random 96-bit nonce is generated per entry. The authentication tag provides integrity verification — tampered ciphertext is rejected on decryption.
The vault key is never stored contiguously in memory. Implemented as XOR-split halves in Rust: two random byte arrays A and B where A ⊕ B = vaultKey. Both halves are re-randomized every 5 minutes while keeping the logical key intact. The key is wiped from memory on lock.
Import and export operations maintain the ZK pipeline end-to-end. On import: entries are encrypted client-side before upload. On export: encrypted entries are decrypted locally using the vault key before writing to file. The server never sees plaintext during either operation.
The desktop app and browser extension receive separate JWT tokens (Bridge Tokens) with distinct scopes. A compromised extension cannot use the app's token and vice versa. Tokens are generated via serde_json structured serialization — no format string injection possible.
Multi-Factor Authentication
8 authentication factors. Every one properly implemented.
Full FIDO2 / WebAuthn support for hardware security keys (YubiKey, Titan, etc.). Phishing-resistant by design — attestation is origin-bound. Works through the browser extension for passkey autofill.
Create and manage platform authenticator passkeys (Windows Hello, Touch ID). Stored securely in the vault with full credential data. Autofilled via browser extension passkey injection bootstrap.
6-digit TOTP with 30-second window (RFC 6238 compliant) and HOTP (RFC 4226). Compatible with all standard authenticator apps. Clock skew tolerance: ±1 window.
Windows Hello fingerprint / face recognition for vault unlock. Biometric failures are counted in the same exponential lockout as PIN failures — defeating biometric bypass attacks. 20 combined failures → automatic vault wipe.
Lockout & Session Security
Client-side exponential lockout. Server-side session guard.
Client-side lockout with exponential backoff enforced in Tauri (Rust) — cannot be bypassed from the UI layer. Schedule: 3 failures → 1 min, 5 → 2 min, 7 → 5 min, 10 → 10 min, 15 → 30 min, 20 → automatic vault wipe. Biometric failures share the same counter.
Two-tier session protection: (1) Proactive token refresh every 12 minutes — refreshes before expiry to maintain seamless session without re-login. (2) Session validity check every 2 minutes — detects server-side revocation and forces re-authentication immediately.
Seven independent rate limiting layers: per-IP global, per-endpoint, per-account login, per-account action, per-session, geographic burst, and Sentinel anomaly throttle. Layers operate independently — bypassing one does not bypass others.
Hide sensitive vault entries with a PIN-protected toggle. When Travel Mode is active, hidden entries are absent from all UI rendering paths — they do not appear in search results, category views, or the vault list. Restore requires PIN re-entry.
Threat Monitoring
Passive breach monitoring. Vault health scoring. Anomaly detection.
Password breach checking via the Have I Been Pwned k-anonymity API. Only the first 5 characters of the SHA-1 password hash are transmitted — the full hash and plaintext password never leave the device. Over 962 million breach records checked passively.
Comprehensive vault health analysis with four detection categories: (1) Weak passwords — entropy below threshold, (2) Reused passwords — cross-entry comparison, (3) Breached passwords — live HIBP k-anonymity check (auto-runs on open), (4) Insecure URLs — HTTP, localhost, IP-only detection. Aggregate health score calculated.
Real-time authentication risk scoring: device fingerprint delta (new device = +35 points), IP geolocation anomaly (+25), impossible travel (speed > 900km/h between sessions = +40), concurrent session anomaly (+20), velocity burst (+15). Score ≥ 60 triggers step-up MFA.
Designate trusted contacts who can request vault access. A configurable waiting period (hours to days) begins when a request is submitted. The owner retains full denial rights throughout the period. Useful for estate planning and recovery scenarios.
What happens when you unlock your vault?
Five cryptographic steps — all on your device, none on the server.
Master Password + Secret Key Input
You enter your master password. Combined with your 128-bit device-bound Secret Key to form the authentication input.
input = masterPassword + ":" + secretKeySRP-6a Authentication Handshake
Your device computes an ephemeral SRP-6a session. The server verifies the handshake without ever receiving your password or its hash.
verifier = H(salt || H(email:password:secretKey))Argon2id Vault Key Derivation
Separately, Argon2id derives your vault encryption key using 128MB of memory and 4 iterations — GPU/ASIC-resistant. Runs entirely in Rust via Tauri.
vaultKey = Argon2id(password, salt, m=131072, t=4, p=1)AES-256-GCM Decryption
Each vault entry is decrypted locally with AES-256-GCM using the derived vault key. A unique 96-bit nonce per entry and AEAD tag ensure integrity.
entry = AES-256-GCM-Decrypt(ciphertext, vaultKey, nonce)Memory-Safe Key Split
The vault key is XOR-split into two random halves in Rust memory. Both halves re-randomize every 5 minutes. Securely wiped on lock or timeout.
store = [part_a, part_b] where part_a ⊕ part_b = vaultKey