Developer Builds Password Manager with Plausible Deniability Using Argon2id and XChaCha20-Poly1305

A Java backend developer rewrote a personal password manager originally built with Electron and React, migrating it to Tauri and Rust while redesigning its storage to support plausible deniability. The new implementation derives keys with Argon2id using a single per-install salt and encrypts files with XChaCha20-Poly1305, storing only random 32-character hex filenames without any headers or magic bytes. Multiple decoy vaults of identical size are created automatically for every user, and all files in the folder receive synchronized timestamps to eliminate metadata-based identification of the active vault. History and sync data are stored as additional encrypted files of the same format, making it impossible to distinguish real from decoy vaults from the filesystem alone. The approach mirrors VeraCrypt hidden volumes but operates on ordinary files and folders, with the explicit goal of providing deniability when a user is compelled to reveal a password.

HabrTranslated from Russian

Read at source

A developer who previously created a simple password manager using Electron, React and a symmetric cipher from npm has now rebuilt the application in Tauri and Rust, adding a robust implementation of plausible deniability.

The original design deliberately avoided any “wrong password” screen: any password either opened an existing vault or created a new empty one. This behavior was intended to provide plausible deniability similar to VeraCrypt hidden volumes, but on ordinary files stored in a folder.

Why the first version failed

The initial implementation stored each vault under a filename that was a bcrypt hash of the master password. This created an oracle: an attacker could simply hash a wordlist and match filenames. Additional folders named history/ and sync/ further revealed which vaults were actively used.

Current design

The updated format uses Argon2id (64 MiB memory, t=3, p=1) with one installation-wide salt to derive the key. Each file begins with a 24-byte nonce followed by XChaCha20-Poly1305 ciphertext. No version numbers, headers or magic bytes are present; all metadata resides inside the authenticated ciphertext.

File names are 32 random hexadecimal characters. Vaults are padded to the next power-of-two size bucket (4 KiB, 8 KiB, 16 KiB, …) so that small and large vaults appear identical on disk.

  • At first launch the application automatically creates two decoy files filled with random bytes.
  • After every write operation, creation, modification and access timestamps of all files in the folder are synchronized.
  • History and synchronization records are stored as additional encrypted files containing a “kind” field inside the ciphertext.

The developer notes that the scheme protects against a single snapshot of the disk but remains vulnerable to multiple snapshots taken over time, NTFS USN journals, Windows shadow copies or Time Machine backups.

Meridian digestThe week's most consequential security stories, distilled into one briefing.See the digest

More in Privacy & Surveillance

Maximizing iPhone Privacy: Essential Settings to Enable, Disable, and Verify Immediately
Top 10 Secure DNS Servers for Privacy, Threat Blocking and Ad Filtering in 2026
WebRTC IP Leaks Explained: Why Disabling the Protocol Harms Anonymity in Anti-Detect Browsers