Skip to content Skip to content

◈ Shadow Vault

Deniable Encryption · Argon2id + ChaCha20-Poly1305

Hide a real message and a plausible decoy at passphrase-derived offsets inside one fixed-size container, then decrypt either slot by supplying its passphrase.

Role privacy is not provided. A format-aware reader can classify a disclosed passphrase as real or decoy by trying the public role/counter domains and authenticating a slot. They do not need the other passphrase. This identifies the configured role, not the importance of its message, and does not recover the unopened plaintext. Hiding labels or equalizing derivation work in this UI does not prevent that offline test. Guessing an independently chosen passphrase opens its own slot, not both messages. Recovering the other password is a separate attack; correlated or reused passwords add risks.

REAL MESSAGE

 

Bits of entropy estimate the number of guesses to break this passphrase: each bit doubles the work, so 80 bits is a million times harder than 60. Deniability holds only while both passphrases are too costly to guess.

0 bytes

DECOY MESSAGE

 

The decoy must be just as hard to guess — if an attacker can brute-force this passphrase, they can also test whether it hides the whole vault.

0 bytes

CONTAINER SIZE

The Deniability Problem

Coercion can reveal a passphrase and its encrypted message. A two-slot container can be used to present a plausible decoy, but that scenario does not itself establish what a format-aware adversary can learn.

Shadow Vault puts two independently encrypted messages at different offsets. It does not provide role privacy: a format-aware adversary can classify the disclosed role by trying the public real/decoy derivation domains and counters and checking which candidate authenticates. Revealing the decoy passphrase therefore discloses its configured decoy label. This does not recover the unopened plaintext or prove the meaning or importance of either message. A stronger deniability guarantee would require a reviewed format/design change; concealing UI labels cannot supply it.

The Two-Passphrase Model

Each passphrase and public role/counter domain derive a key, nonce and offset through Argon2id. Authentication identifies the configured real or decoy role for that passphrase. Opening one role does not provide the other independently chosen passphrase or its plaintext. Equal derivation work and generic failure messages do not conceal the successful role from an offline reader.

Why Argon2id Is Load-Bearing

Argon2id is not incidental — it is the security foundation. Without memory-hard key derivation, the deniability model collapses: an attacker who can brute-force both passphrases simultaneously recovers both offsets and both messages.

Argon2id makes the first dictionary construction expensive, but this demo has no per-container salt: a table built for one parameter set can be reused across every Shadow Vault container at those settings. High-entropy, independently generated passphrases—not a claimed per-target work factor—are the defense.

Container Format

The container is one of four recognized fixed sizes and contains two encrypted slots at derived offsets in CSPRNG padding. It has no plaintext header or magic bytes. Each encrypted slot's plaintext includes a four-byte length field, hidden inside the authenticated ciphertext. Its bytes should look random, while the recognized size and known format still fingerprint it as a Shadow Vault container.

Passphrase → Argon2id(64B) → key[0..31] + nonce[32..43] + offset[44..63] → ChaCha20-Poly1305 AEAD

What This Cannot Protect Against

  • Implementation bugs in this demonstration code
  • Keyloggers or compromised devices capturing passphrases
  • Coercion with violence (rubber-hose cryptanalysis)
  • Metadata outside the container (filenames, timestamps, access logs)
  • Browser memory not being securely wiped (passphrases enter as JS strings)
  • Weak passphrases expose their own slots; correlated passwords can ease separate guessing, and reuse across containers adds key/nonce reuse risks

Honest Limitations

Shadow Vault is a demonstration of deniable encryption concepts, not production-grade deniable storage. Browser-based cryptography is inherently weaker than native tools. Strong, unique, independently generated passphrases are required to protect both messages. Guessing one opens its own slot; this does not imply automatic recovery of the other independently protected message. For real-world deniable encryption, use VeraCrypt with hidden volumes.

Related Projects