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.

Binod Karunanayake
2 min readApr 30, 2024

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

  1. docker run -it ubuntu:jammy
  2. apt update
  3. apt install curl
  4. apt install nano

Install Prerequisites

  1. apt install build-essential
  2. curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh (proceed with standard installation)
  3. . "$HOME/.cargo/env"
  4. curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
  5. nvm install 20
  6. export NVM_DIR="$HOME/.nvm"
  7. [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  8. apt install git-all
  9. git clone https://github.com/iden3/circom.git
  10. cd circom
  11. cargo build --release
  12. cargo install --path circom
  13. npm install -g snarkjs

Develop and Run the zkSNARK Program

  1. Create program.circom file by running nano 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 or public.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

References

  1. https://docs.circom.io/getting-started
  2. snarkjs/README.md at master · iden3/snarkjs (github.com)
  3. https://medium.com/casperblockchain/circom-sha256-15c77bb1b7aa

--

--

Binod Karunanayake

PhD Candidate @RMIT University | Former Software Engineer @WSO2 | BSc Engineering (Hons) University of Moratuwa