Creating a vault
The user picks a password. Argon2id derives a 32-byte key with the parameters above. A new random 32-byte master key is generated and encrypted under the Argon2id-derived key — that ciphertext lives at vault_root/.<random>/keys/master.key.
ML-KEM-768 generates a recovery keypair. The public key is stored; the encrypted ML-KEM ciphertext that wraps the master key is stored; the user is shown the recovery private key once on a printable page.
vault.json is written next to the keys directory. It contains KDF params, a random root-directory ID, and an HMAC-SHA256 integrity tag (verified on every unlock — detects wrong passwords and tampered configs). No secrets are stored in plaintext.
- .<16-hex-chars>/
- 8 random bytes, hex-encoded
- vault.json
- plaintext — KDF params, root id, HMAC tag
- keys/
- master.key
- AES-256-GCM(master_key, Argon2id_key)
- recovery.pub
- 1184-byte ML-KEM-768 public key
- recovery.key
- ML-KEM-768 encapsulation of master_key
- hybrid.priv
- encrypted ephemeral PQ private key