/zkrangeproof

Zero-knowledge Range Proof

Primary LanguageGo

Zero-Knowledge Range Proof with uPort demo

An uPort demo application based on ING's zero-knowledge range proof precompiled contract for the go-ethereum client. The uPort dapps are based on uPort's demo dapp.

Important note:

The original version of the library used here implemented the whitepaper “An Efficient Range Proof Scheme” by Kun Peng and Feng Bao. As discovered by Madars Virza, Research Scientist at MIT Media Lab, this protocol contains a potential security vulnerability.

“The publicly computable value y/t is roughly the same magnitude (in expectation) as w^2 * (m-a+1)(b-m+1). However, w^2 has fixed bit length (again, in expectation) and thus for a fixed range, this value leaks the magnitude of the committed value.”

Therefore, the proofs generated by the protocol used earlier are not zero-knowledge. The current implementation of the library that we use here is based on the paper "Efficient Proofs that a Committed Number Lies in an Interval" by Fabrice Boudot, of which the zero-knowledge property is currently being evaluated.

This demo

A fundamental principle of a Self Sovereign Identity (SSI) scheme is to disclose only the personal information that is necessary for that purpose. Consider, for instance, the purpose of buying alcoholic beverages, where one has to disclose that he or she is above 18 years of age. The known way to do this is by showing your national ID card to the vendor. One could also digitalize the ID card and have it signed by the government, for instance as an uPort attestation. But that will still leak way more information than necessary (place of birth, social security no., etc.). An already better solution would be to issue an "over 18" attestation, but what if another shop wants to check "over 17"?

The zero-knowledge range proof (ZKRP) precompiled contract, as developed by ING, can be used to efficiently verify that a number lies within a certain range, without revealing that number. We apply this to the age limit example in a model that involves three different uPort dapps:

  • an Issuer that is an authority regarding your age, i.e. the government, that generates a cryptographic 'commitment' on your year of birth and signs it. You receive the signed commitment as an uPort attestation, as well as a 'private variables' uPort attestation which you should only share with trusted parties.
  • an Intermediary that reads the commitment and private variables, and generates a range proof for a specific year of birth range (i.e. 1900 - 1999) for the "over 18" example. This functionality could be embedded in a future version of the uPort app.
  • a Relying party, such as the vendor of the liquor store, that reads the range proof and checks it against a certain year of birth range, by calling ING's precompiled ZKRP contract. This age range should match with the age range for which the range proof was generated.

This way, you only reveal the information that is absolutely necessary. As a result, you can be truly self-sovereign. This demo demonstrates an age limit example, but other use cases could be for instance:

  • Validate that someone is in Europe without disclosing the exact location.
  • Validate that a payment-amount is positive without disclosing the amount (as done by Monero).

The three demo dapps are supported by two utility services:

  • a Java application that runs an HTTP server. The uPort dapps call it to generate the commitment and range proofs.
  • ING's modified Geth client, which runs the precompiled ZKRP smart contract.

Usage

The usage of this uPort ZKRP demo consists of three parts:

  1. Running a modified ethereum Geth client that contains ING's precompiled smart contract;
  2. Running the provided Java application;
  3. Installing and starting the three uPort dapps.

Moreover, in some browsers you must disable the Same Origin Policy. Aforementioned steps will be described in further detail below.

Setting up the modified Geth client

Make sure that you have make, golang-go, and gradle installed.

Clone this repository, navigate to the go-ethereum folder and run:

$ make geth

You can now use the modified Geth client with the --rpc parameter. From the zkrangeproof folder, use

$ ./go-ethereum/build/bin/geth --rpc

Running the provided Java application

Make sure that you have an IDE (plugin) that supports Gradle, or another dependency manager. Start your favourite IDE and open the source code form the zkrangeproof root folder (as a Gradle project). Build and run the project such that a Java HTTP server is started.

Installing and starting the three uPort dapps

Hang on, we are almost there! The last step is to install and run the three uPort applications.

Make sure that you have npm installed. For each folder /uport/dapp1, /uport/dapp2, and /uport/dapp3, run the commands:

$ npm install

and

$ npm start

The demo can now be started by connecting to the first dapp, which lives at localhost:3001. After finishing all its steps, continue to the Intermediary dapp at port 3002, and finally to the Relying party dapp at port 3003.

Thanks a lot for trying out this demo and feel free to contribute!