Skip to content

rushby/circom-rsa-4096-sha512-verify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Circom RSA-4096 SHA-512 Zero-Knowledge Proof Circuit

Zero Knowledge Proof circuit for RSA-4096 signature verification using SHA-512 hashing, built with Circom. This generic circuit verifies any RSA-4096 signature with SHA-512 hashing and PKCS1v15 padding using Groth16 zk-SNARKs. Includes Random.org integration as an example use case.

Features

  • 4096-bit RSA signature verification with PKCS1v15 padding
  • SHA-512 hashing (512-bit output)
  • Generic circuit - works with any RSA-4096 + SHA-512 signature
  • Random.org API integration (example use case)
  • ✅ Full zero-knowledge proof generation and verification workflow
  • ✅ Supports exponent 65537

Circuit Statistics

  • Constraints: 1,071,212 (over 1 million)
  • Wires: 1,060,273
  • Public Inputs: 200
  • Key Size: 4096-bit RSA

Quick Start

Installation

npm install

Setup

  1. Install Circom (required for circuit compilation):

    npm install -g circom
  2. Set up Random.org API key (optional, for testing with real data):

    # Create .env file
    echo "RANDOM_ORG_API_KEY=your-api-key-here" > .env
  3. Download Powers of Tau (required for proof generation, ~2.3GB):

    npm run download-ptau
  4. Generate proving keys (one-time setup, takes ~10-30 minutes):

    npm run setup-proof

Running Tests

Circuit Verification Tests

Test that the circuit correctly verifies RSA signatures:

# Run all tests
npm test

# Run general RSA test (generates its own keys - proves generic functionality)
npm run test:general

# Run Random.org integration test (optional - requires API key)
npm run test:random

Recommended: Start with npm run test:general - this test generates its own RSA-4096 keys and signatures, proving the circuit works with any RSA-4096 + SHA-512 signature.

Zero-Knowledge Proof Generation

Generate and verify actual zk-SNARK proofs:

npm run test:proof

This test will:

  1. Compile the circuit (if not already compiled)
  2. Check for Powers of Tau file
  3. Generate or reuse proving/verification keys
  4. Generate a witness for a test RSA signature
  5. Generate a zero-knowledge proof (~10-30 minutes)
  6. Verify the proof (instant)

Project Structure

circom-rsa-4096-sha512-verify/
├── circuits/
│   ├── sha512/          # SHA512 circuit implementation
│   ├── bigint/          # Big integer arithmetic (for RSA operations)
│   ├── pow_mod.circom   # Modular exponentiation
│   └── rsa_verify.circom # RSA verification with SHA512
├── src/
│   ├── randomOrgClient.ts      # Random.org API client
│   ├── signatureParser.ts      # Parse signatures for circuit input
│   └── generateRsaSignature.ts # RSA key generation utilities
├── test/
│   ├── test_general_rsa_4096.ts    # General RSA signature tests
│   ├── test_rsa_pkcs1v15_sha512.ts # Random.org integration tests
│   └── test_proof_generation.ts    # Full ZK proof workflow
├── scripts/
│   ├── download-powers-of-tau.sh   # Download trusted setup file
│   ├── generate-zkey.js            # Generate proving key
│   └── setup-proof-generation.sh   # Full proof setup
└── package.json

Usage

Circuit Template

component main = RsaVerifyPkcs1v15(64, 64, 17, 8);
// Parameters: (word_size, num_words, exp_bits, hash_len)
// 64-bit words, 64 words = 4096 bits, 17-bit exponent (65537), 8 words for SHA512

Inputs

  • exp[64]: RSA public exponent (65537, represented as 64 words)
  • sign[64]: RSA signature (4096 bits)
  • modulus[64]: RSA public key modulus (4096 bits)
  • hashed[8]: SHA512 hash of the message (512 bits = 8 words)

Example: Verify Any RSA-4096 + SHA-512 Signature

The circuit works with any RSA-4096 signature using SHA-512. Test it with your own signatures:

import { generateRsaKeyPair, signRsaPkcs1v15Sha512, prepareRsaSignatureForCircuit } from './src/generateRsaSignature';

// Generate your own RSA-4096 key pair
const keyPair = generateRsaKeyPair();

// Sign your data
const message = "Your message here";
const signature = signRsaPkcs1v15Sha512(message, keyPair.privateKey);

// Prepare circuit input
const circuitInput = prepareRsaSignatureForCircuit(
    signature,
    message,
    keyPair.publicKey
);

// Use with circuit
const input = {
    exp: circuitInput.exp.map(x => x.toString()),
    sign: circuitInput.sign.map(x => x.toString()),
    modulus: circuitInput.modulus.map(x => x.toString()),
    hashed: circuitInput.hashed.map(x => x.toString())
};

// Run: npm run test:general

Example: Verify Random.org Signature (Optional)

import { RandomOrgClient } from './src/randomOrgClient';
import { loadPublicKeyFromCert } from './src/loadPublicKeyFromCert';
import { parseSignatureForCircuit } from './src/signatureParser';

// Get signed random data
const client = new RandomOrgClient(apiKey);
const signedData = await client.generateSignedIntegers(10, 1, 100, true);

