Skip to content

ayushn2/zk_ecdsa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zk_ecdsa – ECDSA Signature Verification in Noir

This project demonstrates verifying an Ethereum ECDSA signature inside a Noir circuit using the ecrecover crate.
We generate a wallet, sign a message with our private key, split the public key into X and Y coordinates, feed them to the circuit, and prove the verification in zero-knowledge.


1. Hash the Message

We start by hashing our message (hello) using cast keccak from Foundry:

cast keccak "hello"
# Output:
# 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8

2. Generate Wallet

cast wallet new
# Address:     0xcd7Cf0418480B063A86fCD93E792F0A908b7AaD6
# Private key: 0xPRIV_KEY

3. Get the Public Key

cast wallet pubkey --private-key 

4. Sign the hashed message

cast wallet sign --no-hash --private-key 0xPRIV_KEY  0xMESSAGE_HASH

--no-hash because we do not want to hash the message again as this will lead to hash mismatch

5. Generate inputs for Noir Circuit

chmod +x generate_inputs.sh
./generate_inputs.sh
# Wrote Prover.toml

6. Run Noir Circuit

nargo execute
# [zk_ecdsa] Circuit witness successfully solved
# [zk_ecdsa] Witness saved to target/zk_ecdsa.gz

7. Prove and Verify with Barretenberg

bb prove -b ./target/zk_ecdsa.json -w ./target/zk_ecdsa.gz -o ./target
# Proof saved to "./target/proof"

bb write_vk -b ./target/zk_ecdsa.json -o ./target
# VK saved to "./target/vk"

bb verify -k ./target/vk -p ./target/proof
# Proof verified successfully

How It Works

This project uses Noir’s ecrecover crate to verify an Ethereum ECDSA signature inside a zero-knowledge proof.

1. Message Preparation

  • A plaintext message (hello) is hashed using Keccak256.
  • The resulting 32-byte hash is the value that will be signed.

2. Key Generation

  • A new Ethereum private key is generated with Foundry's cast wallet new.
  • From this private key, the public key is derived and split into X and Y coordinates (each 32 bytes) representing a point on the secp256k1 elliptic curve.
  • The corresponding Ethereum address is computed from the public key.

3. Signing

  • The hashed message is signed with the private key using ECDSA via cast wallet sign.
  • This produces the signature (r, s, v) which together form 65 bytes.
    In this circuit, only (r, s) are passed, since v is not needed for ecrecover inside the proof.

4. Noir Circuit

  • The Noir circuit imports ecrecover and takes as public inputs:
    • pub_key_x (X coordinate of public key)
    • pub_key_y (Y coordinate of public key)
    • signature (64-byte concatenation of r and s)
    • hashed_message (Keccak256 of the message)
    • expected_address (Ethereum address derived from public key)
  • Inside the circuit, ecrecover is used to recover the Ethereum address from (pub_key_x, pub_key_y, signature, hashed_message).
  • An assertion checks that the recovered address equals expected_address.

5. Proof Generation & Verification

  • nargo execute runs the circuit and generates a witness file.
  • bb prove uses the compiled circuit and witness to generate a zero-knowledge proof.
  • bb write_vk creates the verification key.
  • bb verify verifies the proof, confirming that:
    • The given (X, Y) public key indeed corresponds to the provided Ethereum address.
    • The signature is valid for the given hashed message.
    • All this is proven without revealing the private key.

About

ECDSA signature verification in Noir

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published