Skip to main content

Groth16 / BN254 Proof Verifier

Paste a Groth16 proof, its verifying key and the public signals (snarkjs JSON format) and run the BN254 pairing check entirely in your browser. Verifies proofs from circom + snarkjs pipelines, zk-rollup wrappers (Brevis Pico, Citrea/RISC Zero) and any other system that emits Groth16 over BN254. Nothing is uploaded.

Verifying key (verification_key.json)

Public signals (public.json)

Proof (proof.json)

What the verifier checks

Groth16 proofs are three elliptic-curve points (pi_a, pi_b, pi_c) over the BN254 curve (snarkjs calls it bn128). Verification evaluates one bilinear pairing equation: e(pi_a, pi_b) = e(alpha, beta) · e(sum(publicSignals[i] · IC[i]) + pi_c, delta). If both sides match, the prover knew a witness satisfying the circuit for exactly those public values - without revealing the witness.

The sample above is a real, tamper-tested fixture: a multiplier2 circuit (c = a × b) with public signal 33, generated with circom 2 + snarkjs. Change 33 to any other number and the pairing equation breaks - try it.

FAQ

What can I verify with this tool?

Any Groth16 proof over BN254 in snarkjs JSON format: circom/snarkjs circuits, Semaphore-style protocols, zk-rollup Groth16 wrappers (Brevis Pico's EVM path, Citrea's RISC Zero wrapping), and Tornado-style private withdrawal proofs.

Does it verify PLONK, Halo2 or STARK proofs?

No - those use different proof systems. Groth16 only. The file's protocol field is checked and a clear error is shown for mismatches.

Is verifying a proof here safe for private data?

Yes. Verification is read-only math on public values (a proof, a verifying key, public signals - none of which are secret), and it runs 100 percent in your browser. Open the network tab and verify zero requests.

What is the difference between BN254 and bn128?

Nothing - they are two names for the same pairing-friendly curve (also called alt_bn128). Ethereum precompiles call it bn254; snarkjs files say bn128.