// Load public key
const publicKeyPem = loadPublicKeyFromCert('server.crt');

// Prepare circuit input
const dataString = RandomOrgClient.getSignedDataString(signedData);
const circuitInput = parseSignatureForCircuit(
    signedData.signature,
    dataString,
    publicKeyPem
);

// Use with circuit
const input = {
    exp: circuitInput.exp.map(x => x.toString()),
    sign: circuitInput.sign.map(x => x.toString()),
    modulus: circuitInput.modulus.map(x => x.toString()),
    hashed: circuitInput.hashed.map(x => x.toString())
};

Proof Generation Workflow

1. Setup (One-Time)

Download Powers of Tau:

npm run download-ptau
# Downloads ~2.3GB file (power 21, supports up to 2M constraints)

Generate Proving Key:

npm run setup-proof
# Or manually:
node scripts/generate-zkey.js

This generates:

  • rsa_verify_pkcs1v15.zkey - Proving key (~730MB)
  • vkey.json - Verification key (small)

2. Generate Proofs (Repeated)

npm run test:proof

Or programmatically:

import snarkjs from 'snarkjs';

// Generate witness
const { calculateWitness } = require('./build/proof_test/rsa_verify_pkcs1v15_js/witness_calculator');
const witness = await calculateWitness(input);

// Generate proof
const { proof, publicSignals } = await snarkjs.groth16.prove(
    'build/proof_test/rsa_verify_pkcs1v15.zkey',
    witness
);

// Verify proof
const vkey = JSON.parse(fs.readFileSync('build/proof_test/vkey.json'));
const verified = await snarkjs.groth16.verify(vkey, publicSignals, proof);
console.log('Proof verified:', verified);

Performance Expectations

Timing Breakdown

Step Time Frequency
Download ptau 10-30 min Once (lifetime)
Compile circuit 2-5 min Once per circuit design
Generate proving key 10-30 min Once per circuit
Generate witness 30-60 sec Every proof
Generate proof 10-30 min Every proof
Verify proof Milliseconds Every verification

Note: Actual times may vary significantly based on hardware. Modern machines with snarkjs 0.7.5 have been observed to complete zkey generation in ~12 minutes and proof generation in 10-30 minutes.

Why It's Fast (Despite 1M+ Constraints)

  • Efficient cryptographic operations in snarkjs 0.7.5
  • Modern hardware with multiple CPU cores
  • Optimized circuit structure for 4096-bit operations

Random.org Integration (Example Use Case)

This project includes Random.org integration as a real-world example. The circuit itself is generic and works with any RSA-4096 + SHA-512 signature.

Random.org signs data in the following format:

{completionTime}\n{data[0]}\n{data[1]}\n...\n{data[n-1]}

The signature is a base64-encoded PKCS1v15 RSA signature using SHA-512. Random.org uses a 4096-bit RSA key.

Supported API Methods

  • generateSignedIntegers(n, min, max, replacement) - Generate signed random integers
  • generateSignedStrings(n, length, characters) - Generate signed random strings

Public Key

The Random.org public key is available in server.crt (included in this repository). You can also fetch it from:

Technical Details

PKCS1v15 Padding

The circuit verifies PKCS1v15 padding with SHA512 ASN.1 prefix:

0x00 0x01 [padding FF bytes] 0x00 [ASN.1 prefix] [SHA512 hash]

ASN.1 prefix for SHA512:

0x30 0x51 0x30 0x0d 0x06 0x09 0x60 0x86 0x48 0x01 0x65 0x03 0x04 0x02 0x03 0x05 0x00 0x04 0x40

Circuit Parameters

  • w = 64: Word size in bits
  • nb = 64: Number of words for RSA modulus (64 × 64 = 4096 bits)
  • e_bits = 17: Number of bits in exponent (65537 = 2^16 + 1)
  • hashLen = 8: Hash length in words (512 bits = 8 × 64 bits)

Troubleshooting

"Circuit too large for ptau file"

  • Ensure you're using power 21 or higher ptau file
  • Check that the downloaded file is ~2.3GB

"Out of memory"

  • Increase Node.js memory: NODE_OPTIONS=--max_old_space_size=32000
  • Close other applications
  • Use a machine with more RAM (16GB+ recommended)

"Circom not found"

  • Install circom: npm install -g circom
  • Verify: circom --version

Type Warnings (T3001)

The circuit generates harmless typing warnings about mismatched array dimensions. These are safe to ignore - Circom pads arrays with zeros automatically.

Credits

This project was built using code and concepts from the following open-source projects:

  1. circom-rsa-verify - RSA signature verification circuit implementation

    • Used as reference for RSA verification logic and PKCS1v15 padding verification
    • Adapted for 4096-bit keys and SHA-512 hashing
  2. sha512 - SHA-512 hashing circuit implementation

    • Used as reference for SHA-512 hash function implementation in Circom
    • Integrated into the RSA verification workflow

We extend our gratitude to the developers and contributors of these projects for their valuable work.

References

License

GPL-3.0

About

Circom RSA-4096 SHA-512 Zero-Knowledge Proof Circuit

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published