Rust · RFC 5114 Schnorr group · no crypto crates · no curves
Veilproof proves you know a secret, or that a hidden number satisfies a property, without ever revealing it. SHA-256, the Fiat-Shamir transform, and every Sigma protocol are written from scratch. No black box. Below is the real math, running live in your browser, animated so you can watch each move land.
Pick a secret x. The page computes y = gx mod p and proves knowledge of x with a Schnorr proof, without ever putting x itself in the proof. Watch the commitment, challenge, and response cross the channel between prover and verifier.
prover and verifier, connected only by what is sent below
Pick a secret value from 0 to 255. The page commits to it with Pedersen commitments, decomposes it into 8 bits, proves every bit is honestly 0 or 1 with an OR-proof, and ties the bits back to the commitment. The value itself never leaves its sealed commitment.
each cell is one OR-proof: honestly 0 or 1, never which
C ?= ∏i Ci2^i
Chaum-Pedersen. From a single secret x the page publishes y1 = g^x and y2 = h^x on two different bases, then proves the same x sits behind both, without revealing x. This is the check behind honest re-encryption and verifiable shuffles.
one secret, two bases, one shared response
A ring of public keys is generated and the page proves knowledge of the secret behind exactly one of them, without revealing which. The proof has the same shape at every position, so it cannot leak the index, not even in this visualization.
every key looks the same to the verifier, including yours
running g^q mod p == 1 self-check and a sample proof verification…
Every step below is code you can read, no dependency does the cryptography for you.
All arithmetic happens mod a 2048-bit RFC 5114 prime, inside the 256-bit prime-order subgroup generated by g, self-checked on load.
The compression function, message schedule, and padding are written from the FIPS 180-4 spec, no crates, matching a known-answer vector.
The verifier's random challenge becomes a SHA-256 hash of the full transcript and statement, reduced mod q, so no interaction is needed.
Knowledge of a discrete log x is proven with a commitment t, a challenge c, and a response z, checked by g^z == t · y^c.
A bit commitment is proven to open to 0 or 1 by genuinely proving the true branch and simulating the false one.
n bit proofs, tied back to one commitment through the Pedersen homomorphism, prove a value lies in [0, 2^n) bit by bit.
veilproof prove-dlog, verify-dlog, and demo, plus a plain Rust library with typed errors, never a panic.
The demo above is the same p, q, g, h, the same hand-written SHA-256, and the same Fiat-Shamir logic, ported to JavaScript with native BigInt.
cargo test checks completeness, soundness against wrong witnesses and tampered bytes, determinism, and that the witness never appears in a serialized proof.
# prove knowledge of a secret veilproof prove-dlog --secret 424242 # verify it veilproof verify-dlog --statement <hex> --proof <hex> # run the full range-proof demo veilproof demo