What You’ll Learn
- BN254 curve pairing operations
- Working with G1 and G2 groups
- Batch pairing verification
- Cryptographic building blocks for signature schemes
Overview
The BN254 (also known as BN128 or alt_bn128) curve is widely used in blockchain systems, particularly Ethereum. This example demonstrates core pairing functionality that underlies:- zkSNARK verification (Groth16, PLONK)
- BLS signatures
- Signature aggregation
- Verifiable random functions (VRFs)
This is a toy example for educational purposes. Do not use directly in production cryptographic systems.
Mathematical Background
Pairing Operation
A pairing is a bilinear map:- Bilinearity:
e(aP, bQ) = e(P, Q)^(ab) - Non-degeneracy:
e(g1, g2) ≠ 1
What This Example Proves
Given base pointsg1 ∈ G1 and g2 ∈ G2 and random scalars a and b, prove:
How It Works
use risc0_zkvm::guest::env;
use substrate_bn::{Fr, G1, G2, Gt, pairing_batch};
fn main() {
let inp: bn254_core::Inputs = env::read();
// Decompress points
let g1 = G1::from_compressed(&inp.g1_compressed)
.expect("Point on G1 expected");
let g2 = G2::from_compressed(&inp.g2_compressed)
.expect("Point on G2 expected");
// Parse scalar factors
let a_factor = Fr::from_slice(&inp.a)
.expect("Scalar factor expected");
let b_factor = Fr::from_slice(&inp.b)
.expect("Scalar factor expected");
// Compute batch pairing:
// e(a·g1, b·g2) · e(g1, -ab·g2)
let mut pairs = Vec::new();
pairs.push((g1 * a_factor, g2 * b_factor));
pairs.push((g1, g2 * (-a_factor * b_factor)));
let result = pairing_batch(&pairs);
// Check if result is identity
env::commit(&(result == Gt::one()));
}
use bn254_methods::{BN254_VERIFY_ELF, BN254_VERIFY_ID};
use risc0_zkvm::{ExecutorEnv, default_prover};
fn main() {
// g1 and g2 are generators from EIP-197
let g1_compressed = hex::decode(
"020000000000000000000000000000000000000000000000000000000000000001"
).expect("valid hex");
let g2_compressed = hex::decode(
"0A04D4BF3239F77CEE7B47C7245E9281B3E9C1182D6381A87BBF81F9F2A6254B\
731DF569CDA95E060BEE91BA69B3F2D103658A7AEA6B10E5BDC761E5715E7EE4BB"
).expect("valid hex");
// Random scalars chosen for demonstration
let a = hex::decode(
"9c0d02eaaf8e7e7ad09595ef6e3b896f8915124ba5bef9287f0997557580caeb"
).expect("valid hex");
let b = hex::decode(
"db6764642f7bb1f415d93fcd5aace586161ec2e4305f0d6fb57dbabf1d141a5b"
).expect("valid hex");
let input = bn254_core::Inputs {
g1_compressed,
g2_compressed,
a,
b,
};
let env = ExecutorEnv::builder()
.write(&input)
.unwrap()
.build()
.unwrap();
let receipt = default_prover()
.prove(env, BN254_VERIFY_ELF)
.unwrap()
.receipt;
receipt.verify(BN254_VERIFY_ID).unwrap();
let is_one: bool = receipt.journal.decode()
.expect("Journal should contain a single bool");
println!("Pairing batch should give one; did it? {}", is_one);
}
Running the Example
What Gets Proven?
The receipt proves:- Correct Pairing: Batch pairing was computed correctly
- Identity Result: The pairing result equals the identity element
- Bilinearity: The cryptographic relationship holds
BN254 Curve Details
Groups
- G1: Points on
E(Fp)whereE: y² = x³ + 3 - G2: Points on
E'(Fp²)whereE': y² = x³ + 3/(9+u) - GT: Elements in
Fp¹²
Parameters
- Field size: 254 bits
- Embedding degree: 12
- Security level: ~100 bits (estimated)
BN254 security has been downgraded from 128 bits due to recent advances. Consider BLS12-381 for new applications.
EIP-197 Compatibility
This example uses generators from EIP-197, making it compatible with Ethereum’s precompiled contracts:Use Cases
zkSNARK Verification
Verify Groth16 proofs using pairing checks:BLS Signatures
Verify aggregate signatures:H(m): Hash-to-curve of messageσ: Signature in G1pk: Public key in G2
Signature Aggregation
Combine multiple signatures into one:Verifiable Encryption
Prove ciphertext validity:Substrate BN Library
This example uses thesubstrate_bn crate:
Point Compression
Points are compressed for efficient transmission:- G1: 32 bytes
- G2: 64 bytes
Performance
| Operation | Cycles (approx) |
|---|---|
| G1 scalar mul | ~500K |
| G2 scalar mul | ~1M |
| Single pairing | ~10M |
| Batch pairing (2) | ~15M |
Cryptographic Applications
This building block enables:- Zero-Knowledge Proofs: Groth16, PLONK verification
- Aggregate Signatures: BLS signature schemes
- Threshold Cryptography: Distributed key generation
- Identity-Based Encryption: Boneh-Franklin IBE
- Verifiable Delay Functions: Chia VDF
Security Considerations
This is educational code. Production cryptographic systems require:
- Careful parameter selection
- Constant-time implementations
- Thorough security audits
- Up-to-date security analysis
Known Issues
- BN254 security degraded to ~100 bits
- Vulnerable to number field sieve attacks
- Consider BLS12-381 for new systems
Best Practices
- Validate all points are on the curve
- Check points are in the correct subgroup
- Use constant-time operations for secrets
- Never reuse randomness
Comparison to Other Curves
| Curve | Security | G1 Size | G2 Size | Speed | Ethereum |
|---|---|---|---|---|---|
| BN254 | ~100 bit | 32 B | 64 B | Fast | Native |
| BLS12-381 | ~128 bit | 48 B | 96 B | Medium | Planned |
| BLS12-377 | ~128 bit | 48 B | 96 B | Medium | No |
Next Steps
- Explore BLS12-381 example
- Learn about Groth16 verification
- Study pairing-based cryptography
- Build BLS signature schemes