π₯οΈ
Best Viewed on Desktop
The technical documentation and app previews are optimized for desktop viewing.
β Back to HomeποΈ
Shadow Passphrase
The canary phrase β a deliberate decoy trigger that formalizes peace of mind as a cryptographic parameter (Paper Β§5.4).
π¨ The $5 Wrench Attack (Paper Β§1.1)
Over 189+ documented physical attacks on cryptocurrency holders with estimated losses exceeding $84M. The attack chain: KYC leak β identity correlation β target selection β physical coercion β theft. No encryption algorithm protects assets when an adversary applies physical force (XKCD #538). YoY growth: +292% (2018-2020), +89% (2021-2023).
Why Existing Anti-Coercion Fails (Paper Β§1.2)
Proposed mechanisms like decoy wallets and panic passwords share a fundamental vulnerability: their logic is visible on-chain. A sophisticated attacker can read the contract source, identify duress branches, demand both passwords, and verify which branch executed.
Listing 1 β Detectable anti-coercion logic (VULNERABLE)Solidity
// This code is PUBLICLY VISIBLE on Etherscan
function withdraw(bytes32 _password) external {
if (keccak256(_password) == duressHash) {
// Decoy branch β ATTACKER CAN SEE THIS EXISTS
transferDecoy(msg.sender);
} else if (keccak256(_password) == realHash) {
// Real branch β ATTACKER CAN DEMAND BOTH
transferReal(msg.sender);
}
}β
ZK-Sentinel's Paradigm Shift (Paper Β§1.3)
Move the decision logic inside the zero-knowledge circuit. In a ZK circuit, private inputs and internal computations are mathematically impossible to observe β the verifier learns nothing beyond the validity of the statement. The contract sees only: valid proof + nullifier + recipient. No branches, no duress flags, no detectable logic.
Formal Construction (Paper Β§5)
Definitions 5-7 β Dual Nullifier + Shadow PassphraseMath
ββ Definition 5: Dual-Nullifier Generation ββββββββββββββββ
Given secret s β F_p and Poseidon hash H:
N_real = H(s, 0)
N_decoy = H(s, 1)
Lemma 1 (Nullifier Independence): N_real and N_decoy are
computationally independent. Given one, computing the other
requires knowledge of s. (Poseidon PRF under Sponge assumption)
ββ Commitment Structure βββββββββββββββββββββββββββββββββββ
C = H(s, N_real, N_decoy, H_frase)
β inserted into on-chain Merkle tree
ββ Definition 6: Arithmetic Selector ββββββββββββββββββββββ
a = ia_inference Γ frase_correcta
N_output = a Β· H(N_real) + (1 β a) Β· H(N_decoy)
Lemma 2: Expression expands to N_output = H(N_decoy) + a Β· (H(N_real) β H(N_decoy))
β exactly 2 R1CS constraints regardless of a β {0,1}
β same gas, same proof size, same verification time
ββ Definition 7: Shadow Passphrase (Canary Phrase) ββββββββ
A secondary phrase that deliberately triggers decoy mode
without generating any observable indicator.
frase_correcta = frase_real Γ (1 β frase_shadow)
Where:
frase_real = (frase_hash == frase_esperada)
frase_shadow = (frase_hash == frase_shadow_hash)
"Canary" β sings (activates protection) before danger materializes.Extended Truth Table (Paper Table 5)
| Real Phrase | Shadow Phrase | IA Inference | a | Result | On-Chain |
|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | REAL: Normal operation | Valid TX β |
| 1 | 0 | 0 | 0 | DECOY: AI detects coercion | Valid TX β |
| 0 | 1 | X | 0 | DECOY: Shadow Passphrase (canary) | Valid TX β |
| 0 | 0 | X | 0 | DECOY: Incorrect phrase | Valid TX β |
Defense in depth: real funds released ONLY when both conditions satisfied. Any single indicator of duress activates decoy mode.
π’ Normal Withdrawal (a = 1)
Phrase: Real passphrase β
IA: Normal biometrics β
Nullifier: H(N_real, secret)
Result: Full deposit withdrawn
π Coerced Withdrawal (a = 0)
Phrase: Shadow/wrong OR stress
IA: Stress detected OR phrase wrong
Nullifier: H(N_decoy, secret)
Result: Decoy pool withdrawal
Circuit Implementation (Real Code)
withdraw_dual_v9_relayer.circom β dual nullifier logicCircom
// COMMITMENT: Poseidonβ(secret, Ξ·_real, Ξ·_decoy, H_frase)
component commitmentHasher = Poseidon(4);
commitmentHasher.inputs[0] <== secret;
commitmentHasher.inputs[1] <== nullifier_real;
commitmentHasher.inputs[2] <== nullifier_decoy;
commitmentHasher.inputs[3] <== frase_hash_stored;
// PASSPHRASE VERIFICATION
component fraseHasher = Poseidon(1);
fraseHasher.inputs[0] <== frase_input;
component fraseComparator = IsEqual();
fraseComparator.in[0] <== fraseHasher.out;
fraseComparator.in[1] <== frase_hash_stored;
signal frase_correcta;
frase_correcta <== fraseComparator.out; // 1 si coincide, 0 si no
// DUAL LOGIC β acceso_real = ia_inference AND frase_correcta
// ia_inference: 1 = normal, 0 = estrΓ©s (from ZKML model)
signal acceso_real;
acceso_real <== ia_inference * frase_correcta;
ia_inference * (1 - ia_inference) === 0; // binary constraint
// NULLIFIER HASHES β both computed, one selected
component nullifierRealHasher = Poseidon(2);
nullifierRealHasher.inputs[0] <== nullifier_real;
nullifierRealHasher.inputs[1] <== secret;
signal nullifier_hash_real;
nullifier_hash_real <== nullifierRealHasher.out;
component nullifierDecoyHasher = Poseidon(2);
nullifierDecoyHasher.inputs[0] <== nullifier_decoy;
nullifierDecoyHasher.inputs[1] <== secret;
signal nullifier_hash_decoy;
nullifier_hash_decoy <== nullifierDecoyHasher.out;
// ARITHMETIC SELECTOR β no branching, proof reveals nothing
signal selectedNullifier;
selectedNullifier <== acceso_real * (nullifier_hash_real - nullifier_hash_decoy)
+ nullifier_hash_decoy;
// On-chain: both nullifiers are valid β indistinguishable
nullifierHash === selectedNullifier;Formal Proof of Indistinguishability (Paper Β§9.1)
Theorem 2 β Dual-Logic Indistinguishability (sequence of games)Proof
Theorem 2: Given only public outputs (root, nullifierHash, recipient, relayer, fee, Ο), no PPT adversary can determine the value of private selector a with probability significantly greater than 1/2. Proof via sequence of games: Game 0: Real protocol execution. Adversary observes (root, N_out, recipient, relayer, fee, Ο) Game 1: Replace Poseidon hash outputs with truly random values. |Pr[A wins G1] β Pr[A wins G0]| β€ negl(Ξ») (by PRF security of Poseidon under Sponge assumption) Game 2: Replace Groth16 proof Ο with simulated proof Ο*. |Pr[A wins G2] β Pr[A wins G1]| β€ negl(Ξ») (by zero-knowledge property of Groth16) In Game 2, adversary's view: β’ root: independent of a β’ N_out: random value (by Game 1) β’ recipient, relayer, fee: chosen by user, independent of a β’ Ο*: simulated, no witness information All components independent of a βΉ Pr[A guesses a] = 1/2 β‘ Corollary 1 (Coercion Resistance): Under coercion, decoy nullifier produces valid funds. Attacker CANNOT determine: (1) Whether user has additional real funds (2) Whether coercion resistance was activated (3) What triggered the decoy path
βΉοΈ Peace of Mind as a Cryptographic Parameter (Definition 8)
ZK-Sentinel formalizes cryptographic peace of mind Ξ¨(P): the verifiable guarantee that (1) there exists an escape action A_escape the user can execute under coercion, (2) A_escape is computationally indistinguishable from normal action A_real, and (3) the user can verify (1) and (2) before depositing funds. The Shadow Passphrase satisfies all three: A_escape = entering the canary phrase; indistinguishability guaranteed by arithmetic selector (same circuit, same gas, same proof structure); verifiability via Circom source inspection. Protocol's indistinguishability follows from Poseidon's PRF security under the Sponge assumption (Theorem 2, proven via sequence of games).