Set Up a Proving Service for zkLogin

Step by step instructions for using Docker images and a Groth16 proving key provided by Sui

Set Up a Proving Service for zkLogin

zkLogin, a new Sui primitive, allows people to create a Sui address and sign transactions with just their existing web credentials from providers like Google, Facebook, and Twitch. To ensure privacy, apps integrating zkLogin must create ZK proofs so that credentials remain hidden from apps and transaction history remains hidden from web services. As generating a ZK proof can be resource-intensive and potentially slow on the client side, it's advised to use a backend service endpoint dedicated to ZK proof generation. Running that service along with a salt service will allow users to access your app via zkLogin. For more information on salt services, read about salt strategies in Sui’s docs.

One option for running the proving service in your backend is to use the Docker images provided in Sui docs along with the Common Reference String (CRS) established in the ceremony held this past September.

Set up steps for proving service

  1. Download the Docker images tagged as prover and prover-fe.
  2. Download the Groth16 proving key zkey file that will be used later as an argument to run the prover.
wget -O - | bash

3. Verify you downloaded the correct zkey file by checking the Blake2b hash equals


by running b2sum zkLogin.zkey.

4. Run prover at PORT1 with the downloaded zkey on a Linux-based machine (amd64).

docker run \
  -e ZKEY=/app/binaries/zkLogin.zkey \
  -e WITNESS_BINARIES=/app/binaries \
  -v <path_to_zkLogin.zkey>:/app/binaries/zkLogin.zkey \
  -p PORT1:8080 \

5. Run prover-fe at PORT2:

docker run \
    -e PROVER_URI='http://localhost:PORT1/input' \
    -e NODE_ENV=production \
    -e DEBUG=zkLogin:info,jwks \
    -p PORT2:8080 \

6. Expose the prover-fe service appropriately and keep the prover service internal.

7. Call the proving service with one of the following endpoints:

  • /ping to test if the service is up
    • Running curl http://localhost:PORT2/ping should return pong.
  • /v1 to create a ZK proof
    • Input the JWT_TOKEN, ephemeral public key, maxEpoch, jwtRandomness, salt and key claim name to get the proof.
curl -X POST 'http://localhost:PORT2/v1' -H 'Content-Type: application/json' \
-d '{"jwt":"$JWT_TOKEN", \
"extendedEphemeralPublicKey":"ucbuFjDvPnERRKZI2wa7sihPcnTPvuU//O5QPMGkkgA=", \
"maxEpoch":"10", \
"jwtRandomness":"S76Qi8c/SZlmmotnFMr13Q==", \
"salt":"urgFnwIxJ++Ooswtf0Nn1w==", \
"keyClaimName":"sub" \

Response:`{"proofPoints":{"a":["17267520948013237176538401967633949796808964318007586959472021003187557716854","14650660244262428784196747165683760208919070184766586754097510948934669736103","1"],"b":[["21139310988334827550539224708307701217878230950292201561482099688321320348443","10547097602625638823059992458926868829066244356588080322181801706465994418281"],["12744153306027049365027606189549081708414309055722206371798414155740784907883","17883388059920040098415197241200663975335711492591606641576557652282627716838"],  ["1","0"]],"c":["14769767061575837119226231519343805418804298487906870764117230269550212315249","19108054814174425469923382354535700312637807408963428646825944966509611405530","1"]},  "issBase64Details":{"value":"wiaXNzIjoiaHR0cHM6Ly9pZC50d2l0Y2gudHYvb2F1dGgyIiw", "indexMod4": 2 },"headerBase64":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ"}`

If you would prefer to compile the prover from scratch for performance reasons, take a look at Sui’s fork of rapidsnark. You will need to compile and launch the prover in server mode.