Interactive demo
Before using this, read what a zk-SNARK is if you haven’t — this demo is not a zk-SNARK. It’s Schnorr identification made non-interactive with the Fiat–Shamir transform: a real, working proof of knowledge, and the historical building block the rest of the field grew out of. See how it works for the exact equations this runs.
- Publish — pick a secret
x(or keep the default) and publishy = x·G. Onlyyever leaves this page;xstays in your browser. - Prove — generate a proof
(R, s). No message from a verifier is involved — the “challenge” is a hash the prover computes themselves. - Verify — check the proof against the published
y. This should pass. - Then try the two failure cases below the proof: verifying a
tampered proof, and generating a proof from a wrong secret and
checking it against the real
y. Both should be — and are — rejected.
Ready — secp256k1, the same curve wired up on pedersen.foundation.
Public key y = x·G
This is the only thing that ever gets published. x itself is never sent anywhere — check the network tab if you don't believe it.
No message from a verifier is involved in this step — that's the "non-interactive" part.
Proof: R = k·G, then s = k + c·x mod q
Every value above is computed live in your browser using
@noble/curves on secp256k1 —
see Code for the same scheme in Python, JavaScript, and Rust.
Range proof: proving a value is in range, without revealing it
This second demo is a step closer to a real “argument of knowledge for a relation” than the Schnorr demo above — there, the statement was just “I know a discrete logarithm.” Here, the statement is “the value inside this commitment is in ” — for example, “this balance is non-negative” — without revealing the value itself.
How it works: the value is committed with a Pedersen commitment (), split into 8 individual bits, each with its own commitment. For each bit, an OR-proof (Cramer–Damgård–Schoenmakers, 1994) proves that bit’s commitment opens to 0 or 1, without revealing which — the real branch runs an honest proof, and the other branch is simulated, with a shared challenge split between the two so a verifier can’t tell them apart. The bit commitments then recombine into the original commitment for free, using the fact that Pedersen commitments are additively homomorphic.
Still not succinct. Unlike the Schnorr demo’s 3-of-4 properties, this one is honestly closer but still incomplete: it’s Zero-knowledge and an Argument of Knowledge for a real relation (not just a discrete log), but the proof size here grows linearly with the number of bits — one full OR-proof per bit, all sent to the verifier. It is not succinct.
The real succinct version of this exact problem is Bulletproofs (Bünz, Bootle, Boneh, Poelstra, Wuille, Maxwell, “Bulletproofs: Short Proofs for Confidential Transactions and More,” IEEE S&P 2018, pp. 315–334), which proves the identical range statement in logarithmic size using a recursive inner-product argument — no trusted setup either. Monero adopted Bulletproofs for its Confidential Transactions in its October 2018 network upgrade, cutting typical transaction size by roughly 80%. The demo below is a conceptual predecessor to Bulletproofs, not Bulletproofs itself — it demonstrates the same statement being proven, not the same (succinct) technique for proving it.
Ready — 8-bit range proof (proves a value is in [0, 256)) over Pedersen commitments on secp256k1.
Commitment C = v·G + r·H
This is not succinct — the proof is 8 separate OR-proofs, one per bit, and grows linearly with the bit-width. Compare to Groth16's fixed 3 group elements on the homepage.
Try the two failure cases below the proof, same as the Schnorr demo above: a tampered proof, and an attempt to sneak a bit value of 2 (outside 0 or 1) into one of the bit commitments — both are correctly rejected.