freecoding.school100% FREE · NO SIGNUP
Proof PeaksISSUE #14 of 38

interactive vs non-interactive · fiat-shamir

ZeekaVSThe Collision
Zeeka saysInteractive proofs need back-and-forth challenges; the Fiat-Shamir transform replaces the verifier with a hash, making any such protocol non-interactive — and turning it into a signature.

A sigma protocol runs in three moves: the prover sends a commitment, the verifier sends a random challenge, the prover sends a response. The Fiat-Shamir transform removes the verifier entirely by deriving the challenge as a hash of the public transcript: e = H(commitment, statement). Now the proof is one self-contained message anyone can check — and this is precisely how Schnorr signatures are constructed.

The demo proves knowledge of a discrete log — a secret x with y = g^x — without revealing x, using a non-interactive Schnorr proof. The transcript (R, s) plus the public challenge verifies the equation g^s = R·y^e, yet exposes nothing about x. The one rule: the hash must cover every public value, or the proof becomes forgeable.

Power-ups you unlock

The Collision attacks — common mistakes

Boss battleProve knowledge of x where y = g^x using a non-interactive Schnorr proof, and confirm the transcript never reveals x.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// Schnorr ZK proof of knowledge of x s.t. y = g^x; Fiat-Shamir → non-interactive.
const p=23, q=11, g=2;
const pw=(a,e,m)=>{ let r=1; a%=m; while(e>0){ if(e&1) r=(r*a)%m; a=(a*a)%m; e>>=1; } return r; };
const Hpub=(R,y)=> (R*31 + y*17) % q;              // challenge from PUBLIC values (no verifier)
const x=7, y=pw(g,x,p);                            // secret x; statement y=g^x
const k=5, R=pw(g,k,p);                            // prover commitment
const e=Hpub(R,y);                                 // non-interactive challenge
const s=(k+e*x)%q;                                 // response
const ok = pw(g,s,p) === (R*pw(y,e,p))%p;
document.getElementById('o').textContent = [
  'statement: y = g^x = ' + y + '   (x kept secret)',
  'proof (R, s) = (' + R + ', ' + s + ')   challenge e = H(R,y) = ' + e,
  'verify  g^s == R·y^e : ' + ok,
  'the proof shows R and s but NOT x → zero-knowledge',
  'Fiat-Shamir: e came from a hash → no interaction needed'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Zk Proofs · Completeness · Soundness · Zero-KnowledgeArithmetic Circuits · R1cs · Constraints ›