The vault and the duress slot.
A built-in credentials manager that lives inside the encrypted profile, plus an optional second phrase that opens a different — convincingly populated — decoy vault. For the moment someone insists you unlock.
What it stores
Hostname, username, password, optional notes — per entry. No attachments, no biometric backup, no cloud sync. The vault blob is sealed with a key derived from the profile phrase (same Argon2id + ChaCha20-Poly1305 pipeline used for the rest of the profile).
The duress slot
Optional. When you enable it, you set a second phrase. The vault now stores two blobs of identical, fixed size:
- The real blob — opens with your primary phrase.
- The duress blob — opens with the second phrase, contains whatever decoy credentials you choose to populate it with.
Both blobs are padded to a fixed 256 KiB ciphertext length regardless of contents, so an observer with file-system access can't tell which is "fuller" or which one is the decoy by size.
Populating the duress vault
The decoy is only convincing if it looks lived-in. When you set up the duress slot, treat it like a real workflow:
- Add 15–40 entries, not 2. Empty is a tell.
- Mix hosts: a few big services (mail, social), some niche sites, a couple of work-style logins.
- Use credentials that are plausibly yours but no longer active — old accounts you've abandoned, throwaway mail aliases. Anything currently sensitive must stay in the real vault only.
- Let it age. Pop into the duress vault occasionally and update a password, add a note, change a title. The "modified" timestamps on the blob then look natural.
Switching back
Each unlock is one-shot: enter phrase, see the matching vault, lock when done. There's no UI hint that two vaults exist — the duress experience looks like the real experience, because that's the whole point.
To edit the real vault later: lock the profile, unlock again with the primary phrase.
Edge cases we handled
- Phrase collision. Setup refuses to accept a duress phrase that decrypts the real blob (cross-blob trial-decrypt at configuration time).
- Strings in memory. Username / password /
notes use
Zeroizingwrappers so the cleartext is overwritten on drop, lock and wipe. - Size delta. Vault plaintext is whitespace- padded before encryption so the real and duress blob are indistinguishable in size.
- Locked-profile delete. Wiping a profile still asks for the phrase first, so the cleartext can be zeroed on disk before the blob is removed.
Limitations
- Not coercion-proof. If your adversary knows about the duress feature and knows you're using Husk, they may demand the "real" phrase by name. Plausible deniability is one tool in a kit, not a guarantee.
- Forensic memory. RAM dumps taken while the real vault is unlocked can recover cleartext until lock or shutdown. The wipe is best-effort on a running OS.
- Clipboard. When you copy a password, anything reading the clipboard between copy and paste sees the plaintext. Husk clears the clipboard automatically after a short window, but the window is non-zero.