Suppose you have a bank account or a company. For some reason, the administration will not simply trust your word when you tell them your name is John Doe, living in the Himalayas, and all the money from your account suddenly went to charity. Those nagging people demand some proof, so you must show an identification document convincing them of your identity.
Most of the time, you will present your ID card or a passport issued by your government. By displaying your ID card, you also reveal additional private information that the other side did not ask for but received anyway. That is because many personal details are found on the same document.
Showing partial documents was not really an option so far, as the subset of information, like a broken piece of an ID card, a page scrapped from a passport, or a single line sliced from a larger digital document, would be unverifiable without the rest of the original document.
On the other hand, extracting verifiable pieces of information while hiding the unwanted parts is a school example use case for using zero-knowledge proofs. It is not a new idea to use zero-knowledge magic to generate verifiable subsets of the credentials. Still, a lack of standardization for the existing approaches that could also cover the Blockchain use cases opens up a new research topic.
This research didn't aim to invent the wheel by creating new standards. On the opposite, the main idea was to reuse the existing, proven standards from the Web 2.0 world and migrate them to Blockchain and Web 3.0 with as few modifications as possible. However, Blockchain limitations in cost and data size are challenges that require some innovative thinking.
Let's first analyze the current flow for issuing credentials. You would request a credential from the verified issuer (government, library, ticket service, etc.). The issuer will issue you a credential with a unique number printed on a specific paper form along with other document details or as a digital document. You would receive the credential only if the issuer agrees with that. The issuers would sign the credentials with their private key to prevent counterfeits.
This simple protocol gives an important insight into one specific detail - it doesn't matter if the issuing protocol is performed in an environment with multiple verifiers or on a private channel. The issuer's signature is the only important thing, as the issuer is the one who decides which credential is validly issued by putting a signature. If a verifier trusts the issuer, then all the credentials signed by the trusted issuer are considered valid. This essential detail tells us that issuing credentials on-chain is not only expensive but also unnecessary from the perspective of trust.
So that's it, nothing else to do here? Well, not exactly. We are issuing credentials off-chain, but we still need to enable credential verification on-chain so our credentials can be verified through smart contracts. The issues we are facing here are the size and format of the credentials, as smart contracts favour fixed-sized numbers much more than text documents or arbitrary length.
We can use keccak256 hashes to overcome this issue, natively supported by smart contracts. Now we have a convenient data format to represent credentials of arbitrary length but need to provide credential data to prove that it hashes to the credential hash. One more issue remains - anyone can submit credential data that hashes to some hash. It is necessary to distinguish between valid and invalid credentials. In other words, there has to be a way to verify if the credentials are issued by trusted issuers. Here digital signatures come to help. Issuers can sign credential hash using their private key, and smart contracts can recover the signer address using a natively supported recovery method.
Now we can go to our next topic - the standardization of credentials. W3C consortium created proposals for decentralized identifiers and verifiable credentials. Those standards were seen as the backbone of the credentials in Web3.0, a decentralized world. Decentralized identifiers (DID) represent a set of rules for creating document identifiers in the form of URNs with specified methods for verifying and dereferencing documents behind the identifiers.
Verifiable credentials (VC) use DIDs for representing credential documents following certain rules. There are guidelines on how to prepare data for credential verification, schemas, and how to represent the credentials using different verifiable presentations. An interesting segment of the verifiable representations is the use of Zero-Knowledge proofs to display only parts of the credentials selectively.
To get a better understanding of all this, let's give one example.
Imagine having your ID card in a digital form with all your personal information, such as birth date, full name, address, etc. Now imagine the scenario where you have to prove that your ID card is valid and your name indeed is John Doe. Still, you don't want to reveal your date of birth or any other personal information. Zero-Knowledge proofs enable you to do exactly that. You can generate convincing inclusion proofs that your credential, represented as a hash of all information contained in the document, signed by the authority, includes your name - John Doe without revealing any other information. You would then provide the signature and ZK proof to the verifier, who would be convinced that the credential is valid and you are telling the truth.
One detail we are missing here is - how to enable this verification on the smart contract. Historically, the ZK systems were considerably complex for proof generation and verification, but with Groth16 zkSNARK proofs, verification is possible even through smart contracts for ~300,000 gas. Combining all the information that we've seen so far, the protocol consists of:
Now that we have an overall picture of the protocol let's dive into the implementation details. Verifiable credentials are represented as JSON-LD documents. The documents follow strict contexts defined in the document header. The issuers issue their credentials by generating JSON-LD documents and signing them using their keys. There are many ways to verify credentials, but we will not go deeper into that rabbit hole. We will stick with the signatures created using key pairs. Specifically, to enable signature verification on Blockchain, it is important to use ECDSA signatures so the smart contracts can recover the signer's address and use the existing Ethereum keys for signing.
Another detail worth mentioning is that signing JSON documents may not always be straightforward as simply hashing the document and signing the hash. The problem arises from the freedom of reordering the fields. The document may still contain the same information, but different ordering will affect the hash and, thus, the signature.
This problem can be solved using a specific object serialization method, which is immune to field reordering. One such method is N-Quads. When the document is properly serialized, the hash can be uniquely generated and signed using the private key. To be precise, the hash should be generated only from the values, not keys. The keys can be implicitly represented as data field order numbers, which the smart contract would know in advance.
The issuer issues the credential to the user, and the issuer's work is complete. The user can derive a verifiable presentation that includes only the information required by the verifier. In our previous example, it was the name on the ID card. We need a way to prove that the name is indeed stored in the credential issued and signed by the authorized issuer.
Let's go one step at a time. To prove that we are referring to the valid credential, we only need to provide the signed credential hash to the smart contract. The more exciting part is proving that the name is contained behind the signed hash. To prove that the hash includes some data we are revealing, we need to prove the knowledge of the remaining data fields, which hash together to a value that the issuer signed.
We can quickly get the proper ordering of fields from the N-Quads serialization. We need to generate ZK proof that we know the rest of the credential hash preimage in the exact order. Once we have generated the proof, the verifiable presentation can be used in the Web 2.0 world. Still, the proof from the presentation can be submitted to Blockchain and verified. This concludes the details of our protocol for issuing and presenting verifiable credentials on Blockchain with the help of ZK proofs.
If you want to learn more about ZK applications we encourage you to check out our MACI blog post or join our Discord for more information on this topic.