A zero-knowledge proof lets you prove you know a secret without revealing the secret itself. The verifier learns nothing except that the statement is true. This is one of the deepest ideas in cryptography: conviction without information.
The Ali Baba cave
Imagine a circular cave with a magic door at the back. The prover enters and takes path A or B (the verifier does not see which). The verifier shouts "come out path A" or "come out path B." If the prover knows the secret to open the door, they can always comply. If they do not, they have a 50% chance of being on the wrong side. After 20 rounds, a fake prover's odds of passing are less than one in a million.
# Ali Baba cave simulationimport random
random.seed(42)
def simulate_cave(knows_secret, rounds=20):
for _ inrange(rounds):
prover_path = random.randint(0, 1) # 0=A, 1=B
challenge = random.randint(0, 1)
can_comply = knows_secret or (prover_path == challenge)
ifnot can_comply:
returnFalsereturnTrue# Honest prover always passesprint(f"Honest prover: {simulate_cave(True)}")
# Fake prover: almost always caught
caught = sum(1for _ inrange(1000) ifnot simulate_cave(False))
print(f"Fake prover: {caught}/1000 caught")
Interactive vs non-interactive
The cave protocol is interactive: the verifier must be online, issuing fresh challenges. A non-interactive proof replaces the verifier with a hash function (the Fiat-Shamir heuristic). The prover hashes the commitment to generate their own challenge. Anyone can verify the proof later without interaction.
Scheme
; Fiat-Shamir heuristic: replace the verifier with a hash.; Interactive: verifier sends challenge c; Non-interactive: c = hash(commitment); Schnorr identification protocol (simplified); Prover knows secret x, public key y = g^x mod p; 1. Prover picks random r, sends commitment t = g^r mod p; 2. Challenge c = hash(t) (non-interactive); 3. Prover sends s = r + c*x; 4. Verifier checks g^s = t * y^c
(display "Interactive ZKP:") (newline)
(display " Prover -> commitment -> Verifier") (newline)
(display " Verifier -> challenge -> Prover") (newline)
(display " Prover -> response -> Verifier checks") (newline)
(newline)
(display "Non-interactive (Fiat-Shamir):") (newline)
(display " challenge = hash(commitment)") (newline)
(display " Proof = (commitment, response)") (newline)
(display " Anyone can verify, anytime")
ZK-SNARKs
ZK-SNARK stands for Zero-Knowledge Succinct Non-interactive Argument of Knowledge. "Succinct" means the proof is tiny (a few hundred bytes) regardless of the computation's size. "Non-interactive" means no back-and-forth. ZK-SNARKs let you prove you ran an arbitrary computation correctly, without revealing the inputs.
Scheme
; ZK-SNARKs: what each word means
(display "Zero-Knowledge:") (newline)
(display " Verifier learns nothing beyond validity") (newline)
(newline)
(display "Succinct:") (newline)
(display " Proof size is O(1), not O(computation)") (newline)
(display " A proof for 1M operations is the same") (newline)
(display " size as a proof for 10 operations") (newline)
(newline)
(display "Non-interactive:") (newline)
(display " Single message from prover to verifier") (newline)
(newline)
(display "Argument of Knowledge:") (newline)
(display " The prover must actually know a witness") (newline)
(display " (not just that one exists)") (newline)
(newline)
(display "Applications:") (newline)
(display " - Private transactions (Zcash)") (newline)
(display " - Credential verification without") (newline)
(display " revealing the credential") (newline)
(display " - Verifiable computation (prove you") (newline)
(display " ran the code correctly)")