Emmy
Library for zero-knowledge proof based applications (like anonymous credentials)
Install / Use
/learn @xlab-si/EmmyREADME
emmy - Library for zero-knowledge proofs
<p align="center"> <img src="emmy_logo.png" width="160" /> </p>Emmy is a library for building protocols/applications based on zero-knowledge proofs, for example anonymous credentials. Zero-knowledge proofs are client-server protocols (in crypto terms also prover-verifier, where the prover takes on the role of the client, and the verifier takes on the role of the server) where the client proves a knowledge of a secret without actually revealing the secret.
Emmy also implements a communication layer supporting the execution of these protocols. Communication between clients and the server is based on Protobuffers and gRPC. Emmy server is capable of serving (verifying) thousands of clients (provers) concurrently. Currently, the communication is implemented for the two anonymous credential schemes (see Currently offered cryptographic schemes).
In addition, emmy is built with mobile clients in mind, as it comes with compatibility package providing client wrappers and types that can be used for generating language bindings for Android or iOS mobile platforms.
To get some more information about the theory behind zero knowledge proofs or developing various parts of emmy library, please refer to additional documentation in the docs folder.
What does emmy stand for?
Emmy library is named after a German mathematician Emmy Noether, recognised as one of the most important 20th century mathematicians. Emmy Noether's groundbreaking work in the field of abstract algebra earned her a nickname the mother of modern algebra. We named our library after her, since modern cryptography generally relies heavily on abstract algebraic structures and concepts.
<!-- toc -->- Currently offered cryptographic primitives
- Currently offered cryptographic schemes
- Installation
- emmy CLI tool
- Further documentation
emmy - anonymous credentials showcase
Let's say you would like to travel to some country which requires proof of vaccination for certain diseases. You go to the clinic named South Loop Clinic, you get vaccinated and receive a proof that you are vaccinated. In fact, South Loop Clinic issues an anonymous credential which contains a proof that you have been vaccinated for certain diseases.
The credential would contain something like:
Name: Andrew
Surname: McCain
Age: 45
Gender: M
Vaccinated for yellow fever: true
Note that the credential does not contain attributes as plaintext - the credential is received from the issuer by a zero-knowledge proof. When credential needs to be shown, another zero-knowledge proof is executed. These protocols are unlinkable - issuer and verifier cannot determine whether it is going on about the same credential (unless you reveal some unique attributes like address). In fact, even when user connects two times using the same credential, the verifier cannot know that the same credential has been used (that the same user is connecting).
Let's assume there is a smart phone app which offers a UI to the emmy protocols.
To obtain a credential, user first need to create a master secret key. An app runs:
masterSecret := pubKey.GenerateUserMasterSecret()
Here, pubKey is the public key of a clinic (clinic instantiates an Org from crypto/cl/org.go and
uses it for issuing a credential).
The communication between user and clinic go for example over NFC - between user's phone and some clinic terminal.
User obtains a credential structure from a clinic (see client/cl_test.go):
rc, err := client.GetCredentialStructure()
Credential structure for Org is defined in config/defaults.yml.
User then fills the credential using an app and starts a protocol to obtain a credential:
name, _ := rc.GetAttr("Name")
name.UpdateValue("Andrew")
surname, _ := rc.GetAttr("Surname")
surnname.UpdateValue("McCain")
age, _ := rc.GetAttr("Age")
age.UpdateValue(45)
gender, _ := rc.GetAttr("Gender")
gender.UpdateValue("M")
vaccinated, _ := rc.GetAttr("Vaccinated")
vaccinated.UpdateValue("true") // vaccinated for yellow fever
cm, err := cl.NewCredManager(params, pubKey, masterSecret, rc)
cred, err := client.IssueCredential(cm, "testRegKey5")
The clinic verifies the validity of attributes and issues a credential. The verification in this case is manual - an authorized person needs to verify the attributes and trigger the issuance of a credential. User now possesses a credential on his phone.
When user arrives to a foreign country and a proof of vaccination is needed, he opens an app which runs:
acceptableCreds, err := client.GetAcceptableCreds()
The server returns a list of organizations whose credentials it accepts. Additionally, the attributes that need to be revealed are specified:
revealedAttrs := acceptableCreds["South Loop Clinic"]
In our case this might be:
revealedAttrs = []string{"Vaccinated}
Now, the user can prove he has been vaccinated:
_, err := client.ProveCredential(cm, cred, revealedAttrs)
Verifier learns nothing about the user except that he was vaccinated for a certain disease.
Currently offered cryptographic primitives
The library supports building complex cryptographic schemes. To enable this various layers are needed:
- mathematical groups in which the operations take place
- utilities for generating safe primes, group generators, for decomposing integers into squares (
crypto/common) - commitments (to commit to a chosen value while keeping it hidden to others)
- zero-knowledge proofs as building blocks for schemes (protocols which are used as subprotocols in schemes, see
crypto/zkp) - communication layer to enable client-server interaction (for messages exchanged in protocols)
Groups
The following groups are offered in appropriate subpackages of crypto package:
- ℤ<sub>n</sub>* (
zn.Group) - group of all integers smaller than n and coprime with n. In the special case when n is a prime, a specialized groupzn.GroupZpmay be used. - Schnorr group (
schnorr.Group) - cyclic subgroup of ℤ<sub>p</sub>; the order of Schnorr group is q where p = qr + 1 for some r (p, q are primes); the order of Schnorr group is smaller than of ℤ<sub>p</sub> which means faster computations - RSA group (
rsa.Group) - group of all integers smaller than n and coprime with n, where n is a product of two distinct large primes - QR RSA group (
qr.RSA) - group of quadratic residues modulo n where n is a product of two primes - QR special RSA group (
qr.RSASpecial) - group of quadratic residues modulo n where n is a product of two safe primes - Elliptic curve group (
ec.Group) - wrapper around Goelliptic.Curve
Commitments
The following commitments are offered in appropriate subpackages of crypto package:
- Pedersen - for commitments in Schnorr group (supported ℤ<sub>p</sub> and EC groups, see packages
pedersenandecpedersen, respectively) - Damgard-Fujisaki [12] - for commitments in QR special RSA group (see package
df) - Q-One-Way based [9] (see package
qoneway). Note that Damgard-Fujisaki commitments should be used instead.
Zero-knowledge proofs
- Schnorr proofs for proving the knowledge of dlog [5],
dlog equality [7], dlog equality blinded transcript [4], and partial dlog knowledge [8]. All of these proofs
work with both ℤ<sub>p</sub> and EC groups (see packages
schnorrandecschnorr, respectively). - Proofs of knowledge of homomorphism preimage and knowledge of partial homomorphism preimage
(see package
preimage). These are generalizations of Schnorr proof to general groups and one-way homomorphisms. - Proof of knowledge of representation (generalized Schnorr for multiple bases) [10]
- Damgard-Fujisaki proofs (package
df) [12] - for proving that you can open a commitment, that two commitments hide the same value, that a commitment contains a multiplication of two committed values, that the committed value is positive, that the committed value is a square, commitment range based on Lipmaa [11] - QR special RSA representation proof (like Schnorr but in QR special RSA group, see
qrpackage) - Quadratic residuosity and nonresiduosity (packages
qrandqnr) [6] - Camenisch-Shoup verifiable encryption [1]
Communication
Client-server communication code (based on gRPC) which enables execution of protocols over the internet is in
client and server packages. The messages and services are defined in proto folder. Translations between
gRPC and native emmy messages are in proto/translations.go.
Currently offered cryptographic schemes
Currently two anonymous credentials schemes are offered:
- Pseudonym system [4] (see
crypto/zkp/schemes/pseudonymsys) (offered in ℤ<sub>p</sub> and EC groups) - Camenisch-Lysyanskaya anonymous credentials [2][15] (see
crypto/cl) - work in progress
Pseudonym system [4] was the first anonymous credential scheme and was superseded by Camenisch-Lysyanskaya scheme [2].
Camenisch-Lysyanskaya anonymous credentials
What are anonymous credentials:
- user gets a certificate which contains personal data (name, gender, nationality, age ... )
- the same certificate can be used to connect to different services (even if the databases are joined service providers cannot map/link the users)
- when connecting to a service, user can choose which data to reveal - some services might require only the possession of a certificate (e.g. certify
