The sample code is presented at

curl --location '' -k
--header 'Accept: application/json'
--header 'Connection: Close'
--header 'Content-Type: application/json'
--data '{ "query_type": "github_user_stats_zk_halo2", "query_param": { "encryptedBearer": "YOUR_ENCRYPTED_BEARER", "dataSlot": 0 } }' 

Note that the bearer must be encrypted by public key of Sibyl first



Get the RSA public key used to encrypt the GitHub token on client-side. This API doesn't have any parameters. The key pair is generated and stored in Sibyl's secure enclave. The private key will never leak out of Sibyl. This means that only Sibyl can decrypt the encrypted Github token.


Get the claim which will be used for generating zk range proof on client-side. The claim contains the encrypted statistics of the user's GitHub account with an EdDSA signature.


  • encryptedBearer: string. encrypted GitHub token using RSA public key obtained from github_get_rsa_public_key. This encryptedBearer will be generated on client-side.

  • rsaPubKey: string, RSA public key used for encrypting the result in PEM format. Please note that this public key is different from the public key returned from github_get_rsa_public_key. This public key must be generated by the user on client-side. The corresponding private key must be kept by the user and cannot be disclosed to anyone, including Sibyl.

  • enableFields: a set of key-value pairs with fields you want to query. The key is the field name and the value is a boolean indicating whether you want to query this field. Supported fields: followers, totalStars, totalCommits, totalPrs, contributedTo, and totalIssues.

It must be combined with the front-end code (circomjs) to complete the generation of a zk range proof.


Query user statistics and generate zk range proof for a specific field in the secure enclave (we are currently developing the client-side proof generation support for Halo2 as well).


  • encryptedBearer: same as above

  • dataSlot: int, data slot indicating which field you want to use to generate the zk range proof, 0 ~ 5 represent followers, totalStars, totalCommits, totalPrs, contributedTo, and totalIssues, respectively

Result (a string of escaped JSON):

  • innerAttestation: attestation to prove that the generation of the zk range proof is within a secure enclave

  • userIdHash: hash of the user's GiHhub id

  • zkProof: a number array of zk range proofs

The High-level Design for the zk GitHub attestor

  1. Basic Setup

There are two key pairs involved in the entire process. One is generated in Sibyl's secure enclave while the other is generated in user frontend (on client-side). Both private keys are only stored and known by the generator (Sibyl and the user, respectively). The token is encrypted on client-side and decrypted in the secure enclave with Sibyl's key pair. The decrypted token is only used for querying the user GitHub stats. The stats are then desensitized in the enclave through either a zk range proof (Halo2) or a claim (Circom). Any verifier can verify that the data is within a specific range without knowing the raw value. For example, the user has 125followers on GitHub. The corresponding zk range proof can then prove that the user follower count is between 100 and 200 without disclosing the exact value.

  1. Generate the zero-knowledge range proof on client-side

We support two types of zk range proof generation -- Circom (client-side) and Halo2 (server-side for now). The following flow describes the client-side proof generation. In this scenario, Sibyl itself (the enclave) will only generate a claim for the user GitHub data. The claim contains the encrypted raw statistics from the user's GitHub account as well as an EdDSA signature. The EdDSA signature is signed by Sibyl using its own key pair. The raw stats of the following fields can be queried and included: followers, totalStars, totalCommits, totalPrs, contributedTo, and totalIssues. Sibyl fetches these stats and then encrypts them with a user-provisioned public key. The encrypted data and the signature will then be sent to the user. On client-side, the encrypted data will be decrypted first, and then a zk range proof is generated with the raw stats and the signature as witnesses.

  1. Check that the user hasn't tampered with the data

Users may tamper with their data on client-side to get better stats. To prevent this from happening, we not only compute the data range but also verify the enclave-provisioned signature in the zero-knowledge proof to ensure that the data has integrity with respect to its original source. Because the signature is generated by Sibyl with its own private key, users cannot forge fake signatures with tampered data.

  1. Store the zkp and the attestation on-chain

After desensitization (the zkp), users are able to prove that their private data is within a given range while ensuring that the raw data is not known. Anyone who wants to verify this can check the published zk range proof. We can store the zkp on-chain to make public verification easier. Meanwhile, to prove that the entire process was indeed executed in a secure enclave, we also need to publish the enclave attestation.

Last updated