Zero-Knowledge Proof of SHA256 Hash using zkSNARK
This article provides you sufficient commands to run zkSNARK algorithm with circom circuits on a Ubuntu Docker image to prove SHA256 hash.
If you are just testing for educational purposes, I recommend to use Docker for cleaner setup. However, if you wish to run the zkSNARK program on your machine, you can start from Install Prerequisites section.
Setup Ubuntu Instance on Docker
docker run -it ubuntu:jammy
apt update
apt install curl
apt install nano
Install Prerequisites
apt install build-essential
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
(proceed with standard installation). "$HOME/.cargo/env"
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 20
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
apt install git-all
git clone https://github.com/iden3/circom.git
cd circom
cargo build --release
cargo install --path circom
npm install -g snarkjs
Develop and Run the zkSNARK Program
- Create
program.circom
file by runningnano program.circom
pragma circom 2.0.0;
include "./circomlib/circuits/sha256/sha256.circom";
template program() {
signal input in[2];
signal output out[256];
component SHA = Sha256(2);
SHA.in <== in;
out <== SHA.out;
}
component main = program();
2. Get sha256
library by simply running git clone https://github.com/iden3/circomlib.git
in project directory.
Pro tip: Similarly you can use other given libraries to write any custom program for your scenario
3. Compile the .circom file using circom program.circom --r1cs --wasm --sym --c
.
4. Create input.json
file in program_js
directory.
{"in":["1","2"]}
5. Run node generate_witness.js program.wasm input.json witness.wtns
in program_js
directory.
6. Run snarkjs powersoftau new bn128 15 pot15_0000.ptau -v
in project direcotry. Note that you need at least 2¹⁵ maximum number of constraints that the ceremony can accept for this scenario. For more info see Ref 2.
7. snarkjs powersoftau contribute pot15_0000.ptau pot15_0001.ptau --name="First contribution" -v
8. snarkjs powersoftau prepare phase2 pot15_0001.ptau pot15_final.ptau -v
9. snarkjs groth16 setup program.r1cs pot15_final.ptau program_0000.zkey
10. snarkjs zkey contribute program_0000.zkey program_0001.zkey --name="1st Contributor Name" -v
11. snarkjs zkey export verificationkey program_0001.zkey verification_key.json
12. snarkjs groth16 prove program_0001.zkey program_js/witness.wtns proof.json public.json
13. snarkjs groth16 verify verification_key.json public.json proof.json
Try running command in step 13 after changing values from
input.json
orpublic.json
to see how verification results change.
Final directory structure
|-- circomlib/
| |-- ...
|-- program_cpp
| |-- ...
|-- program_js
| |-- generate_witness.js
| |-- input.json
| |-- program.wasm
| |-- witness.wtns
| `-- witness_calculator.js
|-- pot15_0000.ptau
|-- pot15_0001.ptau
|-- pot15_final.ptau
|-- program.circom
|-- program.r1cs
|-- program.sym
|-- program_0000.zkey
|-- program_0001.zkey
|-- proof.json
|-- public.json
`-- verification_key.json