├── .DS_Store ├── .github └── workflows │ └── deploy-mkdocs.yml ├── .gitignore ├── LICENSE ├── README.md └── mkdocs ├── docs ├── CNAME ├── basics │ ├── getting-started.md │ ├── introduction.md │ ├── key-concepts.md │ └── more-on-identity.md ├── circom-snarkjs │ └── index.md ├── contracts │ └── contracts.md ├── favicon.ico ├── getting-started │ ├── babyjubjub.md │ ├── claim-revocation.md │ ├── claim │ │ ├── auth-claim.md │ │ ├── claim-schema.md │ │ └── generic-claim.md │ ├── getting-started.md │ ├── identity │ │ ├── example │ │ │ ├── go.mod │ │ │ └── main.go │ │ ├── identifier.md │ │ ├── identity-profile.md │ │ ├── identity-state.md │ │ ├── identity-types.md │ │ └── onchain-identity.md │ ├── issue-claim-overview.md │ ├── json-ld-credential.md │ ├── mt.md │ ├── signature-claim │ │ └── signature.md │ └── state-transition │ │ ├── new-identity-state.md │ │ ├── on-chain-state-transition-remix.md │ │ ├── on-chain-state-transition.md │ │ ├── state-transition-proof.md │ │ └── state-transition.md ├── guides │ ├── centralized-login.md │ ├── circom-and-snarkjs.md │ └── images │ │ ├── centralized_login_protocol.png │ │ └── circuit.png ├── imgs │ ├── GIST.png │ ├── icons │ │ ├── decentralised.svg │ │ ├── open-source.svg │ │ └── privacy.svg │ ├── iden3-icon2.png │ ├── iden3.png │ ├── identity-state-diagram.png │ ├── identity_state_transition.png │ ├── inputs-to-transitState-function.png │ ├── login.png │ ├── merkle-tree-proof-of-membership-visual-0.png │ ├── merkle-tree-proof-of-membership-visual-1.png │ ├── merkle-tree-proof-of-membership-visual-2.png │ ├── merkle-tree-proof-of-membership-visual-3.png │ ├── merkle-tree-proof-of-membership-visual-4.png │ ├── merkle-tree-proof-of-membership-visual-5.png │ ├── merkle-tree-proof-of-membership-visual-6.png │ ├── merkle-tree-proof-of-membership-visual-7.png │ ├── merkle-tree-proof-of-membership-visual-8.png │ ├── merkle-tree-specification-visual-0.png │ ├── merkle-tree-specification-visual-1.png │ ├── merkle-tree-specification-visual-2.png │ ├── merkle-tree-specification-visual-3.png │ ├── merkle-tree-tamper-resistance-visual-0.png │ ├── merkle-tree-tamper-resistance-visual-1.png │ ├── merkle-tree-tamper-resistance-visual-1b.png │ ├── merkle-tree-tamper-resistance-visual-2.png │ ├── merkle-tree-tamper-resistance-visual-3.png │ ├── merkle-tree-tamper-resistance-visual-4.png │ ├── sparse-merkle-tree-0.png │ ├── sparse-merkle-tree-1.png │ ├── sparse-merkle-tree-2.png │ ├── sparse-merkle-tree-3.png │ ├── sparse-merkle-tree-4.png │ ├── transitState-input-Go.png │ ├── transitState-input-remix.png │ └── verifier-user-query.png ├── index.md ├── logo-dark.svg ├── logo.svg ├── protocol │ ├── bjjkey.md │ ├── circuits.md │ ├── claim-schema.md │ ├── claims-structure.md │ ├── main-circuits.md │ ├── non-merklized.md │ ├── querylanguage.md │ ├── spec.md │ ├── template-circuits.md │ └── zklogin.md ├── publications │ ├── pdfs │ │ ├── Baby-Jubjub.pdf │ │ ├── Ed-DSA.pdf │ │ ├── Merkle-Tree.pdf │ │ ├── Pedersen-Hash.pdf │ │ └── test.md │ └── publications.md ├── services │ ├── images │ │ ├── login_flow.png │ │ └── login_overview.png │ ├── libraries.md │ ├── login-protocol.md │ └── rhs.md └── w3c │ ├── images │ └── json-mrklz.png │ └── merklization.md └── mkdocs.yml /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/.DS_Store -------------------------------------------------------------------------------- /.github/workflows/deploy-mkdocs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy mkdocs 2 | 3 | # Controls when the workflow will run 4 | on: 5 | # Triggers the workflow on push request events in the main branch, but only for changes within mkdocs folder 6 | push: 7 | paths: 8 | - 'mkdocs/**' 9 | branches: [ master ] 10 | 11 | # Allows running this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # Workflow jobs 15 | jobs: 16 | build-and-deploy-docs: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out repository 23 | - uses: actions/checkout@v2 24 | 25 | # Installs mkdocs 26 | - name: install mkdocs 27 | run: pip install mkdocs 28 | 29 | # Installs material theme 30 | - name: install material theme 31 | run: pip install mkdocs-material 32 | 33 | # Installs material theme 34 | - name: install mkdocs markdown graphviz 35 | run: pip install mkdocs-graphviz 36 | 37 | # Installs material theme 38 | - name: install mkdocs mermaid2 plugin 39 | run: pip install mkdocs-mermaid2-plugin 40 | 41 | # Builds docs 42 | - name: build 43 | run: cd mkdocs && mkdocs build 44 | 45 | # Deploys docs 46 | - name: deploy 47 | run: cd mkdocs && mkdocs gh-deploy --force 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mkdocs build 2 | site/ 3 | 4 | # Editors 5 | .vscode/ 6 | .idea 7 | 8 | # System files 9 | **/.DS_Store 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 | 7 | [![Chat on Twitter][ico-twitter]][link-twitter] 8 | [![Chat on Telegram][ico-telegram]][link-telegram] 9 | [![Website][ico-website]][link-website] 10 | 11 | 12 |
13 | 14 | [ico-twitter]: https://img.shields.io/twitter/url?color=black&label=Iden3&logoColor=black&style=social&url=https%3A%2F%2Ftwitter.com%2Fidenthree 15 | [ico-telegram]: https://img.shields.io/badge/telegram-telegram-black 16 | [ico-website]: https://img.shields.io/website?up_color=black&up_message=iden3.io&url=https%3A%2F%2Fiden3.io 17 | 18 | 19 | [link-twitter]: https://twitter.com/identhree 20 | [link-telegram]: https://t.me/iden3io 21 | [link-website]: https://iden3.io 22 | 23 | 24 | # Identity protocol 25 | 26 | ## Prove your access rights, not your identity 27 | 28 | iden3 is a next-generation private access control based on self-sovereign identity, designed for decentralised and trust-minimised environments. 29 | 30 | ## Privacy for all 31 | 32 | Everyone has the right to liberty and equality, the right freely to participate in their community, and the right to privacy. 33 | 34 | The aim of the iden3 protocol is to empower people and create a more inclusive and egalitarian foundation for better human relationships through open-source cryptography and decentralised technologies. 35 | 36 |
37 |
38 | 39 | Privacy by design | Decentralised | Open source 40 | :---------------------------:|:---------------------------------:|:-------------------------------: 41 | ![](mkdocs/docs/imgs/icons/privacy.svg) | ![](mkdocs/docs/imgs/icons/decentralised.svg) | ![](mkdocs/docs/imgs/icons/open-source.svg) 42 | 43 |
44 |
45 | 46 | ## Iden3 protocol libraries 47 | 48 | - **Crypto library ([go-iden3-crypto](https://github.com/iden3/go-iden3-crypto))** 49 |
Implementation of Poseidon hash and Baby JubJub Elliptic curve 50 | 51 | - **Merkle tree sql library ([go-merkletree-sql](https://github.com/iden3/go-merkletree-sql))** 52 |
Implementation of Sparse Merkle tree 53 | 54 | - **Core library ([go-iden3-core](https://github.com/iden3/go-iden3-core))** 55 |
Identity core primitives 56 | 57 | - **Circuits ([circuits](https://github.com/iden3/circuits))** 58 |
Identity circuits 59 | 60 | - **Go-circuits ([go-circuits](https://github.com/iden3/go-circuits))** 61 |
Library for transformation go-core primitives to json inputs for identity circuits 62 | 63 | - **Prover server ([prover-server](https://github.com/iden3/prover-server))** 64 |
Wrapper on snarkjs for ZK proof generation 65 | 66 | - **Authorization library ([go-iden3-auth](https://github.com/iden3/go-iden3-auth))** 67 |
Library for authentication with zkp verification (edited) 68 | 69 | --- 70 | 71 | # How to run this documentation (locally) 72 | ## Install mkdocs 73 | ``` 74 | pip3 install mkdocs 75 | ``` 76 | 77 | In case you have a rendering problem with the pieces of code, please execute: 78 | ``` 79 | pip install --upgrade mkdocs 80 | ``` 81 | 82 | ## Install mkdocs-material theme 83 | ``` 84 | pip install mkdocs-material 85 | ``` 86 | 87 | ## Install mkdocs-markdown-graphviz (1.3) 88 | ``` 89 | pip3 install mkdocs-markdown-graphviz==1.3 90 | ``` 91 | 92 | ## Run the webserver 93 | At the mkdocs directory execute: 94 | 95 | ``` 96 | mkdocs serve 97 | ``` 98 | auth 99 | 100 | ** signal input genesisID; 101 | // random number, which should be stored by user 102 | // if there is a need to generate the same userID (ProfileID) output for different proofs 103 | signal input profileNonce; 104 | 105 | // user state 106 | ** signal input state; 107 | ** signal input claimsTreeRoot; 108 | ** signal input revTreeRoot; 109 | ** signal input rootsTreeRoot; 110 | 111 | // Auth claim 112 | ** signal input authClaim[8]; 113 | 114 | // auth claim. merkle tree proof of inclusion to claim tree 115 | ** signal input authClaimIncMtp[IdOwnershipLevels]; 116 | 117 | // auth claim - rev nonce. merkle tree proof of non-inclusion to rev tree 118 | ** signal input authClaimNonRevMtp[IdOwnershipLevels]; 119 | ** signal input authClaimNonRevMtpNoAux; 120 | ** signal input authClaimNonRevMtpAuxHi; 121 | ** signal input authClaimNonRevMtpAuxHv; 122 | 123 | // challenge signature 124 | ** signal input challenge; 125 | ** signal input challengeSignatureR8x; 126 | ** signal input challengeSignatureR8y; 127 | ** signal input challengeSignatureS; 128 | 129 | // global identity state tree on chain 130 | signal input gistRoot; 131 | // proof of inclusion or exclusion of the user in the global state 132 | signal input gistMtp[onChainLevels]; 133 | signal input gistMtpAuxHi; 134 | signal input gistMtpAuxHv; 135 | signal input gistMtpNoAux; -------------------------------------------------------------------------------- /mkdocs/docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.iden3.io 2 | -------------------------------------------------------------------------------- /mkdocs/docs/basics/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Zero-knowledge Proofs 4 | To learn how to create [zero-knowledge](../basics/key-concepts.md#zero-knowledge-proofs) proofs, have a look at [Circom and SnarkJS guide](../circom-snarkjs/index.md). 5 | 6 | The process starts with employing various techniques of writing circuits for zero-knowledge proofs; it then moves on to creating and verifying a proof off-chain and finishes off by showing you how to replicate the process on-chain with Ethereum. 7 | 8 | 10 | 11 | 12 | ## Services and Protocols 13 | To get started with any of our services/protocols, have a look [here](../services/libraries.md). 14 | -------------------------------------------------------------------------------- /mkdocs/docs/basics/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | >Identity is a uniquely human concept. It is that ineffable “I” of self-consciousness, something that is understood worldwide by every person living in every culture. As René Descartes said, Cogito ergo sum — I think, therefore I am. ([Source](http://www.lifewithalacrity.com/2016/04/the-path-to-self-soverereign-identity.html)) 4 | 5 | What constitutes your identity? What makes you who you are? What is it about you that distinguishes you from others? Philosophers have argued over these questions since the beginning of civilization. Suffice to say there are no simple answers. Identity is a difficult concept to pin down. 6 | 7 | Nevertheless, we don't need a precise definition to see that there are problems with how modern society thinks about identity. 8 | 9 | In the words of [Christopher Allen](http://www.lifewithalacrity.com/2016/04/the-path-to-self-soverereign-identity.html): 10 | 11 | >Today, nations and corporations conflate driver’s licenses, social security cards, and other state-issued credentials with identity; this is problematic because it suggests a person can lose his very identity if a state revokes his credentials or even if he just crosses state borders. I think, but I am not. 12 | 13 | How can we improve on this? 14 | 15 | It is clear that we are at an inflection point for how the digital world interacts with the physical world. 16 | 17 | **The legacy systems of the physical world have not kept up with the rising importance of the digital world.** As both worlds continue to merge, this scenario will need to change. 18 | 19 | This gives us an opportunity to create systems -- from the ground up -- that bridge the two. The systems that operate with a different concept of identity. 20 | 21 | If we design them well, these systems will allow us to redefine how modern society thinks about identity. Perhaps getting us closer to that ineffable "I" of self-consciousness. 22 | 23 | At Iden3, **we're focused on building the tools and developing the protocols to make this happen.** 24 | -------------------------------------------------------------------------------- /mkdocs/docs/basics/key-concepts.md: -------------------------------------------------------------------------------- 1 | # Key Concepts 2 | 3 | ## Identity 4 | 5 | At Iden3, our goal is to democratize identity. We believe that everyone should be empowered to become their own [certification authority](https://en.wikipedia.org/wiki/Certificate_authority). 6 | 7 | **What Do We Mean by Identity?** 8 | 9 | An identity can be a person, a company, an organization, a [DAO](https://hackernoon.com/what-is-a-dao-c7e84aa1bd69), or a government. Identity can even be a thing: a chair, a room, a bot, and so on. When we talk about identities, we are referring to "identities as accounts". 10 | 11 | Generally speaking, these accounts are going to be smart contracts. So **you can think of identities as smart contracts**, where the address of the contract is the identifier of that identity. 12 | 13 | **Key Takeaways**: 14 | 15 | - **Anything** can be an identity. 16 | 17 | - One person can define and have many identities. 18 | 19 | - In Ethereum, an identity is an **account** or a smart contract. 20 | 21 | ## Claims 22 | 23 | An [identity](#identity) can provide a claim. You can think of a claim as a statement: something an identity is saying. 24 | 25 | Most of the time, these statements refer to other identities. In other words, **claims usually create relations between identities.** 26 | 27 | For example, when a university (identity) says that a student (identity) has a degree, this is a statement (claim) about the student. This statement creates a relation between the student and the university. 28 | 29 | **Claims can be public or private.** And it turns out that almost anything we say or do can be thought of as a claim. Company invoices, Facebook likes, and email messages can all be thought of as claims. 30 | 31 | ### Examples of Claims 32 | 33 | - A certificate (e.g. birth certificate) 34 | 35 | - A debt recognition 36 | 37 | - An invoice 38 | 39 | - An Instagram "Like" 40 | 41 | - An endorsement (reputation) 42 | 43 | - An email 44 | 45 | - A driving license 46 | 47 | - A role in a company 48 | 49 | - ... Almost anything! 50 | 51 | ## Zero-knowledge Proofs 52 | 53 | *In cryptography, a zero-knowledge proof or zero-knowledge protocol is a method by which one party (the prover) can prove to another party (the verifier) that they know a value x, without conveying any information apart from the fact that they know the value x.* ([Source](https://en.wikipedia.org/wiki/Zero-knowledge_proof)) 54 | 55 | In other words, zero-knowledge proofs allow us to prove something specific without revealing any extra information. 56 | 57 | Why do we care? Simply put, when we're talking about claims, sometimes, we want to prove things in a private manner. 58 | 59 | ### Examples 60 | 61 | #### Nightclub Entry 62 | 63 | Say you want to enter a nightclub, and you need to prove to the bouncer that you are over 18. But you don't want to reveal to him your name, address, or anything else that's not relevant. 64 | 65 | With zero-knowledge proof, you can prove that you hold the key that belongs to an identity that the state says is over 18, without revealing anything else about that identity. 66 | 67 | #### ICO Participation 68 | 69 | Say an ICO is available only to KYC-approved or authorized users. With ZK proofs, you can prove that you are an authorized person to participate in the ICO without revealing who you are or how much you spent. 70 | 71 | #### Anonymous Voting 72 | 73 | Similar to the above, ZK proofs allow you to prove that you are an eligible identity, without revealing your identity. 74 | 75 | ### Non-reusable Proofs 76 | 77 | A non-reusable proof is a received proof that is not valid to be sent to a third identity. 78 | 79 | For example, imagine that you belong to a given political party. This party has made a private claim that you belong to it. 80 | 81 | Now, you want to prove to another identity that you belong to the party, but you don't want that this identity to pass on that proof to others. In other words, you want to make sure the proof stays between the two of you.We can do this using zero-knowledge proofs. 82 | 83 | How? 84 | 85 | To prove something - let's call it A - we can create a new proof called B that is valid either if A is valid or we know the private key of the recipient, R. 86 | 87 | 88 | 89 | Clearly, we don't know R's private key, so when we share a valid proof B with R, R knows that A must be valid. 90 | 91 | 92 | 93 | To see why B is non-reusable, let us suppose that R wants to share B with another recipient R'. 94 | 95 | 96 | 97 | Now, from the perspective of R', B is valid either if A is valid or R knows its own private key. 98 | 99 | 100 | 101 | But since R clearly knows its private key, R' can't tell whether A is valid or not. 102 | 103 | 104 | 105 | ### ZK-SNARKs 106 | 107 | You can think of ZK-SNARKs as an efficient way to produce zero-knowledge proofs. These are the proofs that are short enough to be published on blockchain and that can be read later by a verifier. 108 | 109 | ## Digital Signatures 110 | 111 | A digital signature is a mathematical scheme for demonstrating the authenticity of digital messages or documents. A valid digital signature gives a recipient reason to believe that the message was created by a known sender, that the sender cannot deny having sent the message (authentication and non-repudiation), and that the message was not altered in transit (integrity). ([Source](https://en.wikipedia.org/wiki/Digital_signature)) 112 | 113 | We use digital signatures for user authentication purposes and to prove that a claim was issued by a specific identity. 114 | 115 | ## Merkle Trees 116 | 117 | In cryptography and computer science, a Merkle tree is a tree in which every leaf node is labeled with the hash of a data block and every non-leaf node is labeled with the cryptographic hash of the labels of its child nodes. ([Source](https://en.wikipedia.org/wiki/Merkle_tree)) 118 | 119 | We care about Merkle trees because we want to build a data structure that: 120 | 121 | - Can store lots of data (**scalability**) 122 | - Makes it easy to prove that some data exists (**proof of membership**) 123 | - Allows us to check that the data hasn't been altered (**tamper resistance**) 124 | 125 | Merkle trees satisfy the three properties mentioned above. 126 | 127 | ### Specifications 128 | 129 | Before we take a closer look at these properties, let's go through how to build a Merkle tree with some given data. 130 | 131 | ![](../imgs/merkle-tree-specification-visual-0.png) 132 | 133 | Suppose we have several blocks containing data and that these blocks form the leaves of our tree. The first step is to create a parent node for each data block. These parent nodes form the next level in the tree and store the hash of their descendent data block. 134 | 135 | ![](../imgs/merkle-tree-specification-visual-1.png) 136 | 137 | Next, we group these parent nodes into pairs and store the hash of each pair one level up the tree. 138 | 139 | ![](../imgs/merkle-tree-specification-visual-2.png) 140 | 141 | We continue doing this until we are left with a single block, the root of the tree, also called Merkle Root. 142 | 143 | ![](../imgs/merkle-tree-specification-visual-3.png) 144 | 145 | ### Tamper Resistance 146 | 147 | It turns out that any attempt to tamper with any piece of data can be detected by simply remembering the hash at the root of the tree. 148 | 149 | To understand why this is the case, let’s look at what happens if an adversary wants to tamper with a data block. 150 | 151 | ![](../imgs/merkle-tree-tamper-resistance-visual-0.png) 152 | 153 | If an adversary tampers with a block at the leaf of our tree, 154 | 155 | ![](../imgs/merkle-tree-tamper-resistance-visual-1.png) 156 | 157 | it will cause the mismatch with the hash in the node that’s one level up. 158 | 159 | ![](../imgs/merkle-tree-tamper-resistance-visual-2.png) 160 | 161 | So the adversary will have to tamper with that too. 162 | 163 | ![](../imgs/merkle-tree-tamper-resistance-visual-3.png) 164 | 165 | This means s/he has to tamper with the node one level up from there. 166 | 167 | ![](../imgs/merkle-tree-tamper-resistance-visual-4.png) 168 | 169 | And so on… Eventually, s/he will get to the root. If s/he tries to tamper with the root too, we’ll know because this is the node we’ve kept track of. 170 | 171 | ### Proof of Membership 172 | 173 | Merkle trees allow us to quickly check membership (through a neat mechanism known as Merkle proofs). What do we mean by that? 174 | 175 | ![](../imgs/merkle-tree-proof-of-membership-visual-0.png) 176 | 177 | Suppose that, as usual, we remember just the root (on-chain). And we want to prove that a certain data block, data0, is a member of the Merkle tree. 178 | 179 | ![](../imgs/merkle-tree-proof-of-membership-visual-1.png) 180 | 181 | All we need are the blocks on the path from the data block to the root. 182 | 183 | ![](../imgs/merkle-tree-proof-of-membership-visual-2.png) 184 | 185 | And each of data0's siblings on the way up. 186 | 187 | ![](../imgs/merkle-tree-proof-of-membership-visual-3.png) 188 | 189 | We can ignore the rest of the tree, as these blocks are enough to allow us to verify the hashes all the way up to the root of the tree. But how? 190 | 191 | ![](../imgs/merkle-tree-proof-of-membership-visual-4.png) 192 | 193 | The idea is to recalculate the root by recursively hashing the data. If the calculated root is equal to the on-chain root, it proves that the data block exists in the Merkle tree. 194 | 195 | ![](../imgs/merkle-tree-proof-of-membership-visual-5.png) 196 | 197 | In our case, we start by calculating the hash of data0 and storing it in the block labeled 0. 198 | 199 | ![](../imgs/merkle-tree-proof-of-membership-visual-6.png) 200 | 201 | We then calculate the hash of the hash of data0 concatenated with the hash of data1. In other words, we calculate the hash of the concatenation of blocks 0 and 1 and store it in block 4. 202 | 203 | ![](../imgs/merkle-tree-proof-of-membership-visual-7.png) 204 | 205 | Finally, we calculate the hash of blocks 4 and 5 to obtain the recalculated root. 206 | 207 | ![](../imgs/merkle-tree-proof-of-membership-visual-8.png) 208 | 209 | If the calculated root is equal to the on-chain root, we’ve proven that data0 exists in the Merkle tree. 210 | 211 | In technical terms: 212 | 213 | *This means that if there are n nodes in the tree, only about log(n) items need to be shown. And since each step just requires computing the hash of the child block, it takes about log(n) time for us to verify it. And so even if the Merkle tree contains a very large number of blocks, we can still prove membership in a relatively short time. Verification thus runs in time and space that’s logarithmic in the number of nodes in the tree.* ([Source](https://d28rh4a8wq0iu5.cloudfront.net/bitcointech/readings/princeton_bitcoin_book.pdf) (pg 35)) 214 | 215 | ### Scalability 216 | 217 | Storing data on a blockchain is expensive. Merkle trees help us in minimizing the amount of data stored on-chain. How? 218 | 219 | As we saw in the previous sections, to ensure tamper-resistance and Proof of Membership, we need to store only the root of the tree, not the whole tree. This means that no matter how big the tree is, the only piece of data we actually need to store on-chain is the root. 220 | 221 | ### Sparse Merkle Trees 222 | At Iden3, we use a slightly more complex data structure called a sparse Merkle tree. 223 | 224 | A sparse Merkle tree is like a standard Merkle tree, except that its contained data is indexed, and each data block is placed at the leaf that corresponds to that block's index. 225 | 226 | In addition to inheriting the *tamper-resistance* and *proof of membership* properties from normal Merkle trees, sparse Merkle trees make it easy to prove that some data doesn’t exist (*proof of non-membership*). 227 | 228 | #### Proof of Non-membership 229 | 230 | ![](../imgs/sparse-merkle-tree-0.png) 231 | 232 | Now consider that we only have two pieces of data -- `data0` and `data3` -- with indices `0` and `3` respectively. To construct a sparse Merkle tree, we populate the 0th and 3rd leaves with this data, leaving the 1st and 2nd leaves empty. 233 | 234 | ![](../imgs/sparse-merkle-tree-1.png) 235 | 236 | Well, almost empty! To be precise, we fill the 1st and 2nd leaves in with a special placeholder value like `null`. 237 | 238 | ![](../imgs/sparse-merkle-tree-2.png) 239 | 240 | With this placeholder, we can now build up the rest of the tree. 241 | 242 | ![](../imgs/sparse-merkle-tree-3.png) 243 | 244 | Now, what happens if we want to prove that a piece of (indexed) data -- `data2` -- is not a member of this tree? 245 | 246 | ![](../imgs/sparse-merkle-tree-4.png) 247 | 248 | Thanks to the way our data is indexed, proving that `data2` is not a member of the tree is equivalent to proving that the value of the leaf at index `2` is `null`! 249 | 250 | Put another way, proving non-membership of a `data` block is equivalent to proving membership of `null` (a simple Merkle proof). And as we saw in our previous post, doing this efficiently is a basic property of a Merkle tree. 251 | 252 | #### Summary 253 | 254 | By indexing data and making leaves empty, sparse Merkle trees allow us to reframe proofs of non-membership into proofs of membership (a.k.a Merkle proofs), making it easy to prove that some data does not exist. 255 | 256 | One drawback to sparse Merkle trees is that they are really big. This means that without optimizations, read and write operations can be quite inefficient. 257 | 258 | > For example, a sparse Merkle tree usually has 2^256 leaves vs. 2^32 for a normal Merkle tree. This means that naive implementations require 256 operations to read or write (vs 32). 259 | 260 | Luckily, these sorts of inefficiencies are largely illusory. Since fairly simple [optimizations](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751) exist to get around them! 261 | 262 | !!!note 263 | While we won't get into the details here, one of the keys to these optimizations is that sparse Merkle trees are mostly sparse. This means many of the subtrees will end up being zero subtrees. 264 | 265 | Since H(0), H(H(0)), H(H(H(0))), and so on are all constant values, the zero-subtrees can be cached (calculated once, stored, and then omitted from Merkle proofs), greatly reducing the size of computations. 266 | 267 | 268 | ### Why Do We use Merkle Trees at Iden3? 269 | 270 | At Iden3, one of our major goals is scalability. Specifically, we believe that anybody should be able to create as many identities as they want. And that **any identity should be able to generate as many claims as it wants.** 271 | 272 | Imagine if you had to make a new transaction to the blockchain every time you wanted to make a new claim? Even worse, imagine you're a government institution and you're responsible for making millions of claims every day. 273 | 274 | Achieving this goal requires minimizing the amount of data stored on-chain. This is where Merkle trees come into the picture. 275 | 276 | Even if you're a government institution that is making millions of claims a day, you can just construct a tree (off-chain) with each claim as a separate data block, and simply calculate and store the root on-chain. 277 | 278 | In other words, Merkle trees allow prolific claim generators to add/modify **millions of claims** in a single transaction. This makes it easy to scale the claims. 279 | 280 | ### Definitions 281 | 282 | 283 | #### Hash Functions 284 | 285 | A hash function maps an input string of any size to an output string of a fixed size. 286 | 287 | It must be efficiently computable (for any given input string, we can figure out the output of the hash function in a reasonable amount of time. More technically, computing the hash of an n‐bit string should have a running time that is O(n)). 288 | 289 | For a hash function to be cryptographically secure, it must have three additional properties: 290 | 291 | - Collision Resistance 292 | - Hiding 293 | - Puzzle-friendliness 294 | 295 | While we would not get into the details here, let's briefly discuss what each of these properties stands for. 296 | 297 | **Collision Resistance** means that nobody can find two inputs that map to the same output. 298 | 299 | **Hiding** means that given an output there's no feasible way to figure out the input that generated it. 300 | 301 | **Puzzle-friendliness**, intuitively, means that it is very hard to target the hash function to come out to some particular output value y. 302 | 303 | #### Hash Pointers 304 | 305 | A hash pointer is simply a pointer to where some information is stored together with a cryptographic hash of the information. **A pointer gives you a way to retrieve the information, whereas a hash pointer gives you a way to verify that the information wasn't changed.** 306 | 307 | In other words, a hash pointer is a pointer to where data is stored along with a cryptographic hash of the value of that data at some fixed point in time. 308 | 309 | If at some point in the future, we want to check if the data hasn't changed, we simply hash the data again and verify that the new output (cryptographic hash) matches the previous output. This works because we know by the **collision resistance** property of the hash function that nobody can find two inputs that map to the same output. So if the output is the same, the input must also have been the same. 310 | 311 | -------------------------------------------------------------------------------- /mkdocs/docs/basics/more-on-identity.md: -------------------------------------------------------------------------------- 1 | # More on Decentralized Identity 2 | 3 | ### Why Does Identity Matter? 4 | 5 | In the words of [Vitalik](https://vitalik.ca/general/2019/04/03/collusion.html): 6 | 7 | >Mechanisms that do not rely on identity cannot solve the problem of concentrated interests outcompeting dispersed communities; an identity-free mechanism that empowers distributed communities cannot avoid over-empowering centralized plutocrats pretending to be distributed communities. 8 | 9 | In other words, without an identity mechanism, one can't ensure "one human, one address" or "one human, one vote". This means that however you structure the rules of the system, those with the most resources would be able to game it. 10 | 11 | ### How Is the Existing System Failing Us? 12 | 13 | In recent times, identities have been verified by credentials such as a passport or a social network account issued by a central authority (usually a state or corporation). 14 | 15 | However, as noted in [Verifying Identity as a Social Intersection](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3375436), such identity systems have several interrelated flaws: 16 | 17 | 1. They are **insecure**. Crucial data such as an ID number constantly has to be given out. This is enough to impersonate an individual. On top of this, since all data is stored in a single repository managed by the state or a corporation, it becomes particularly vulnerable to hacking or internal corruption. 18 | 19 | 2. They **narrow** you down to one thing (in the system or out, a criminal or not, a credit score, etc.). The central database has little use for more information than this. This limits the functionality of the system and results in great injustices (for example, convicted individuals find it hard to re-enter society as this is the only information about them that they can reliably convey). 20 | 21 | 3. They are **artificial** in the sense that the information stored about you usually bears little relation to what you or your friends think of you about your identity. 22 | 23 | To quote directly from the paper: 24 | 25 | >Recently, new identity paradigms have tried to get around some of these elements. One approach, adopted by "big data" platforms like Facebook and Google, is to overcome thinness [narrowness] by storing enormous amounts of detailed information about each individual. we might call this "panoptic identity". However, such solutions have greatly exacerbated the other two problems, as they require extremely artificial compromises to intimacy through the global sharing of data with platforms that would not otherwise store it, creating exceptional potential security risks. 26 | 27 | ### Why Do We Need This Vision Now? 28 | 29 | Given the rising political polarization and the increasing amount of information collected, shared, and cross-correlated by governments and corporations, there's a real risk that our information will be used against us in ways we cannot imagine. 30 | 31 | If history has taught us anything, it's that **power belongs to those who control the information**. 32 | 33 | Right now, that power belongs to the gatekeepers of our identities: governments and corporations. 34 | 35 | In an increasingly uncertain world, there's a real risk that general fear, discontent and polarization will result in that power being abused. 36 | 37 | In such a world, a check on the government and corporate power that goes beyond formal legal protection is essential. 38 | 39 | By putting the control of information back in our hands, decentralized identity systems provide a natural technological check on the ability of the governments and corporations to abuse their power. 40 | 41 | ### How Can the Developing World Benefit? 42 | 43 | In the developing world, decentralized identity systems have the potential to help bring millions of people out of the clutches of poverty. 44 | 45 | To quote the words of [Timothy Ruff](https://medium.com/evernym/7-myths-of-self-sovereign-identity-67aea7416b1): 46 | 47 | >Most of us take for granted that we can prove things about ourselves, unaware that over a billion people cannot. Identity is a prerequisite to financial inclusion, and financial inclusion is a big part of solving poverty. 48 | 49 | ### What Are Some of the Use Cases? 50 | 51 | #### Liquid Democracy 52 | 53 | Imagine if you could vote every two weeks to express your political sentiments regarding interest rates. 54 | 55 | Imagine if you could have a direct say in any decision rather than relying on elected politicians to represent you. Imagine if those in power were held accountable in real-time rather than once every few years. This is the promise of liquid democracy. Liquid democracy exists somewhere in the sweet spot between direct and representative democracy. 56 | 57 | As with direct democracy, everyone has the opportunity to vote on every issue. However, unlike direct democracy, you also have the choice to delegate your vote to someone else. You can even choose to delegate your votes on different issues to different people. 58 | 59 | For example, on environmental issues, you might choose to delegate your vote to your favourite environmentalist. Whereas on issues concerning government debt and taxation you might choose your father. 60 | 61 | This ability to delegate is recursive. It means that if your father, in turn, chooses to delegate his vote on financial issues to his favourite economist, your vote will also be delegated to that economist. 62 | 63 | If you're unhappy with your father's decision, you can take that power away from him/her, and either vote yourself or re-delegate to someone you deem more trustworthy. 64 | 65 | Under such a system, those with the most delegations become our representatives. But unlike representative democracy, they are held accountable in real-time. 66 | 67 | >A system like this addresses the uninformed voters' issue that a direct democracy creates by allowing these voters allot their votes to experts. It also addresses the corruption issues of representative democracy because citizens can rescind their vote from someone instantly, forcing delegates to vote in the best interest of their constituents. It is the best of both worlds that truly gives the power of influence to the voters. ([Source](https://media.consensys.net/liquid-democracy-and-emerging-governance-models-df8f3ce712af)) 68 | 69 | This sounds almost too good to be true. A fair, transparent, and corruption-free government! Why haven't we implemented this before? 70 | 71 | Since there is no central government under this form of democracy, we need to figure out how to allow citizens to vote in a secure, private, and decentralized way. It turns out this is a pretty hard problem to solve. It has actually been impossible to solve. Until now. This is the first time in our history that technology exists to turn this dream into reality. Of course, we're talking about public blockchains. 72 | 73 | Right now, we're in the experimentation phase. There are still some hard challenges that need to be overcome. 74 | 75 | The three main challenges revolve around **scalability**, **privacy**, and **Sybil attacks**. 76 | 77 | Scalability is important because we need millions of people to be able to use these systems. 78 | 79 | Privacy is important because it ensures voters can't be discriminated against for the decisions they make. It also makes it harder for them to be bribed/coerced into voting for something they don't believe in. 80 | 81 | But perhaps the hardest challenge is to ensure that one person is not able to vote multiple times (what's known in the jargon as a Sybil attack). 82 | 83 | The key to solving the last two challenges is a voting protocol that requires basic verification and reputation for each user whilst protecting their pseudonymous identity. In other words, a voting protocol with a built-in decentralized identity system. 84 | 85 | Put another way, decentralized identity is the big unlock that's needed to turn liquid democracy into a reality. 86 | 87 | **P.S.** It turns out that solving the privacy problem helps solve the scalability problem too, but we won't get into that here. -------------------------------------------------------------------------------- /mkdocs/docs/circom-snarkjs/index.md: -------------------------------------------------------------------------------- 1 | # Circom 2.0 2 | 3 | > Circuit Compiler for ZK Proving Systems 4 | 5 | [Circom](https://iden3.io/circom) is a novel domain-specific language for defining arithmetic circuits and its associated compiler written in Rust language. 6 | 7 | Our open-source library of templates called [CircomLib](https://github.com/iden3/circomlib) is publicly available to practitioners and developers. The library contains multiple circuit templates that have been reviewed and proven to work by our research team. 8 | 9 | The implementations of the proving systems are also available in our libraries: [SnarkJS](https://github.com/iden3/snarkjs), written in Javascript and Pure Web Assembly; and [rapidsnark](https://github.com/iden3/rapidsnark) written in C++ and has assembly optimizations for x86_64 and ARM processors. 10 | 11 | This way, Circom aims to provide developers with a holistic framework to construct arithmetic circuits through an easy-to-use interface and abstract the complexity of the proving mechanisms. 12 | 13 | --- 14 | 15 | #
[==> circom](https://docs.circom.io/)
16 | 17 | --- 18 | -------------------------------------------------------------------------------- /mkdocs/docs/contracts/contracts.md: -------------------------------------------------------------------------------- 1 | [**State.sol - Github**](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol) 2 | 3 | The State Contract stores the [Global Identity State Tree](../protocol/spec.md#gist-new). The GIST State represents a snapshot of the states of all the identities operating in the system. The design of the State Contract allows identities to authenticate themselves using [Identity Profiles](../protocol/spec.md#identity-profiles-new) 4 | 5 | Every time that an identity is updated, for example when a credential is issued using SMT Proof or revoked, it needs to perform a [State Transition](../getting-started/state-transition/on-chain-state-transition.md). This process consists of generating a zk-proof or a digitally signed message that proves that the identity is authorized to perform the state transition. 6 | Then State contract verifies the proof on-chain via its [transitState](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol) (for zk-proofs) or [transitStateGeneric](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol) (generic as name suggests) function. 7 | Note that the actual zk-proof verification is performed by calling the `verifyProof` function inside the [verifier.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/verifier.sol) from the [`transitState`](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol) function inside the State Contract. 8 | 9 | Whenever an identity is updated, the State contract updates the corresponding leaf of the GIST Tree. This process is managed by the [SMTLib](https://github.com/iden3/contracts/blob/master/contracts/lib/SmtLib.sol) which is a Sparse Merkle Tree implementation that manages the GIST Tree and keeps track of its history. 10 | 11 | The `verifier.sol` contract is automatically generated using circom and can be used as a standalone contract to verify state transition zk-proof. `State` implements further logic once the proof is verified (such as updating the GIST State). 12 | 13 | ### State contract addresses 14 | 15 | - Ethereum: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896](https://etherscan.io/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 16 | - Ethereum Sepolia: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896](https://sepolia.etherscan.io/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 17 | - Polygon Mainnet: [0x624ce98D2d27b20b8f8d521723Df8fC4db71D79D](https://polygonscan.com/address/0x624ce98D2d27b20b8f8d521723Df8fC4db71D79D) 18 | - Polygon Amoy Testnet: [0x1a4cC30f2aA0377b0c3bc9848766D90cb4404124](https://www.oklink.com/amoy/address/0x1a4cc30f2aa0377b0c3bc9848766d90cb4404124) 19 | - Polygon zkEVM: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896](https://zkevm.polygonscan.com/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 20 | - Polygon zkEVM Cardona: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896](https://cardona-zkevm.polygonscan.com/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 21 | - Linea: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896](https://lineascan.build/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 22 | - Linea-Sepolia: [0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a89](https://sepolia.lineascan.build/address/0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896) 23 | 24 |
25 | [**IdentityTreeStore.sol - Github**](https://github.com/iden3/contracts/blob/master/contracts/identitytreestore/IdentityTreeStore.sol) 26 | 27 | The identity tree store contract is responsible for storing revocation and roots tree nodes of Identity. In case 28 | when identity is using onchain [RHS](https://docs.iden3.io/services/rhs/) and [Iden3OnchainSparseMerkleTreeProof2023](https://iden3-communication.io/w3c/status/overview/) credential status. 29 | 30 | ### IdentityTreeStore contract addresses (On-chain RHS) 31 | 32 | - Ethereum: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://etherscan.io/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 33 | - Ethereum Sepolia: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://sepolia.etherscan.io/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 34 | - Polygon Mainnet: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://polygonscan.com/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 35 | - Polygon Amoy Testnet: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://www.oklink.com/amoy/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 36 | - Polygon zkEVM: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://zkevm.polygonscan.com/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 37 | - Polygon zkEVM Cardona: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://cardona-zkevm.polygonscan.com/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 38 | - Linea: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://lineascan.build/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 39 | - Linea-Sepolia: [0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81](https://sepolia.lineascan.build/address/0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81) 40 | 41 | ### VALIDATOR_MTP_V2 contract addresses 42 | 43 | - Ethereum: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://etherscan.io/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 44 | - Ethereum Sepolia: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://sepolia.etherscan.io/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 45 | - Polygon Mainnet: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://polygonscan.com/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 46 | - Polygon Amoy Testnet: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://www.oklink.com/amoy/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 47 | - Polygon zkEVM: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://zkevm.polygonscan.com/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 48 | - Polygon zkEVM Cardona: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://cardona-zkevm.polygonscan.com/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 49 | - Linea: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://lineascan.build/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 50 | - Linea-Sepolia: [0x27bDFFCeC5478a648f89764E22fE415486A42Ede](https://sepolia.lineascan.build/address/0x27bDFFCeC5478a648f89764E22fE415486A42Ede) 51 | 52 | ### VALIDATOR_SIG_V2 contract addresses 53 | 54 | - Ethereum: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://etherscan.io/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 55 | - Ethereum Sepolia: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://sepolia.etherscan.io/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 56 | - Polygon Mainnet: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://polygonscan.com/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 57 | - Polygon Amoy Testnet: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://www.oklink.com/amoy/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 58 | - Polygon zkEVM: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://zkevm.polygonscan.com/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 59 | - Polygon zkEVM Cardona: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://cardona-zkevm.polygonscan.com/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 60 | - Linea: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://lineascan.build/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 61 | - Linea-Sepolia: [0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b](https://sepolia.lineascan.build/address/0x59B347f0D3dd4B98cc2E056Ee6C53ABF14F8581b) 62 | 63 | ### VALIDATOR_V3 contract addresses 64 | 65 | - Ethereum: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://etherscan.io/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 66 | - Ethereum Sepolia: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://sepolia.etherscan.io/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 67 | - Polygon Mainnet: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://polygonscan.com/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 68 | - Polygon Amoy Testnet: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://www.oklink.com/amoy/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 69 | - Polygon zkEVM: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://zkevm.polygonscan.com/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 70 | - Polygon zkEVM Cardona: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://cardona-zkevm.polygonscan.com/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 71 | - Linea: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://lineascan.build/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) 72 | - Linea-Sepolia: [0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336](https://sepolia.lineascan.build/address/0xd179f29d00Cd0E8978eb6eB847CaCF9E2A956336) -------------------------------------------------------------------------------- /mkdocs/docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/favicon.ico -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/babyjubjub.md: -------------------------------------------------------------------------------- 1 | # Baby Jubjub Key Pair 2 | 3 | In Iden3 Protocol the public and private key pair is used to manage an identity and to authenticate in the name of an identity. In particular, Baby Jubjub is the elliptic curve used in Iden3. [This curve](../publications/pdfs/Baby-Jubjub.pdf) is designed to work efficiently with zkSNARKs. 4 | 5 | 1.**Initiate a Go Module** 6 | 7 | ```bash 8 | go mod init example/iden3-tutorial 9 | ``` 10 | 11 | 2.**Update the required dependencies.** 12 | 13 | ```bash 14 | go get github.com/iden3/go-iden3-crypto/babyjub 15 | ``` 16 | 17 | 3.**Generate a baby jubjub public key.** 18 | 19 | ``` go 20 | package main 21 | 22 | import ( 23 | "fmt" 24 | "github.com/iden3/go-iden3-crypto/babyjub" 25 | ) 26 | 27 | // BabyJubJub key 28 | func main() { 29 | 30 | // generate babyJubjub private key randomly 31 | babyJubjubPrivKey := babyjub.NewRandPrivKey() 32 | 33 | // generate public key from private key 34 | babyJubjubPubKey := babyJubjubPrivKey.Public() 35 | 36 | // print public key 37 | fmt.Println(babyJubjubPubKey) 38 | } 39 | ``` 40 | 41 | Here is an example of a public key generated using Baby Jubjub: 42 | 43 | ```bash 44 | 500d43e1c3daa864995a9615b6f9e3a4fd0af018548c583773b6e422b14201a3 45 | ``` 46 | 47 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L21) 48 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/claim-revocation.md: -------------------------------------------------------------------------------- 1 | # Revocation 2 | 3 | Revocation is the process of invalidating a claim. For example, if a claim is used to prove that a person is resident in a country, and the person moves to another country, the claim can be revoked by the issuer. 4 | 5 | This is done by adding the claim revocation nonce to the [revocation tree](https://docs.iden3.io/protocol/spec/#revocation-tree). The revocation tree contains revocation nonces of all the claims that were revoked. The root of the revocation tree is stored in the [identity state](./identity/identity-state.md). 6 | 7 | To revoke a claim, the revocation nonce of the claim must be added to the revocation tree. The revocation nonce is a number that is added to the claim [data structure](./claim/generic-claim.md) when it is created. 8 | 9 | ```go 10 | // revocation nonce of the claim to be revoked 11 | revocationNonce := uint64(1909830690) 12 | 13 | // add the revocation nonce to the revocation tree 14 | ret.Add(ctx, new(big.Int).SetUint64(revNonce), big.NewInt(0)) 15 | ``` 16 | 17 | The action of adding the revocation nonce to the revocation tree modifies the root of the revocation tree and, consequently, the identity state. 18 | 19 | To finalize the revocation process, the identity state must be updated on-chain by executing a [state transition](./state-transition/state-transition.md). 20 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/claim/auth-claim.md: -------------------------------------------------------------------------------- 1 | # Key Authorization Claim 2 | 3 | The most important building block of an identity is the Key Authorization Claim. This claim stores user's Baby Jubjub public key. 4 | 5 | An [Auth Claim](https://docs.iden3.io/protocol/bjjkey/) **must** be included as a leaf inside the Identity Tree. All the actions performed by an Idenitity (such as claim issuance or revocation) require users to prove via a digital signature that they own the private key associated with the public key stored in the `AuthClaim`. 6 | 7 | 1.**Specify the credential schema** 8 | 9 | The [auth claim schema](https://github.com/iden3/claim-schema-vocab/blob/main/schemas/json-ld/auth.json-ld) is pre-defined and should always be the same when creating an `AuthClaim`. The schema hash is: *`ca938857241db9451ea329256b9c06e5`*. According to this schema, X and Y coordinates of the Baby Jubjub public key must be stored, respectively, in the first and second index data slot. 10 | 11 | 2.**Generate an AuthClaim.** 12 | 13 | ```go 14 | package main 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | 20 | "github.com/iden3/go-iden3-core" 21 | "github.com/iden3/go-iden3-crypto/babyjub" 22 | ) 23 | 24 | // Create auth claim 25 | func main() { 26 | 27 | authSchemaHash, _ := core.NewSchemaHashFromHex("ca938857241db9451ea329256b9c06e5") 28 | 29 | // Add revocation nonce. Used to invalidate the claim. This may be a random number in the real implementation. 30 | revNonce := uint64(1) 31 | 32 | // Create auth Claim 33 | authClaim, _ := core.NewClaim(authSchemaHash, 34 | core.WithIndexDataInts(babyJubjubPubKey.X, babyJubjubPubKey.Y), 35 | core.WithRevocationNonce(revNonce)) 36 | 37 | authClaimToMarshal, _ := json.Marshal(authClaim) 38 | 39 | fmt.Println(string(authClaimToMarshal)) 40 | } 41 | ``` 42 | 43 | Here is what the claim would look like: 44 | 45 | ``` 46 | Claim: 47 | ["304427537360709784173770334266246861770","0","12360031355466667401641753955380306964012305931931806442343193949747916655340","7208907202894542671711125895887320665787554014901011121180092863817137691080","1","0","0","0"] 48 | ``` 49 | 50 | Let us destructure the output: 51 | 52 | ``` 53 | Index: 54 | { 55 | "304427537360709784173770334266246861770", // Schema hash 56 | "0", 57 | "12360031355466667401641753955380306964012305931931806442343193949747916655340", // X coordinate of the pubkey 58 | "7208907202894542671711125895887320665787554014901011121180092863817137691080" // Y coordinate of the pubkey 59 | } 60 | 61 | Value: 62 | { 63 | "1", // revocation nonce 64 | "0", 65 | "0", // first value data slot 66 | "0" // second value data slot 67 | } 68 | ``` 69 | 70 | The data stored in position 1 of the Value contains the Revocation Nonce. This value will be used to revoke/invalidate an `AuthClaim`. More on that in the next section. 71 | 72 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L89) 73 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/claim/claim-schema.md: -------------------------------------------------------------------------------- 1 | # Credential Schema 2 | 3 | The reusability of credentials across platforms and services is guaranteed by [Credential Schema](https://docs.iden3.io/protocol/claim-schema/) consistency. 4 | 5 | Polygon ID use [JSON-LD documents](https://json-ld.org/learn.html) to represent Credential Schemas. 6 | 7 | As an issuer it is advised to check if any of the [existing credential schemas](https://github.com/0xPolygonID/schemas/tree/main/jsonld) can accommodate the type of information you are interested to issue. 8 | 9 | If not, here's the guide to create a new credential schema. Let us create a shared and reusable credential schema of type **ProofOfDaoMembership**. 10 | 11 | 1.**Define the value to be included in the schema.** 12 | 13 | The ProofOfDaoMembership credential should attest that a person executes a role inside a specific DAO. 14 | 15 | Information such as the identifier of the DAO or the identifier of the subject of the credential don't need to be encoded inside one of the four data slots allocated for claim information (i_2,i_3, v_2, v_3): 16 | 17 | - The information about the specific DAO can be inferred from the credential issuer identifier 18 | - The information about the individual subject of the claim is already stored in the i_1 or v_1 data slot of the Claim. 19 | 20 | A further information that must be included in the claim is the *role* of the individual inside a DAO. This will be the added inside one of the data slots (i_2,i_3,v_2,v_3). 21 | 22 | Remember that a claim can only store numeric data so each DAO role should be encoded as a number. 23 | 24 | 2.**Decide where to store this information, should it be inside index data slots or value data slots?** 25 | 26 | Claim's index determines its uniqueness inside the issuer's claims tree. There cannot be more than one claim with the same index. If it is decided to store the identifier of the subject of the claim inside i_1 and leave the other index data slots empty, it means that there can only be one claim issued to a specific identity inside the tree. 27 | 28 | In this case, the question is whether to store the information with type *role* inside i_2 or v_2. 29 | 30 | - Storing the role inside i_2 means that the uniqueness inside the tree is determined by the combination "person identifier + role" 31 | - Storing the role inside v_2 means that the uniqueness inside the tree is only determined the person identifier 32 | 33 | Considering the possibility that a DAO member covers more than one role, it makes more sense to store the role inside i_2. This choice allow the DAO to issue subsequent claims to the same individual attesting a different role. 34 | 35 | 3.**Describe the vocabulary of the schema** 36 | 37 | Create a markdown file in your repository to describe the vocabulary used in the claim. This should contain a description of the key type *role* and its possible values: 38 | 39 | ```js 40 | # role 41 | 42 | Describes the role covered by an individual inside a specific DAO 43 | 44 | 1: Contributor 45 | 2: Guild Coordinator 46 | 3: Team Member 47 | ``` 48 | 49 | 4.**Create the JSON-LD document** 50 | 51 | Add a file inside your repository with extension .json-ld and populate it. 52 | 53 | The `@id` key should contain the identifier of the Schema Type "ProofOfDaoMembership", in this case the unique url to the JSON-LD document. 54 | The `proof-of-dao-vocab` key should contain the url that describes the vocabulary of the claim schema. 55 | 56 | ```json 57 | { 58 | "@context": [{ 59 | "@version": 1.1, 60 | "@protected": true, 61 | "id": "@id", 62 | "type": "@type", 63 | "ProofOfDaoMembership": { 64 | "@id": "https://raw.githubusercontent.com/iden3/tutorial-examples/main/claim-schema/proof-of-dao-membership.json-ld#ProofOfDaoMembership", 65 | "@context": { 66 | "@version": 1.1, 67 | "@protected": true, 68 | "id": "@id", 69 | "type": "@type", 70 | "proof-of-dao-vocab": "https://github.com/iden3/tutorial-examples/blob/main/claim-schema/proof-of-dao.md#", 71 | "serialization": "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/serialization.md#", 72 | "type": { 73 | "@id": "proof-of-dao-vocab:role", 74 | "@type": "serialization:IndexDataSlotA" 75 | }, 76 | } 77 | } 78 | }] 79 | } 80 | ``` 81 | 82 | 5.**Generate the schema hash** 83 | 84 | The [Schema Hash](https://docs.iden3.io/protocol/claim-schema/#schema-hash) has to be added inside claim's index. 85 | 86 | The schema hash is generated by hashing together `schemaBytes` (the JSON-LD document in byte format) and `credentialType` (in this case "ProofOfDaoMembership"). In this case: 87 | 88 | ```go 89 | package main 90 | 91 | import ( 92 | "fmt" 93 | "os" 94 | 95 | core "github.com/iden3/go-iden3-core" 96 | "github.com/iden3/go-iden3-crypto/keccak256" 97 | ) 98 | 99 | func main() { 100 | 101 | schemaBytes, _ := os.ReadFile("./tutorial-examples/claim-schema/proof-of-dao-membership.json-ld") 102 | 103 | var sHash core.SchemaHash 104 | h := keccak256.Hash(schemaBytes, []byte("ProofOfDaoMembership")) 105 | 106 | copy(sHash[:], h[len(h)-16:]) 107 | 108 | sHashHex, _ := sHash.MarshalText() 109 | 110 | fmt.Println(string(sHashHex)) 111 | // 4f6bbcb133bfd4e9ebdf09b16a0816c8 112 | } 113 | ``` 114 | 115 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/tree/main/claim-schema) 116 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/claim/generic-claim.md: -------------------------------------------------------------------------------- 1 | # Generic Claim 2 | 3 | A [Claim](https://docs.iden3.io/protocol/spec/#claims) is a statement made by one identity about another identity or about itself. In general, claim is a flexible and modular data primitive that can be used to represent any identity-related information. 4 | 5 | Claims can be viewed as Soul Bound Tokens (SBTs) on steroids. Similar to SBTs, the ownership is cryptographically guaranteed allowing control and reusability across platforms. Differently to SBTs, claims live off-chain ensuring users privacy over their Personal Identifiable Information. 6 | 7 | 1.**Update the required dependencies.** 8 | 9 | ```bash 10 | go get github.com/iden3/go-iden3-core 11 | ``` 12 | 13 | 2.**Specify the credential schema**. 14 | 15 | A [credential schema](./claim-schema.md) defines how a set of data must be stored inside a claim. In this example, we will use a schema called [`KYCAgeCredential`](https://github.com/iden3/claim-schema-vocab/blob/main/schemas/json-ld/kyc-v2.json-ld). According to this schema the birthday is stored in the first index slot of the [claim data structure](https://docs.iden3.io/protocol/claims-structure), while the documentType is stored in the second data slot. 16 | 17 | The hash of the schema is generated from the content of the schema document following the [Claim Schema Generation Rules](../../protocol/claim-schema.md). For our example, the hash of the schema is: *`2e2d1c11ad3e500de68d7ce16a0a559e`* 18 | 19 | 3.**Create a generic claim.** 20 | 21 | ```go 22 | package main 23 | 24 | import ( 25 | "encoding/json" 26 | "fmt" 27 | "math/big" 28 | "time" 29 | 30 | core "github.com/iden3/go-iden3-core" 31 | ) 32 | 33 | // create basic claim 34 | func main() { 35 | 36 | // set claim expriation date to 2361-03-22T00:44:48+05:30 37 | t := time.Date(2361, 3, 22, 0, 44, 48, 0, time.UTC) 38 | 39 | // set schema 40 | ageSchema, _ := core.NewSchemaHashFromHex ("2e2d1c11ad3e500de68d7ce16a0a559e") 41 | 42 | // define data slots 43 | birthday := big.NewInt(19960424) 44 | documentType := big.NewInt(1) 45 | 46 | // set revocation nonce 47 | revocationNonce := uint64(1909830690) 48 | 49 | // set ID of the claim subject 50 | id, _ := core.IDFromString("113TCVw5KMeMp99Qdvub9Mssfz7krL9jWNvbdB7Fd2") 51 | 52 | // create claim 53 | claim, _ := core.NewClaim(ageSchema, core.WithExpirationDate(t), core.WithRevocationNonce(revocationNonce), core.WithIndexID(id), core.WithIndexDataInts(birthday, documentType)) 54 | 55 | // transform claim from bytes array to json 56 | claimToMarshal, _ := json.Marshal(claim) 57 | 58 | fmt.Println(string(claimToMarshal)) 59 | } 60 | ``` 61 | 62 | Here is what the claim would look like: 63 | ``` 64 | ["3613283249068442770038516118105710406958","86645363564555144061174553487309804257148595648980197130928167920533372928","19960424","1","227737944108667786680629310498","0","0","0"] 65 | ``` 66 | 67 | In particular, the first 4 values of the claim represent the `Index` part of the claim while the last 4 represent the `Value`. 68 | ``` 69 | Index: 70 | [ 71 | "3613283249068442770038516118105710406958", // Claim Schema hash 72 | "86645363564555144061174553487309804257148595648980197130928167920533372928", // ID Subject of the claim 73 | "19960424", // First index data slot stores the date of birth 74 | "1" // Second index data slot stores the document type 75 | ] 76 | 77 | Value: 78 | [ 79 | "227737944108667786680629310498", // Revocation nonce 80 | "0", 81 | "0", // first value data slot 82 | "0" // second value data slot 83 | ] 84 | ``` 85 | 86 | The data stored in the first position of the Index contains a reference to the schemahash of the claim. As defined in the [`KYCAgeCredential` schema](https://github.com/iden3/claim-schema-vocab/blob/main/schemas/json-ld/kyc-v2.json-ld), the value birthday must be stored in the first index data slot while the second index stores the documentType. Other schemas may provide different rules on where to store the data. 87 | 88 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L63) 89 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/getting-started.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The first part of the tutorial walks you through the core components of Iden3 protocol necessary to initiate an identity and design claims: 4 | 5 | - [Baby Jubjub Keypair](babyjubjub.md) 6 | - [Sparse Merkle Tree](mt.md) 7 | - [Claim](claim/generic-claim.md) 8 | - [Identity](identity/identity-types.md) 9 | 10 | Having understood the primitives you will be then able to start [**issuing claims**](./issue-claim-overview.md). 11 | 12 | > The tutorial follows a cascade strucuture: each step relies on the data and code snippets generated in the previous ones. The full executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/tree/main/issuer-protocol) 13 | 14 | ## Iden3 Go Core Libraries 15 | 16 | - [Go Iden3 core](https://github.com/iden3/go-iden3-core) - Identity core primitives 17 | - [Go Iden3 crypto](https://github.com/iden3/go-iden3-crypto) - Implementation of Poseidon hash and Baby JubJub Elliptic curve 18 | - [Go Merkletree sql](https://github.com/iden3/go-merkletree-sql) - Implementation of Sparse Merkle tree 19 | - [Go circuits](https://github.com/iden3/go-circuits) - A library for transforming the go-core primitives to json inputs for identity circuits 20 | 21 | ## Other useful resources 22 | 23 | - [Circom2](https://docs.circom.io/) - A compiler written in Rust for compiling circuits written in the Circom language 24 | - [SnarkJS](https://github.com/iden3/snarkjs) - An npm package that contains APIs to generate and validate zk proofs generated by Circom 25 | - [GoLang Intro](https://go.dev/doc/) - Recommended if you are not proficient with GoLang 26 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/example/go.mod: -------------------------------------------------------------------------------- 1 | module example 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/iden3/go-iden3-core v1.0.2 7 | github.com/iden3/go-merkletree-sql/v2 v2.0.6 8 | ) 9 | 10 | require ( 11 | github.com/iden3/go-iden3-crypto v0.0.15 // indirect 12 | github.com/mr-tron/base58 v1.2.0 // indirect 13 | golang.org/x/sys v0.6.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "math/big" 7 | 8 | core "github.com/iden3/go-iden3-core" 9 | "github.com/iden3/go-merkletree-sql/v2" 10 | "github.com/iden3/go-merkletree-sql/v2/db/memory" 11 | ) 12 | 13 | // Generate the three identity trees 14 | func main() { 15 | 16 | ctx := context.Background() 17 | 18 | // Create empty Claims tree 19 | clt, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 20 | 21 | // Create empty Revocation tree 22 | ret, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 23 | 24 | // Create empty Roots tree 25 | rot, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 26 | 27 | // Generate a proper BJJ key pair here and provide x & y coordinates 28 | x := big.NewInt(1) 29 | y := big.NewInt(2) 30 | 31 | authClaim, err := core.NewClaim(core.AuthSchemaHash, 32 | core.WithIndexDataInts(x, y), 33 | core.WithRevocationNonce(0)) 34 | 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | // Get the Index and the Value of the authClaim 40 | hIndex, hValue, _ := authClaim.HiHv() 41 | 42 | // add auth claim to claims tree with value hValue at index hIndex 43 | clt.Add(ctx, hIndex, hValue) 44 | 45 | // print the roots 46 | fmt.Println(clt.Root().BigInt(), ret.Root().BigInt(), rot.Root().BigInt()) 47 | } 48 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/identifier.md: -------------------------------------------------------------------------------- 1 | # Identifier 2 | 3 | Each identity has one main identifier - **Genesis ID**, and can have many additional identifiers - [Identity Profiles](./identity-profile.md). 4 | 5 | Genesis ID is: 6 | 7 | - Permanent: it remains the same for the entire existence of an identity. 8 | - Unique: No two identities can have the same ID. 9 | 10 | The Genesis ID is deterministically [calculated](https://docs.iden3.io/protocol/spec/#genesis-id) from the Genesis State. 11 | 12 | **Calculate Genesis ID from the Genesis State** 13 | 14 | ```go 15 | package main 16 | 17 | import ( 18 | "fmt" 19 | 20 | core "github.com/iden3/go-iden3-core" 21 | ) 22 | 23 | // Retrieve ID 24 | func main() { 25 | 26 | id, _ := core.IdGenesisFromIdenState(core.TypeDefault, state.BigInt()) 27 | 28 | fmt.Println("ID:", id) 29 | 30 | } 31 | ``` 32 | 33 | Here is what the output would look like: 34 | 35 | ```bash 36 | ID: 11AbuG9EKnWVXK1tooT2NyStQod2EnLhfccSajkwJA 37 | ``` 38 | 39 | The identity gets published, together with all other identities, inside the struct `StateLib.Data internal _stateData` state variable, which is part of the `State` [contract](../../contracts/contracts.md). While the ID remains constant, the Identity State will get updated as soon as the identity adds or revokes claims in its trees. 40 | 41 | > No Personal Identifiable Information (PPI) is stored on-chain. From the IdState is impossible to retrieve any information (represented as claim) stored inside the Identity Claims Tree 42 | 43 | The Identity State hasn't been published on-chain yet as claims haven't been issued yet. This is the subject of the next section. 44 | 45 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L133) 46 | 47 | ## Genesis State 48 | 49 | There are two [identity types](./identity-types.md), which differ in many aspects and because of this have two different ways to generate the Genesis State: 50 | 51 | 1. **Regular Identity**: The Genesis State is the initial Identity State (hash of Identity SMT Roots). This identity is primarily controlled by Baby JubJub keys. At least one BJJ public key must be added into Claims Tree during the identity creation. 52 | 2. **Ethereum-controlled Identity**: The Genesis State is derived from the Ethereum address. This identity is primarily controlled by Ethereum account from which its Genesis State and Identifier are derived. 53 | 54 | ## W3C DID representation 55 | 56 | Decentralized Identifier can be generated from the ID by prepending the DID method and network parameters in the following way: 57 | 58 | ``` 59 | did:::: 60 | ``` 61 | 62 | Example of valid DIDs: 63 | 64 | 1. 65 | ``` 66 | did:iden3:eth:mainnet:11AbuG9EKnWVXK1tooT2NyStQod2EnLhfccSajkwJA 67 | ``` 68 | where: 69 | * `did:iden3` is DID method 70 | * `eth:mainnet` is the network identifier for the Ethereum Mainnet 71 | * `id`, base58-encoded id. 72 | 73 | 2. 74 | ``` 75 | did:polygonid:polygon:mumbai:2qCU58EJgrEMAMwdTehMoxtopwP1gKXCEt9GGeVDaG 76 | ``` 77 | where: 78 | * `did:polygonid` is DID method 79 | * `polygon:mumbai` is the network identifier for the Mumbai testnet 80 | * `id`, base58-encoded id. 81 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/identity-profile.md: -------------------------------------------------------------------------------- 1 | # Identity Profiles 2 | 3 | Identity Profiles allow users to hide their [`Genesis Identifier`](identifier.md) during interactions. Instead, users will be identified by their [`Identity Profile`](../../protocol/spec.md#identity-profiles-new). 4 | 5 | An Identity Profile is generated by hashing the `id` with a `profileNonce` (a random number generated by the identity owner). 6 | 7 | ``` 8 | profileHash = hash(genesisId, profileNonce) 9 | 10 | profileId = idType + profileHashCut + checksum 11 | ``` 12 | where: 13 | * idType - identifier of DID method and blockchain network & subnetwork, 2 bytes 14 | * profileHashCut - first 27 bytes of profileHash, 27 bytes 15 | * checksum - control checksum, 2 bytes 16 | * profileNonce - random number generated by the identity owner, 31 bytes (actually max ~253 bits to fit into the zk prime field) 17 | 18 | ```go 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | "math/big" 24 | 25 | core "github.com/iden3/go-iden3-core" 26 | ) 27 | 28 | // Generate Identity Profile from Genesis Identifier 29 | func main() { 30 | 31 | id, _ := core.IDFromString("11BBCPZ6Zq9HX1JhHrHT3QKUFD9kFDEyJFoAVMptVs") 32 | 33 | profile, _ := core.ProfileID(id, big.NewInt(50)) 34 | 35 | fmt.Println(profile.String()) 36 | 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/identity-state.md: -------------------------------------------------------------------------------- 1 | # Identity State 2 | 3 | Each Identity State (and therefore Identity) consists of [three Sparse Merkle Trees](https://docs.iden3.io/protocol/spec/#identity-state-update): 4 | 5 | - **Claims Tree** - a tree that contains the claims issued by that particular identity. 6 | - **Revocations Tree** - a tree that contains the revocation nonces of the claims that have been revoked by that particular identity. 7 | - **Roots Tree** - a tree that contains the history of the tree roots from the Claims tree. 8 | 9 | Claims issued by an identity are added to the Claims tree (we'll see in a while why that's not always the case). The position of a claim inside the Sparse Merkle Tree is determined by the hash of the claim's `Index` while the value stored inside the leaf will be the hash of the claim's `Value`. 10 | 11 | An identity must issue at least one `Auth Claim` to operate properly. This is the first claim that is issued by an identity and that **must** be added to the `ClT`. 12 | 13 | An Identity State is a hash of the roots of these three merkle trees. 14 | 15 | `IdState = Hash(ClR || ReR || RoR)` where: 16 | 17 | - `Hash`: Poseidon Hash Function 18 | - `ClR`: Claims Tree Root 19 | - `ReR`: Revocation Tree Root 20 | - `RoR`: Roots Tree Root 21 | 22 | The identity state gets stored on-chain and represents the status of an identity at a certain point in time. 23 | 24 |
25 | 26 |
Identity State Diagram
27 |
28 | 29 | ## Code Examples 30 | 31 | 32 | ### Create identity trees and add authClaim 33 | 34 | ```go 35 | package main 36 | 37 | import ( 38 | "context" 39 | "fmt" 40 | 41 | core "github.com/iden3/go-iden3-core" 42 | "github.com/iden3/go-merkletree-sql/v2" 43 | "github.com/iden3/go-merkletree-sql/v2/db/memory" 44 | ) 45 | 46 | // Generate the three identity trees 47 | func main() { 48 | 49 | ctx := context.Background() 50 | 51 | // Create empty Claims tree 52 | clt, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 53 | 54 | // Create empty Revocation tree 55 | ret, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 56 | 57 | // Create empty Roots tree 58 | rot, _ := merkletree.NewMerkleTree(ctx, memory.NewMemoryStorage(), 40) 59 | 60 | authClaim := core.NewClaim(core.AuthSchemaHash, 61 | core.WithIndexDataInts(X, Y), 62 | core.WithRevocationNonce(0)) 63 | 64 | // Get the Index and the Value of the authClaim 65 | hIndex, hValue, _ := authClaim.HiHv() 66 | 67 | // add auth claim to claims tree with value hValue at index hIndex 68 | clt.Add(ctx, hIndex, hValue) 69 | 70 | // print the roots 71 | fmt.Println(clt.Root().BigInt(), ret.Root().BigInt(), rot.Root().BigInt()) 72 | } 73 | ``` 74 | 75 | We've just generated the three identity trees! For now, we only added a leaf corresponding to the `authClaim` to the Claims tree `ClT`. The Revocation tree `ReT` and the `RoT` remain empty. In particular: 76 | 77 | - The revocation tree gets updated whenever an identity decides to revoke a claim. For instance, if a user decides to rotate her keys, then she generates a key pair, creates a new authClaim with the public key from the key pair and adds the claim to the Claims Tree. Now the user can revoke the old public key, so she adds an entry to the Revocation Tree with the claim revocation nonce as an Index and zero as a Value. 78 | - The Roots Tree gets updated whenever the Identity Claims Tree root gets updated. 79 | 80 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L104) 81 | 82 | 83 | **Retrieve the Identity State `IdState`** 84 | 85 | ```go 86 | package main 87 | 88 | import ( 89 | "fmt" 90 | "github.com/iden3/go-merkletree-sql" 91 | ) 92 | 93 | // Retrieve Identity State 94 | func main() { 95 | 96 | // calculate Identity State as a hash of the three roots 97 | state, _ := merkletree.HashElems( 98 | clt.Root().BigInt(), 99 | ret.Root().BigInt(), 100 | rot.Root().BigInt()) 101 | 102 | fmt.Println("Identity State:", state) 103 | 104 | } 105 | ``` 106 | 107 | Here is what the output would look like: 108 | 109 | ```bash 110 | Identity State: 111 | 20698226269617404048572275736120991936409000313072409404791246779211976957795 112 | ``` 113 | 114 | > The very first identity state of an identity is defined as **Genesis State** 115 | 116 | Every verification inside Iden3 protocol is executed against the Identity State. For instance, to prove the validity of a specific claim issued by A to B (in case if the claims gets added to the claims tree): 117 | 118 | - user B needs to produce a merkle proof of the existence of that claim inside user's Claims Tree 119 | - user B needs to produce a merkle proof of non-existence of the corresponding revocation nonce inside user's Revocations Tree 120 | 121 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L124) 122 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/identity-types.md: -------------------------------------------------------------------------------- 1 | # Identity Types 2 | 3 | In iden3 protocol there are two types of identities, which differ in many aspects: 4 | 5 | 1. **Regular Identity**, which is generated from three identity trees and controlled by Baby JubJub keys. 6 | 2. **Ethereum-controlled Identity**, which is primarily controlled by Ethereum account from which it's Genesis State and 7 | Identifier are derived. 8 | 9 | ## Regular Identity 10 | 11 | Regular identity is created from three merkle trees (Genesis State is a hash of Identity SMT Roots). This identity is 12 | primarily controlled by Baby JubJub keys. At least one BJJ public key must be added into Claims Tree during the identity 13 | creation. 14 | 15 | ``` 16 | genesisState = Hash(ClaimsTreeRoot || RevocationsTreeRoot || RootsTreeRoot) 17 | 18 | genesisId = idType + genesisStateCut + checksum 19 | ``` 20 | 21 | where: 22 | 23 | * idType - identifier of DID method and blockchain network & subnetwork, 2 bytes 24 | * genesisStateCut - first 27 bytes of genesisState, 27 bytes 25 | * checksum - control checksum, 2 bytes 26 | 27 | ### Limitations of Regular Identity 28 | 29 | Currently, adding an Ethereum key to the Claims Tree and using it for authentication and proving is not practical, because 30 | it's very computationally expensive to verify ECDSA signatures in zk-circuits. Also, having the user's Ethereum address 31 | there's no way to get a user identifier from it, so dApps would need to authenticate the user additionally to get the 32 | identifier. 33 | 34 | ## Ethereum-controlled Identity 35 | 36 | This type of identity was introduced to overcome some of the limitations of regular identity - allow using Ethereum 37 | accounts to authenticate, prove statements and control identity (perform state transitions). That eliminates strict 38 | requirement to have Baby JubJub keys. 39 | 40 | Genesis state is always zero for Ethereum-controlled Identity. 41 | 42 | Genesis Identifier is directly derived from the Ethereum address in the following way: 43 | 44 | ``` 45 | genesisId = idType + zeroPadding + ethAddress + checksum 46 | ``` 47 | 48 | where: 49 | 50 | * idType - identifier of DID method and blockchain network & subnetwork, 2 bytes 51 | * zeroPadding - 7 zero bytes 52 | * ethAddress - Ethereum address of controlling Ethereum account, 20 bytes 53 | * checksum - control checksum, 2 bytes 54 | 55 | Example: 56 | 57 | ``` 58 | idType: 0212 // DID method: PolygonID; Network: Polygon Mumbai 59 | + 60 | ethAddress: 0x0dcd1bf9a1b36ce34237eeafef220932846bcd82 61 | + 62 | // uint16 sum of bytes of the byte string: idType + zeroPadding + ethAddress. 63 | // Note that the bytes of the uint16 are in reversed order, e.g. if sum is 0x0a45 then checksum is 0x450a 64 | checksum: 450a 65 | === 66 | id: 0212000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd82450a (bytes) 67 | id: 2qCU58EJgrELSJT6EzT27Rw9DhvwamAdbMLpePztYq (base58) 68 | ``` 69 | 70 | Note that identifiers in Smart Contracts are represented using little-endian byte order (because of how zero-knowledge proofs are verified), so the identifier for smart contracts is reversed: 71 | ``` 72 | id: 000a4582cd6b84320922efafee3742e36cb3a1f91bcd0d000000000000001202 (bytes32, reversed byte order with appended zero byte in the front) 73 | id: 18148217572028590643859359173103611579212110941630801448409877263163593218 (uint256, same reversed bytes but encoded as uin256) 74 | ``` 75 | 76 | 77 | ### DID representation 78 | 79 | Canonical form is the same as for Regular Identity: 80 | 81 | ``` 82 | did:polygonid:polygon:mumbai:2qCU58EJgrELSJT6EzT27Rw9DhvwamAdbMLpePztYq 83 | ``` 84 | 85 | ### Authentication Method 86 | 87 | Ethereum-controlled Identity can be authenticated by verifying if the Identifier matches the Ethereum account that sent a 88 | transaction (`msg.sender`). 89 | 90 | In case Ethereum-controlled Identity performs State Transition and adds BJJ keys to it's Claims Tree, it can also 91 | perform authentication by ZKP using BJJ keys. 92 | 93 | ### Ethereum Account Types 94 | 95 | Ethereum has two types of accounts: 96 | 97 | * Smart Contract (SC) 98 | * Externally Owned Account (EOA) 99 | 100 | ### Smart Contract (SC) 101 | 102 | Smart contracts can control identity and perform state transitions. In case such a smart contract manages its identity 103 | trees on chain, it becomes an OnChain Identity. 104 | 105 | ### Externally Owned Account (EOA) 106 | 107 | Note: The EOA-controlled identity is not yet fully supported in iden3 protocol (WIP). 108 | 109 | ### Limitations of Ethereum-controlled Identity 110 | 111 | * Only one Ethereum account can control identity 112 | * No support for Ethereum key rotation and revocation. It's embedded into Identifier directly 113 | * No support for profiles. It's not possible to hide genesis identifier and use profile instead when using Ethereum key 114 | to authenticate & prove statements. 115 | * No support for credential issuance with BJJ signature, only SMT proofs available. 116 | 117 | The last two limitations can be overcome by adding BJJ keys to Claims Tree and performing state transition. Afterwards, it's possible to use BJJ keys for authentication, proving & credential issuance. See [Identity Type Comparison](#identity-type-comparison) for more details. 118 | 119 | ## Identity Type Comparison 120 | 121 | | Aspect | Regular Identity | Ethereum-controlled Identity | Ethereum-controlled Identity with added BJJ keys | 122 | |------------------------------------|-----------------------------|------------------------------|------------------------------------------------------------| 123 | | Genesis State | Identity State | Ethereum Address | Ethereum Address | 124 | | Keys | BJJ keys | Ethereum Account (SC or EOA) | Ethereum Account (SC or EOA) + BJJ keys | 125 | | Authentication Method (off-chain) | JWZ with ZKP using BJJ keys | JWS with Ethereum Signature | JWS with Ethereum Signature or JWZ with ZKP using BJJ keys | 126 | | Authentication Method (on-chain) | ZKP using BJJ keys | Ethereum Account | Ethereum Account or ZKP using BJJ keys | 127 | | State Transition Method | ZKP using BJJ keys | Ethereum Account | \* Ethereum Account or ZKP using BJJ keys | 128 | | Key Rotation Support | Only BJJ keys | Can add BJJ keys | Only BJJ keys | 129 | | Profiles Support | Yes | No | Yes | 130 | | Credential Issuance with MTP proof | Yes | Yes | Yes | 131 | | Credential Issuance with Sig proof | Yes | No | Yes | 132 | | Credential Revocation Support | Yes | Yes | Yes | 133 | 134 | \* Take into account the data consistency warnings described in relevant [OnChain Identity](onchain-identity.md#state-data-consistency-warning) section. 135 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/identity/onchain-identity.md: -------------------------------------------------------------------------------- 1 | # OnChain Identity 2 | 3 | OnChain Identity is an identity that is controlled by a Smart Contract. It is a special case of Ethereum-controlled Identity. 4 | 5 | The OnChain Identity manages its own identity trees on chain. It can issue credentials (by adding them to its claims tree), revoke them and perform state transitions. 6 | 7 | ## OnChain Issuer 8 | 9 | The OnChain Issuer is a special case of OnChain Identity, which is used to issue credentials to other identities. 10 | 11 | ## Libraries and Contracts 12 | 13 | * [IdentityLib.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/IdentityLib.sol) - library that can create identity, manage trees, issue/revoke credentials and perform state transitions. 14 | * [GenesisUtils.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/GenesisUtils.sol) - library that can generate id from Ethereum address or identity state and verify it. 15 | * [IdentityBase.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/IdentityBase.sol) - base contracts to build OnChain Identity / Issuer Contracts with required public interfaces implemented. 16 | 17 | ## Benefits & Possible Use Cases 18 | 19 | * Transparent and Auditable: smart contract code defines who can do what, e.g. who can issue credentials, who can rotate keys, etc. 20 | * Trustless / Trust-Minimized (depending on smart contract business logic): no need to trust a third party to perform user verification correctly and issue credentials only to verified users. Correct behavior is enforced by the smart contract. 21 | * Smart Governance: for example DAO may vote to issue credential (give executive/validator role) to a specific user, or to revoke credentials of a specific user. 22 | * Private and portable web3 reputation: think of proving balance, possession of NFTs or trade volumes without disclosing your address. 23 | * Self-Issuance: user can go to the smart contract and issue herself a credential, that is valid and verifiable just like credentials issued by regular (off-chain) issuers. 24 | * ZK-Self-Issuance: it's also possible to issue credentials with private web2 data. A user can create credentials on its own device and prove that it's created correctly and follows the rules of a Smart Contract and a specific ZK Circuit. For example, a user gets digitally signed data from its own biometric document, generates a verifiable credential out of it and proves that the resulting VC corresponds to the data, and data itself is properly signed with valid government keys. Then only the hash of the credential together with zero-knowledge proof is sent on-chain to be verified and added to OnChain Identity's Claims Tree. In this way, private data never leaves the user's device and it gets valid credential. 25 | 26 | ## Onchain Identity State Transition 27 | 28 | OnChain Identity State Transition is performed by calling `transitState` function of the `IdentityLib` library. The function calculates new state from the claims, revocations and roots tree roots. 29 | It also verifies whether roots were changed since the last state transition as a result of possible claims/revocations added to the relevant trees. 30 | 31 | As the last step, it calls `transitStateGeneric` function of the `State` contract, which is designed to be generic and in the future will be used to perform state transitions of other types of identities and/or other transition logic. 32 | 33 | #### State data consistency warning 34 | 35 | Please be aware that both the `State` contract and `IdentityLib` do not impose any restrictions on users who wish to perform a state transition using `IdentityLib.transitState()` and then subsequently perform another state transition using the `State.transitState()` contract with BJJ keys authentication. This sequence of actions has the potential to create inconsistent state data between the `State` and On-chain Identity smart contracts. It is the responsibility of the on-chain identity owner to take steps to prevent such situations from occurring. 36 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/issue-claim-overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | In the last section, you have initiated an identity and created different types of claims. As of now, the claims haven’t been published or issued in any way. The goal of this section is to *issue* claims so that the receiver can start using them within other applications. 4 | 5 | Starting from the same [core claim](./claim/generic-claim.md) there are two ways of issuing it: via Signature or via Merkle tree. 6 | 7 | ## Via Signature 8 | 9 | The claim gets signed by the issuer using her private key. The proof of issuance is the signature itself. This action doesn’t modify the identity state of the issuer, so there’s no on-chain transaction involved. 10 | 11 | ## Via Merkle tree 12 | 13 | The claim gets added to the issuer’s [Claims Tree](./identity/identity-state.md). This action modifies the structure of the Merkle Tree and, therefore, the state has to be updated with the new Merkle root. The **state transition** involves an on-chain transaction. In this case, the proof of issuance is the membership of the claim itself inside the issuer’s Claims Tree. 14 | 15 | ## Similarities and Differences 16 | 17 | Both approaches guarantee that the claim is tamper-resistant. The private zk-based verification of the claim is equally guaranteed in both cases. 18 | 19 | The process of updating the on-chain state (in the case of Merkle Tree (MT)) may take around 10/20 seconds, so the claim could not be immediately available to use for the user. Instead, with Signature (S), the claim is immediately ready for use. The biggest advantage of MT approach is that it offers timestamp proof of an identity state: a user could always prove the existence of a claim at a specific point in time according to the block number when it was added to the issuer tree. Naturally, this comes at a cost: the gas fees needed to update the state (458,228 gas used inside the transaction). No on-chain transactions take place in the case of S. 20 | A further element of difference regards the uniqueness of the claim: in the MT case, there couldn’t be two claims with the same index [Claim Data Structure](https://docs.iden3.io/protocol/claims-structure). This is guaranteed by the characteristic of [Sparse Merkle Tree](./mt.md). With S, an issuer could sign as many claims they want with the same index. Let’s consider an example: a passport issued as a claim. This claim contains the identifier of the passport owner inside its index. MT approach provides a cryptographic guarantee that the issuer cannot duplicate the passport by issuing a claim with the same identifier. S doesn’t. 21 | 22 | > Note: This section describes the claim issuance on a protocol level. The way in which issuers and users’ wallets communicate and transfer claims is defined on a platform level. This will be the subject of Polygon ID light issuer tutorial coming out this Autumn. 23 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/json-ld-credential.md: -------------------------------------------------------------------------------- 1 | # W3C Verifiable Credentials 2 | 3 | ### JSON-LD Credential and Claim 4 | 5 | A [Claim](../protocol/claims-structure.md) is the core data structure used by Iden3 to represent information. A claim by itself doesn't contain enough meaningful information to be read, understood and consumed (e.g. by the wallet). For example, it doesn't tell anything about the meaning of values stored inside the data slots. 6 | 7 | The JSON-LD credential is able to pack the information contained in a claim in a more human-readable way. Furthermore, a JSON-LD credential does not only contain the claim itself but other proofs needed for the subject of the claim needs to consume the claim with other Verifiers. 8 | 9 | Let's anaylise what is a JSON-LD Credential with a practical example. The first tab contains a claim attesting to someone's date of birth (this is the same claim generated in the [Generic Claim Section](./claim/generic-claim.md)). The second tab contains the corresponding JSON-LD Credential of type `KYCAgeCredential`. 10 | 11 | === "Core Claim Format" 12 | 13 | ```go 14 | Index: 15 | { 16 | "3613283249068442770038516118105710406958", // Claim Schema hash 17 | "86645363564555144061174553487309804257148595648980197130928167920533372928", // ID Subject of the claim 18 | "19960424", // First index data slot stores the date of birth 19 | "1" // Second index data slot stores the document type 20 | } 21 | 22 | Value: 23 | { 24 | "227737944108667786680629310498", // Revocation nonce 25 | "0", 26 | "0", // first value data slot 27 | "0" // second value data slot 28 | } 29 | ``` 30 | 31 | === "JSON-LD Credential" 32 | 33 | ``` json 34 | { 35 | "id": "eca80230-6ed1-4251-8fe9-3c0204ba10ba", 36 | "@context": [ 37 | "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/iden3credential.json-ld", 38 | "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld" 39 | ], 40 | "@type": [ 41 | "Iden3Credential" 42 | ], 43 | "expiration": "2361-03-22T00:44:48+05:30", 44 | "updatable": false, 45 | "version": 0, 46 | "rev_nonce": 1909830690, 47 | "credentialSubject": { 48 | "birthday": 19960424, 49 | "documentType": 1, 50 | "id": "113TCVw5KMeMp99Qdvub9Mssfz7krL9jWNvbdB7Fd2", 51 | "type": "KYCAgeCredential" 52 | }, 53 | "credentialStatus": { 54 | "id": "https://fe03-49-248-235-75.in.ngrok.io/api/v1/claims/revocation/status/1909830690", 55 | "type": "SparseMerkleTreeProof" 56 | }, 57 | "subject_position": "index", 58 | "credentialSchema": { 59 | "@id": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld", 60 | "type": "KYCAgeCredential" 61 | }, 62 | "proof": [ 63 | { 64 | "@type": "BJJSignature2021", 65 | "issuer_data": { 66 | "id": "113TCVw5KMeMp99Qdvub9Mssfz7krL9jWNvbdB7Fd2", 67 | "state": { 68 | "claims_tree_root": "ea5774fac8d72478d4db8a57a46193597bb61475fc9e72bdc74a0ce35aa85518", 69 | "value": "5ccc30d5d0360170a29188d5a907381098801a1ab09003493d9833fa4d95271f" 70 | }, 71 | "auth_claim": [ 72 | "304427537360709784173770334266246861770", 73 | "0", 74 | "6610201945487752676983171932113332232608162355365546060896064454271869708127", 75 | "11380100573862532536254569563965305187461805636461289256869908267462627351172", 76 | "0", 77 | "0", 78 | "0", 79 | "0" 80 | ], 81 | "mtp": { 82 | "existence": true, 83 | "siblings": [] 84 | }, 85 | "revocation_status": "https://fe03-49-248-235-75.in.ngrok.io/api/v1/claims/revocation/status/1909830690" 86 | }, 87 | "signature": "5e1356754a061c9f691496a4b4bd4cab5d1d74eb835ef7575fc6b2c1e8b4311dab9e2b544f9c3f4701324b1e0b3a8c09de22425de9038c2a08f98f6963f17102" 88 | } 89 | ] 90 | } 91 | ``` 92 | 93 | 94 | The core claim (1st tab) contains a limited set of information such as the schema hash, the identity subject of the claim, the data slots stored inside the claim (in this case the date of birth) and the revocation nonce of the claim. It's worth noting that the claim by itself doesn't say anything about the meaning of this content. How can someone infer that that value refers to a birthday? Furthermore the claim doesn't reveal information about the issuer, nor whether it has been revoked or not. All these set of extended information about a claim are included in the JSON-LD format in order to allow other parties to consume and understand the content of a claim. 95 | 96 | In particular the first part of the JSON-LD Credential contains the details of the claim: 97 | 98 | - `id` namely the identifier of the credential itself 99 | - `context`, as per JSON-LD spec is used to establish a description of the common terms that we will be using such as "expiration", "updatable" .... In particular the first one is standard for iden3 credential vocabulary while the second is specific to this type of claim. 100 | - `type` defines the type of the credential itself, when dealing with iden3 claim the credential should always be named Iden3Credential 101 | - `expriation` which is a field contained in the claim in v_0(specifically, the hash of this value is contained in the claim) 102 | - `updatable` which is a field contained in the claim in i_0 103 | - `version` which is a field contained in the claim in i_0 104 | - `rev_nonce` which is a field contained in the claim in v_0 105 | - `credentialSubject` which contains all the details about the subject of the claim and the information contained in the claim regarding the subject 106 | - `credentialStatus` which contains a url to fetch the revocation status of the claim 107 | - `subject_position` indicates whether the identifier of the subject of the claim should be stored inside index data slot (i_1) or value data slot (v_1) 108 | - `credentialSchema` defines the [Schema](./claim/claim-schema.md) of the claim itself 109 | 110 | The second part ofthe JSON-LD Credential contains a cryptographic proof that the credentials was issued by a specific issuer: 111 | 112 | - `@type` indicates the way the proof was generated. It can be either "BJJSignature2021" or "Iden3SparseMerkleProof" 113 | - `issuer_data` contains all the data related to the issuer of the claim. Including its [identifier](./identity/identifier.md) (`id`), its [identity state](./identity/identity-state.md) value at the time of the issuance (`id`), its [Auth Claim](./claim/auth-claim.md) (`auth_claim`), the merkle tree proof that the Auth Claim belongs to the Claims Tree at the time of the issuance (`mtp`) and, lastly, a url to fetch the revocation status of the issuer's auth claim (`revocation_status`) 114 | - `signature` contains the signed claim [generated using the issuer's private key](./signature-claim/signature.md) 115 | 116 | > In this case the claim was issued by signature, in the case of claim of Merkle Tree Type the proof array would also contain a second value, namely the `Iden3SparseMerkleProof` of inclusion of the issued claim inside the issuer's Claims Tree 117 | 118 | The subject of the claim will store the JSON-LD format credential inside their wallet. Starting from the details contained inside the Credential he/she will be able to generate zk proofs and present it to Verifiers. 119 | 120 | - [] Why we need that JSON-LD Credential? 121 | - [] How am I able to get from the credential to core-claim? Is it gonna match? Is it also able to parse revocation nonce etcetera? 122 | - [] Does the parsing also work in reverse? From claim to VC? 123 | - [] What is `signature`? 124 | - [] Add part to explain how to parse the VC into a core claim 125 | 126 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/mt.md: -------------------------------------------------------------------------------- 1 | # Sparse Merkle Tree 2 | 3 | A Merkle Tree or a hash tree is a cryptographically verifiable data structure where every "leaf" node of the tree contains the cryptographic hash of a data block, and every non-leaf node contains the cryptographic hash of its child nodes. 4 | 5 | The Merkle Trees used in Iden3 protocol are Sparse. In [Sparse Merkle Trees](https://blog.iden3.io/sparse-merkle-trees-visual-introduction.html) each data block has an index associated to it that determines its position as leaf inside the tree. 6 | 7 | In addition to inheriting the tamper-resistance and proof-of-membership properties from standard merkle trees, a Sparse Merkle Tree has other features: 8 | 9 | - The insert order of data blocks doesn't influence the final Merkle Tree Root. A data block `A` with index `1` and a data block `B` with index `4` will always occupy the same positions inside the tree despite the insert order 10 | - Some leaves remain empty 11 | - It's possible to prove that certain data is not included in the tree (**proof of non-membership**) 12 | 13 | A Sparse Merkle Tree is the core data structure used in Iden3 protocol to represent an identity. In particular, the leaves of a Sparse Merkle Tree are the claims issued by an identity. 14 | 15 | 1.**Update the required dependencies.** 16 | 17 | ```bash 18 | go get github.com/iden3/go-merkletree-sql 19 | ``` 20 | 21 | 2.**Design a Sparse Merkle Tree.** 22 | 23 | 24 | ```go 25 | package main 26 | 27 | import ( 28 | "context" 29 | "fmt" 30 | "math/big" 31 | 32 | merkletree "github.com/iden3/go-merkletree-sql" 33 | "github.com/iden3/go-merkletree-sql/db/memory" 34 | ) 35 | 36 | // Sparse MT 37 | func main() { 38 | 39 | ctx := context.Background() 40 | 41 | // Tree storage 42 | store := memory.NewMemoryStorage() 43 | 44 | // Generate a new MerkleTree with 32 levels 45 | mt, _ := merkletree.NewMerkleTree(ctx, store, 32) 46 | 47 | // Add a leaf to the tree with index 1 and value 10 48 | index1 := big.NewInt(1) 49 | value1 := big.NewInt(10) 50 | mt.Add(ctx, index1, value1) 51 | 52 | // Add another leaf to the tree 53 | index2 := big.NewInt(2) 54 | value2 := big.NewInt(15) 55 | mt.Add(ctx, index2, value2) 56 | 57 | // Proof of membership of a leaf with index 1 58 | proofExist, value, _ := mt.GenerateProof(ctx, index1, mt.Root()) 59 | 60 | fmt.Println("Proof of membership:", proofExist.Existence) 61 | fmt.Println("Value corresponding to the queried index:", value) 62 | 63 | // Proof of non-membership of a leaf with index 4 64 | proofNotExist, _, _ := mt.GenerateProof(ctx, big.NewInt(4), mt.Root()) 65 | 66 | fmt.Println("Proof of membership:", proofNotExist.Existence) 67 | } 68 | ``` 69 | 70 | A data block inside the tree is represented by a `index` and a `value`. The index represents the position in the tree and it must be unique. The value represents the associated value stored in the tree. 71 | 72 | The `GenerateProof` method shown above allows verifying the membership of a leaf in the merkle tree starting from its root. 73 | 74 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L32) 75 | 76 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/signature-claim/signature.md: -------------------------------------------------------------------------------- 1 | # Signature Claim Issuance 2 | 3 | To issue a claim by signing it, the only thing needed is access to your [Baby Jubjub private key](../babyjubjub.md). 4 | 5 | 1.**Retrieve hash of Claim's Index and hash of Claim's Value** 6 | 7 | Starting from the [Generic Claim](../claim/generic-claim.md) previously created the first step we first need to extract the hash of its index and the hash of its value 8 | 9 | ```go 10 | claimIndex, claimValue := claim.RawSlots() 11 | indexHash, _ := poseidon.Hash(core.ElemBytesToInts(claimIndex[:])) 12 | valueHash, _ := poseidon.Hash(core.ElemBytesToInts(claimValue[:])) 13 | ``` 14 | 15 | 2.**Hash the `indexHash` and the `valueHash` together and sign it** 16 | 17 | ```go 18 | // Poseidon Hash the indexHash and the valueHash together to get the claimHash 19 | claimHash, _ := merkletree.HashElems(indexHash, valueHash) 20 | 21 | // Sign the claimHash with the private key of the issuer 22 | claimSignature := babyJubjubPrivKey.SignPoseidon(claimHash.BigInt()) 23 | ``` 24 | 25 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L139) 26 | 27 | 28 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/state-transition/new-identity-state.md: -------------------------------------------------------------------------------- 1 | # Add Claim to the Claims Tree 2 | 3 | At t=0, the situation is the same left from the *Identity* section of tutorial. Our identity is still at the `Genesis State`. The Claims Tree contains only the `authClaim`. The revocation and roots trees are empty. The state hasn't been published on-chain yet. 4 | 5 | Let's see what happens when if we decide to add a new claim to the Claims Tree. 6 | 7 | 1.**Update the required dependencies.** 8 | 9 | ```bash 10 | go get github.com/iden3/go-circuits 11 | ``` 12 | 13 | 2.**Add a new claim and fetch the new state** 14 | 15 | ```go 16 | package main 17 | 18 | import ( 19 | "encoding/hex" 20 | "fmt" 21 | "math/big" 22 | 23 | "github.com/iden3/go-circuits" 24 | core "github.com/iden3/go-iden3-core" 25 | "github.com/iden3/go-iden3-crypto/poseidon" 26 | "github.com/iden3/go-merkletree-sql" 27 | ) 28 | 29 | // Change Identity State 30 | func main() { 31 | // GENESIS STATE: 32 | 33 | // 1. Generate Merkle Tree Proof for authClaim at Genesis State 34 | authMTPProof, _, _ := clt.GenerateProof(ctx, hIndex, clt.Root()) 35 | 36 | // 2. Generate the Non-Revocation Merkle tree proof for the authClaim at Genesis State 37 | authNonRevMTPProof, _, _ := ret.GenerateProof(ctx, new(big.Int).SetUint64(revNonce), ret.Root()) 38 | 39 | // Snapshot of the Genesis State 40 | genesisTreeState := circuits.TreeState{ 41 | State: state, 42 | ClaimsRoot: clt.Root(), 43 | RevocationRoot: ret.Root(), 44 | RootOfRoots: rot.Root(), 45 | } 46 | // STATE 1: 47 | 48 | // Before updating the claims tree, add the claims tree root at Genesis state to the Roots tree. 49 | rot.Add(ctx, clt.Root().BigInt(), big.NewInt(0)) 50 | 51 | // Create a new random claim 52 | schemaHex := hex.EncodeToString([]byte("myAge_test_claim")) 53 | schema, _ := core.NewSchemaHashFromHex(schemaHex) 54 | 55 | code := big.NewInt(51) 56 | 57 | newClaim, _ := core.NewClaim(schema, core.WithIndexDataInts(code, nil)) 58 | 59 | // Get hash Index and hash Value of the new claim 60 | hi, hv, _ := newClaim.HiHv() 61 | 62 | // Add claim to the Claims tree 63 | clt.Add(ctx, hi, hv) 64 | 65 | // Fetch the new Identity State 66 | newState, _ := merkletree.HashElems( 67 | clt.Root().BigInt(), 68 | ret.Root().BigInt(), 69 | rot.Root().BigInt()) 70 | 71 | // Snapshot of the new tree State 72 | newTreeState := circuits.TreeState{ 73 | State: newState, 74 | ClaimsRoot: clt.Root(), 75 | RevocationRoot: ret.Root(), 76 | RootOfRoots: rot.Root(), 77 | } 78 | 79 | // Sign a message (hash of the genesis state + the new state) using your private key 80 | hashOldAndNewStates, _ := poseidon.Hash([]*big.Int{state.BigInt(), newState.BigInt()}) 81 | 82 | signature := babyJubjubPrivKey.SignPoseidon(hashOldAndNewStates) 83 | 84 | authClaimNewStateIncMtp, _, _ := clt.GenerateProof(ctx, hIndex, newTreeState.ClaimsRoot) 85 | 86 | // Generate state transition inputs 87 | stateTransitionInputs := circuits.StateTransitionInputs{ 88 | ID: id, 89 | OldTreeState: genesisTreeState, 90 | NewTreeState: newTreeState, 91 | IsOldStateGenesis: true, 92 | AuthClaim: authClaim, 93 | AuthClaimIncMtp: authMTPProof, 94 | AuthClaimNonRevMtp: authNonRevMTPProof, 95 | AuthClaimNewStateIncMtp: authClaimNewStateIncMtp, 96 | Signature: signature, 97 | } 98 | 99 | // Perform marshalling of the state transition inputs 100 | inputBytes, _ := stateTransitionInputs.InputsMarshal() 101 | 102 | fmt.Println(string(inputBytes)) 103 | } 104 | ``` 105 | 106 | After issuing a new claim, the claims tree gets modified and, therefore, the Identity State changes. To complete the state transition it is necessary to verify it inside a circuit. The type `StateTransitionInputs` lets us pack the inputs needed to generate a proof while the `InputsMarshal()` function turns it into a json file that can be used directly as State Transition Circuit inputs. These inputs will be used in the next section. 107 | 108 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/blob/main/issuer-protocol/main.go#L156) 109 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/state-transition/on-chain-state-transition-remix.md: -------------------------------------------------------------------------------- 1 | ### Remix 2 | 3 | 1. Connect yout Metamask wallet to Polygon Mumbai Testnet. 4 | 5 | 2. On the [Remix Homepage](https://remix.ethereum.org/), click "Load from GitHub" and import `State.sol` using the link: https://github.com/iden3/contracts/blob/master/contracts/State.sol 6 | 7 | 3. Move to the "Solidity Compiler" section and compile `State.sol`. 8 | 9 | 4. Move to the "Deploy and Run Transaction" section and modify the Environment to "Injected web3". If everything was set correctly, you should see `Custom (80001) network` below the environment drop-down menu.The system prompts you to connect to your MetaMask wallet. Make sure to select the "Mumbai" network on your Metamask before connecting the wallet. 10 | 11 | 5. Make sure that the State contract is selected in the contract drop-down menu and "Load contract from address" adding **0x46Fd04eEa588a3EA7e9F055dd691C688c4148ab3** as contract address. 12 | 13 | 6. Check identity state at T=0. To check the identity state call the getState function on the State.sol passing in your identifier. The identifier is the first public input in the public array returned from the solidity calldata from the previous tutorial. The result is zero as there's no identity state associated with that identifier because the identity state has never been published on-chain (yet!) 14 | 15 | 7. Now update the identity state by calling the `transitState` function on State.sol. 16 | 17 | The outputs generated from the previous tutorial are passed as inputs to the `transitState` function. See the one-to-one mapping between the outputs from state transition and the inputs to the `transitState` function in the diagram below: 18 | 19 |
20 | 21 | 22 |
transitState Function Inputs
23 |
24 | 25 | 8. Check the new state. To check, call the `getState` function again by passing the value of the identifier you used above as an input to the `transitState` function. 26 | 27 | You can see that the console displays a new state: 28 | 29 | `uint256:14531895531750268543323474544059484523319511522635242711319115705040584883009` 30 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/state-transition/on-chain-state-transition.md: -------------------------------------------------------------------------------- 1 | # Verify the Proof On-Chain 2 | 3 | In order to complete the State Transition process it is necessary to verify the proof inside the `State.sol` contract. 4 | 5 | The `transitState` public function of the contract takes the proof generated in the previous section and verifies it on-chain. On verification, the `identities` mapping associated with the `ID` that is executing the transition gets updated. 6 | 7 | ### Hardhat 8 | 9 | 1.**Add Mumbai Network inside your `hardhat.config.js`** 10 | 11 | ```js 12 | networks: { 13 | mumbai: { 14 | url: `${process.env.MUMBAI_RPC_URL}`, 15 | accounts: [`${process.env.MUMBAI_PRIVATE_KEY}`] 16 | } 17 | } 18 | ``` 19 | 20 | 2.**Add [State.sol](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol#L148) contract and its dependencies ([Poseidon.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/Poseidon.sol) and [Smt.sol](https://github.com/iden3/contracts/blob/master/contracts/lib/Smt.sol)) inside the contracts folder** 21 | 22 | 3.**Import the state contract from the existing Mumbai testnet address** 23 | 24 | ```js 25 | const contract = await hre.ethers.getContractAt("State", "0xEA9aF2088B4a9770fC32A12fD42E61BDD317E655"); 26 | ``` 27 | 28 | 4.**Add inputs from the proof generated in the previous section** 29 | 30 | ```js 31 | const id = "0x000a501c057d28c0c50f91062730531a247474274ff6204a4f7da6d4bcb70000" 32 | const oldState = "0x1c057d28c0c50f91062730531a247474274ff6204a4f7da6d4bcb7d23be4d605" 33 | const newState = "0x203034fdafe4563e84962f2b16fefe8ebedb1be5c05b7d5e5e30898d799192fd" 34 | const isOldStateGenesis = "0x0000000000000000000000000000000000000000000000000000000000000001" 35 | 36 | const a = ["0x0c98dbb5bcdc4810a976b9804972c6086e855532740ab2c611fbcf4a5d939f91", "0x1f3b6aa1cfe69a2a3f5e8e7db5ccae0d269fc66be6d0c364469486d5718431ee"] 37 | const b = [["0x21f67821a25f3b0eb008e8aa840706c6dd9c1cff16ec6f138d7745aff350dbbb", "0x255b9f12a90b1f1089af5edcda19fb6d592096f6ba7ce2438ce4ecc48399687d"],["0x1568f9a5a84d72a31b90d26b5035030b0b02544dcba18f0a3740f80b9632942d", "0x28dcba6dd58878a3383fd556d27118a3e905f424d23afa30b71de3ac000822de"]] 38 | const c = ["0x15adbb5f1abe4418a7ea7f876164b57bf70f88183fa7d85406be4cb5f8fee261", "0x04466d6e7131a89fdcf5136b52ed2b52e00755ad77c97bb87e8afa690eeef5e4"] 39 | ``` 40 | 41 | > Note: Do not use these same inputs for the next section of the tutorial. I already executed the State Transition using these inputs, so the transaction will fail. Instead, use the inputs that you locally generated. 42 | 43 | 5.**Execute state transition function** 44 | 45 | ```js 46 | await contract.transitState(id, oldState, newState, isOldStateGenesis, a, b, c); 47 | ``` 48 | 49 | 6.**Fetch identity state after state transition** 50 | 51 | ```js 52 | // Get state of identity without BigNumber 53 | let identityState = await contract.getStateInfoById(id); 54 | 55 | console.log("Identity State after state transition", identityState.id); 56 | // 18221365812082731933036101625854358571814024255404073202903829924181114880 57 | ``` 58 | 59 | Congratulations! You have successfully completed the identity state transition. 60 | 61 | Starting from the identifier, people will be able to track the status of an identity in a timestamped and tamper-proof way. The identifier remains fixed for the entire existence of an identity, while the identity state changes every time an identity gets updated, for example, when issuing or revoking a claim. As we'll see in the next section, every ZK proof generated from an identity will be checked against the identity state published on-chain. 62 | 63 | It is important to underline that: 64 | 65 | - The mapping that associates an identifier with its current identity state is the only piece of information stored on-chain. 66 | - Starting from the identifier and the identity state, it is impossible to retrieve any information stored in the identity trees, for example, reading the content of a claim (which is stored off-chain). 67 | - There is no association between the ECDSA (Elliptical Curve Digital Signature Algorithm) key pair associated with the Ethereum address that executes the State Transition and the Baby Jubjub key pair which is used to control an identity. 68 | 69 | > The executable code can be found [here](https://github.com/0xPolygonID/tutorial-examples/tree/main/hardhat-transit-state) 70 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/state-transition/state-transition-proof.md: -------------------------------------------------------------------------------- 1 | # Generate Proof for State Transition 2 | 3 | The output of the previous tutorial was the result of a locally executed computation by the Identity Owner, namely moving from the genesis state to state 1. 4 | 5 | >What if the person that executed the state transition wasn't actually the Identity Owner? What if the key used to sign the message was revoked? 6 | 7 | To ensure the state transition happens in a trustless way, it must be verified inside a circuit. 8 | 9 | The State Transition inputs generated earlier will be passed into the [State Transition Circuit](../../protocol/main-circuits.md#statetransition) to generate a proof of the executed state transition. 10 | 11 | 1.**Install [Circom and SnarkJS.](https://docs.circom.io/getting-started/installation/#installing-circom)** 12 | 13 | 2.**Clone the repository that contains the compiled circuit** 14 | 15 | ```bash 16 | git clone https://github.com/iden3/tutorial-examples.git 17 | ``` 18 | 19 | This repository contains the `stateTransition` compiled circuit after a trusted setup. 20 | 21 | 3.**Create a .json file with the state transition inputs from the previous tutorial** 22 | 23 | For this, create a file named `input.json` inside the `.stateTransition/stateTransition_js` and then paste the inputs you generated in the previous tutorial. These inputs will be passed to the circuit and will be used to generate the zk proof. 24 | 25 | 4.**Generate the proof** 26 | 27 | From the compiled-circuits folder run: 28 | 29 | ```bash 30 | ./generate.sh stateTransition 31 | ``` 32 | 33 | If everything worked fine, your terminal should display: 34 | 35 | ```bash 36 | [INFO] snarkJS: OK! 37 | ``` 38 | 39 | 5.**Display the proof** 40 | 41 | You should now have 2 new files inside the /stateTransition/stateTransition_js directory, namely proof.json and public.json: 42 | 43 | - `proof.json` contains the actual proof represented by the three arrays `a, b, and c`. It contains all the raw data of the proof that the SnarkJS library uses for verification of the proof. 44 | 45 | - `public.json` is an array of the four elements representing the public inputs of the circuit. These are `userID,oldUserState,newUserState,isOldStateGenesis` 46 | 47 | 6.**Export the proof in the Solidity calldata.** 48 | 49 | The two files from the above step can also be exported as Solidity calldata in order to execute the verification on-chain. From the `stateTransition_js` directory run `snarkjs generatecall`. 50 | 51 | ```bash 52 | snarkjs generatecall 53 | ``` 54 | Here is what the output would look like: 55 | 56 | ```bash 57 | ["0x0c98dbb5bcdc4810a976b9804972c6086e855532740ab2c611fbcf4a5d939f91", "0x1f3b6aa1cfe69a2a3f5e8e7db5ccae0d269fc66be6d0c364469486d5718431ee"],[["0x21f67821a25f3b0eb008e8aa840706c6dd9c1cff16ec6f138d7745aff350dbbb", "0x255b9f12a90b1f1089af5edcda19fb6d592096f6ba7ce2438ce4ecc48399687d"],["0x1568f9a5a84d72a31b90d26b5035030b0b02544dcba18f0a3740f80b9632942d", "0x28dcba6dd58878a3383fd556d27118a3e905f424d23afa30b71de3ac000822de"]],["0x15adbb5f1abe4418a7ea7f876164b57bf70f88183fa7d85406be4cb5f8fee261", "0x04466d6e7131a89fdcf5136b52ed2b52e00755ad77c97bb87e8afa690eeef5e4"],["0x000a501c057d28c0c50f91062730531a247474274ff6204a4f7da6d4bcb70000","0x1c057d28c0c50f91062730531a247474274ff6204a4f7da6d4bcb7d23be4d605","0x203034fdafe4563e84962f2b16fefe8ebedb1be5c05b7d5e5e30898d799192fd","0x0000000000000000000000000000000000000000000000000000000000000001"] 58 | ``` 59 | 60 | The Solidity calldata output represents: 61 | 62 | - `a[2]`, `b[2][2]`, `c[2]`, namely the proof 63 | - `public[4]`, namely the public inputs of the circuit 64 | 65 | In the next tutorial, we shall pass this proof to the State.sol smart contract in order to complete the State Transition function. 66 | -------------------------------------------------------------------------------- /mkdocs/docs/getting-started/state-transition/state-transition.md: -------------------------------------------------------------------------------- 1 | # State Transition 2 | 3 | When an identity adds a new claim to her Claims Tree, the root of the tree and, consequently, the identity state change. The process of moving from one state to another is defined using [**State Transition Function**](https://docs.iden3.io/protocol/spec/#identity-state-transition-function). 4 | 5 | Before performing changing states of identity, State Contract verifies the State Transition Function proof. 6 | 7 | This proof can be: 8 | * A ZK proof generated by the prover using the [State Transition Circuit](../../protocol/main-circuits.md#statetransition) and BJJ keys. 9 | * An Ethereum transaction executed by the identity owner (for [Ethereum-controlled Identities](../identity/identity-types.md#ethereum-controlled-identity)). 10 | 11 | ## ZK State Transition Verifier 12 | 13 | State Contract has `transitState` [smart contract function](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol), which verifies proof of `stateTransition` [circuit](../../protocol/main-circuits.md#statetransition), which represents a set of rules that identity holder needs to follow to complete the state transition such as: 14 | 15 | - The prover is the owner of the identity (checked using a digital signature by the private key corresponding the `authClaim`) 16 | - The `authClaim` of the prover hasn't been revoked. 17 | 18 | The identity state gets updated by calling the `transitState` [smart contract function](https://github.com/iden3/contracts/blob/master/contracts/state/State.sol#L148). To call this function, it is necessary to pass in the proof generated previously. 19 | 20 | ## Ethereum State Transition Verifier 21 | 22 | Ethereum State Transition requires a `msg.sender` of an Ethereum transaction to match identifier provided. 23 | 24 | ## State Transition Process 25 | 26 | After successful verification, the `identities` mapping gets updated associating the `ID` with a new `IdState`, and GIST gets updated with the new `IdState` value. 27 | 28 | This tutorial is split in 3 parts: 29 | 30 | 1. [Add Claim to the Claims Tree](./new-identity-state.md) 31 | 2. [Generate ZK Proof for State Transition](./state-transition-proof.md) 32 | 3. [Verify ZK Proof On-Chain](./on-chain-state-transition.md) 33 | 34 | > Note: The Identity State Transition happens not only when an identity adds a new claim to the Claims Tree, but also when a claim gets updated or revoked (by adding it to the revocation tree). 35 | -------------------------------------------------------------------------------- /mkdocs/docs/guides/centralized-login.md: -------------------------------------------------------------------------------- 1 | # Centralized Login Use Case 2 | 3 | ## Overview 4 | 5 | This document will guide you through the steps required to integrate iden3's technology into your application's login. 6 | 7 | ## Introduction 8 | 9 | Iden3 is a complete decentralized identity management solution that allows users to leverage their pre-existing validated identities. This helps these users prove that they are who they claim to be; thus saving them the hassle of registering with each service (each requiring a validated identification) individually. One of the direct applications of the iden3 technology is to allow web services to reuse these identities for logging into their portals. 10 | 11 | The diagram below shows the steps of the backend process; follow these to enable a user gain access to your application using the iden3 identity system once the s/he has requested to log in. 12 | 13 | ![image0](images/centralized_login_protocol.png) 14 | Iden3 provides an SDK to take care of requesting and verifying the identity so that the users can be authenticated. 15 | 16 | ## Platforms Supported 17 | 18 | - **JavaScript:** 19 | 20 | - **Go:** 21 | 22 | ## Pre-requirements 23 | 24 | The minimum requirements for a functional centralized login include: 25 | 26 | 1. The iden3 wallet service has been deployed. 27 | 2. A user attempting to log in has at least one valid identity. 28 | 29 | ## Integration 30 | 31 | A JavaScript reference implementation of how a third-party can integrate the iden3 solution to log in to its application can be found at: 32 | . 33 | In this example, the external service includes a front-end and a back-end server. Let's see how this division into the front-end and the back-end actually works: 34 | 35 | 37 | 38 | ### Front-End 39 | 40 | On the front-end, you need to embed a button to initiate the login process. You will also need to display a QR code that the user can scan to complete the authentication. After the button is pressed, the front-end makes a request to the back-end to start the identity authentication process and waits for the response containing the QR code to be displayed and scanned by the user. 41 | 42 | In the reference implementation, this is achieved by the JavaScript function *getLoginData()*, found in frontend/index.js. This code shows how to: 43 | 44 | 1. Send a request for a new *requestIdenAssert* packet to the centralized application back-end. 45 | 2. Open a WebSocket between the front-end and back-end. 46 | 3. Display a QR code containing the *requestIdenAssert* packet to be signed by iden3's wallet. 47 | 48 | ### Back-End 49 | 50 | #### Generating Requests of Identity Assertion 51 | 52 | On the back-end, you will need to prepare a new API endpoint to handle the *requestIdenAssert()* petitions from the front-end. In the reference implementation, we use *GET/login* by calling the JavaScript function: 53 | 54 | ``` {.sourceCode .javascript} 55 | const signatureRequest = iden3.protocols.login.newRequestIdenAssert(nonceDB, origin, timeout); 56 | ``` 57 | 58 | or the Go function: 59 | 60 | ``` {.sourceCode .c} 61 | requestIdenAssert := NewRequestIdenAssert(nonceDb, origin, timeout) 62 | ``` 63 | 64 | where: 65 | 66 | - **nonceDB** is a NonceDB object generated by calling an API function and stored in a RAM database. 67 | - **origin** is the domain of the emitter of the request, for example, *myweb.com*. 68 | - **timeout** is the timeout in seconds, for example, two minutes (*120s*). 69 | 70 | The nonceDB is obtained by calling the following JavaScript function: 71 | 72 | ``` {.sourceCode .javascript} 73 | const nonceDB = new iden3.protocols.NonceDB(); 74 | ``` 75 | 76 | or the Go function: 77 | 78 | ``` {.sourceCode .c 79 | nonceDb := core.NewNonceDb()} 80 | ``` 81 | 82 | Once you have the *signatureRequest* object, you can return it back to the front-end so that it can be displayed. 83 | 84 | #### Verifying signedPacket 85 | 86 | On the back-end, you will also need to prepare a new API endpoint to handle the responses from the iden3 wallet containing the *signedPacket*. In the reference implementation, we use *POST /login* to allow the walled to send the signed data. 87 | 88 | To perform the verification in the newly added endpoint you just need to call the *iden3js* library: 89 | 90 | ``` {.sourceCode .javascript} 91 | const verified = iden3.protocols.login.verifySignedPacket(nonceDB, origin, signedPacket); 92 | ``` 93 | 94 | or the *go-iden3* library: 95 | 96 | ``` {.sourceCode .C} 97 | verified, err := signedPacketVerifier. 98 | VerifySignedPacketIdenAssert(signedPacket, nonceDB, origin) 99 | ``` 100 | 101 | where: 102 | 103 | - **nonceDB** is the NonceDB object generated earlier. 104 | - **origin** is the domain of the emitter of the request, for example, *myweb.com*. 105 | - **signedPacket** is the signed packet sent by the iden3 wallet. 106 | - **verified** is *null* if verification fails. 107 | 108 | ## SDK Installation 109 | 110 | ### iden3js 111 | 112 | #### Installation 113 | 114 | ``` {.sourceCode .bash} 115 | npm install --save @iden3/iden3 116 | ``` 117 | 118 | #### Import 119 | 120 | ``` {.sourceCode .javascript} 121 | const iden3 = require('iden3'); 122 | ``` 123 | 124 | ### go-iden3 125 | 126 | #### Installation 127 | 128 | ``` {.sourceCode .bash} 129 | go get github.com/iden3/go-iden3 130 | ``` 131 | 132 | #### Import 133 | 134 | ``` {.sourceCode .c} 135 | import { "github.com/iden3/go-iden3/services/signedpacketsrv" } 136 | ``` 137 | -------------------------------------------------------------------------------- /mkdocs/docs/guides/circom-and-snarkjs.md: -------------------------------------------------------------------------------- 1 | # How to Use Circom and SnarkJS? 2 | 3 | Hello and welcome!! 4 | 5 | In this guide, we'll explain how to create your first [zero-knowledge Snark](https://github.com/iden3/docs/blob/master/mkdocs/docs/basics/key-concepts.md#zk-snarks) circuit using [Circom](https://docs.circom.io) and [SnarkJS](https://github.com/iden3/snarkjs). 6 | 7 | [Circom](https://circom.iden3.io) is a library that allows you to build circuits to be used in zero-knowledge proofs. 8 | 9 | While [SnarkJS](https://github.com/iden3/snarkjs) is an independent implementation of the zk-SNARK protocol (fully written in JavaScript), Circom is designed to work with SnarkJS. In other words, any circuit you build in Circom can be used in SnarkJS. 10 | 11 | We'll start by covering various techniques to write circuits; then we shall move on to creating and verifying a proof off-chain, and finally, finish it off by repeating this process on-chain (on Ethereum). 12 | 13 | If you have zero knowledge about zero-knowledge 😋 or are unsure about what a zk-SNARK is, we recommend you read [this page](../../basics/key-concepts) first. 14 | 15 | To get started, click [here](https://docs.circom.io/getting-started/installation/). 16 | 17 | -------------------------------------------------------------------------------- /mkdocs/docs/guides/images/centralized_login_protocol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/guides/images/centralized_login_protocol.png -------------------------------------------------------------------------------- /mkdocs/docs/guides/images/circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/guides/images/circuit.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/GIST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/GIST.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/iden3-icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/iden3-icon2.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/iden3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/iden3.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/identity-state-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/identity-state-diagram.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/identity_state_transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/identity_state_transition.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/inputs-to-transitState-function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/inputs-to-transitState-function.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/login.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-0.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-1.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-2.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-3.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-4.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-5.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-6.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-7.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-proof-of-membership-visual-8.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-specification-visual-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-specification-visual-0.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-specification-visual-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-specification-visual-1.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-specification-visual-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-specification-visual-2.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-specification-visual-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-specification-visual-3.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-0.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-1.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-1b.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-2.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-3.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/merkle-tree-tamper-resistance-visual-4.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/sparse-merkle-tree-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/sparse-merkle-tree-0.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/sparse-merkle-tree-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/sparse-merkle-tree-1.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/sparse-merkle-tree-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/sparse-merkle-tree-2.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/sparse-merkle-tree-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/sparse-merkle-tree-3.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/sparse-merkle-tree-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/sparse-merkle-tree-4.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/transitState-input-Go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/transitState-input-Go.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/transitState-input-remix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/transitState-input-remix.png -------------------------------------------------------------------------------- /mkdocs/docs/imgs/verifier-user-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/imgs/verifier-user-query.png -------------------------------------------------------------------------------- /mkdocs/docs/index.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 |
5 | 6 | [![Chat on Twitter][ico-twitter]][link-twitter] 7 | [![Chat on Telegram][ico-telegram]][link-telegram] 8 | [![Website][ico-website]][link-website] 9 | 10 | 11 | 12 | 13 | 14 | [ico-twitter]: https://img.shields.io/twitter/url?color=black&label=Iden3&logoColor=black&style=social&url=https%3A%2F%2Ftwitter.com%2Fidenthree 15 | [ico-telegram]: https://img.shields.io/badge/telegram-telegram-black 16 | [ico-website]: https://img.shields.io/website?up_color=black&up_message=iden3.io&url=https%3A%2F%2Fiden3.io 17 | 18 | 19 | [link-twitter]: https://twitter.com/identhree 20 | [link-telegram]: https://t.me/iden3io 21 | [link-website]: https://iden3.io 22 | 23 | 24 | --- 25 | 26 | # Iden3 Docs 27 | 28 | Welcome to the documentation site of the Iden3 project, future-proof tech stack for self-sovereign identity. 29 | 30 | --- 31 | 32 | #
[Iden3 on GitHub](https://github.com/iden3)
33 | 34 | --- 35 | 36 | ## Versatility of applications 37 | 38 | The main idea of the iden3 protocol is that each identity is self-soverign and can issue claims on another identity (which can be for an individual, an organisation or a system/machine). 39 | 40 | This simple and unique characteristics can lead to creation complex adaptive systems and the following use cases: 41 | 42 |
    43 |
  • Decentralised trust models / web-of-trust
  • 44 |
  • Decentralised ID verification / proof-of-personhood
  • 45 |
  • Decentralised voting systems
  • 46 |
  • Interaction with DeFi / dApps / Web3
  • 47 |
  • Decentralised payment identifiers
  • 48 |
  • Private access control
  • 49 |
  • Authentication and authorisation
  • 50 |
  • Signing documents and private messaging
  • 51 |
  • Supply chain and IoT
  • 52 |
  • NFT ownership
  • 53 |
54 | 55 | ## Iden3 protocol libraries 56 | 57 | - **Crypto library ([go-iden3-crypto](https://github.com/iden3/go-iden3-crypto))** 58 |
Implementation of Poseidon hash and Baby JubJub Eliptic curve 59 | 60 | - **Merkle tree sql library ([go-merkletree-sql](https://github.com/iden3/go-merkletree-sql))** 61 |
Implementation of Sparse Merkle tree 62 | 63 | - **Core library ([go-iden3-core](https://github.com/iden3/go-iden3-core))** 64 |
Identity core primitives 65 | 66 | - **Circuits ([circuits](https://github.com/iden3/circuits))** 67 |
Identity circuits 68 | 69 | - **Go-circuits ([go-circuits](https://github.com/iden3/go-circuits))** 70 |
Library for transformation go-core primitives to json inputs for identity circuits 71 | 72 | - **Prover server ([prover-server](https://github.com/iden3/prover-server))** 73 |
Wrapper on snarkjs for ZK proof generation 74 | 75 | - **Authorization library ([go-iden3-auth](https://github.com/iden3/go-iden3-auth))** 76 |
Library for authentication with zkp verification (edited) 77 | -------------------------------------------------------------------------------- /mkdocs/docs/logo-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mkdocs/docs/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/bjjkey.md: -------------------------------------------------------------------------------- 1 | # AuthBJJCredential 2 | 3 | AuthBJJCredential is a primary credential for each identity. It represents an authorization operational key. 4 | Hex of the current auth claim schema is _ca938857241db9451ea329256b9c06e5_. 5 | This claim must be presented in most circuits for identity verification. 6 | 7 | 8 | A Baby Jubjub key uses a specific elliptic curve defined over the large prime subgroup of the BN128 elliptic curve. To know more about the bjj key, you can [visit this page](https://iden3-docs.readthedocs.io/en/latest/_downloads/33717d75ab84e11313cc0d8a090b636f/Baby-Jubjub.pdf). 9 | 10 | X and Y values of the bjj public key are part of the Index data slots [I_2] and [I_3]. 11 | 12 | You can find below an example of a claim entry: 13 | 14 | ``` 15 | Index: 16 | i_0: [ 128 bits] 269270088098491255471307608775043319525 // auth schema (big integer from ca938857241db9451ea329256b9c06e5) 17 | [ 32 bits ] 00010000000000000000 // header flags: first 000 - self claim 1 - expiration is set. 18 | [ 32 bits ] 0 19 | [ 61 bits ] 0 20 | i_1: [ 253 bits] 0 21 | i_2: [ 253 bits] 15730379921066174438220083697399546667862601297001890929936158339406931652649 // x part of BJJ pubkey 22 | i_3: [ 253 bits] 5635420193976628435572861747946801377895543276711153351053385881432935772762 // y part of BJJ pubkey 23 | Value: 24 | v_0: [ 64 bits ] 2484496687 // revocation nonce 25 | [ 64 bits ] 1679670808 // expiration timestamp 26 | [ 125 bits] 0 27 | v_1: [ 253 bits] 0 28 | v_2: [ 253 bits] 0 29 | v_3: [ 253 bits] 0 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/circuits.md: -------------------------------------------------------------------------------- 1 | # Circuits 2 | 3 | ## Template Docs Example 4 | 5 | Let's understand how circuits and templates can be described by their graphs. Just compare the following .circom code with its visual graph displayed underneath. 6 | 7 | The code: 8 | ``` 9 | template Example () { 10 | signal input input1; 11 | signal input input2; 12 | signal input input3; 13 | signal input input4; 14 | signal input input5; 15 | 16 | component template1 = Template1(); 17 | template1.in1 = input1; 18 | template1.in2 = input2; 19 | template1.in3 = input3; 20 | 21 | component template2 = Template2(); 22 | template2.in1 = input3; 23 | template2.in2 = input4; 24 | } 25 | ``` 26 | 27 | The graph: 28 | ```mermaid 29 | graph TB 30 | Input1 --> Template1 31 | Input2 --> Template1 32 | Input3 --> Template1 33 | Input3 --> Template2 34 | Input4 --> Template2 35 | 36 | classDef inputStyle fill:#ecb3ff 37 | class Input1,Input2,Input3,Input4,Input5,Input6,Input7,Input8,Input9 inputStyle 38 | 39 | classDef circuitStyle fill:#b3ffd4,stroke-width:3px; 40 | class Template1,Template2,Template3 circuitStyle; 41 | ``` 42 | 43 | 44 | ## Basic Templates 45 | 46 | Basic templates are not used independently to create circuits but are used as the building blocks for other templates. 47 | 48 | ### checkClaimExists 49 | This circuit checks if a claim exists in the sparse Merkle tree. By "exists", we mean that a value Hv (hash of all values slots) is located by path Hi (hash of all index slots) in the tree. 50 | 51 | ```mermaid 52 | graph TB 53 | claim --> getClaimHiHv 54 | getClaimHiHv -- key --> SMTVerifier[SMTVerifier] 55 | getClaimHiHv -- value --> SMTVerifier 56 | claimMTP -- siblings --> SMTVerifier 57 | treeRoot -- root --> SMTVerifier 58 | 1 -- enabled --> SMTVerifier 59 | zero1[0] -- fnc --> SMTVerifier 60 | zero2[0] -- oldKey --> SMTVerifier 61 | zero3[0] -- oldValue --> SMTVerifier 62 | zero4[0] -- isOld0 --> SMTVerifier 63 | 64 | classDef inputStyle fill:#ecb3ff 65 | class claim,claimMTP,treeRoot inputStyle 66 | 67 | classDef circuitStyle fill:#b3ffd4,stroke-width:3px; 68 | class getClaimHiHv,SMTVerifier circuitStyle; 69 | ``` 70 | 71 | ### checkClaimNonRev 72 | 73 | The circuit checks that the claim does not exist in the sparse Merkle tree. That means that the tree leaf is empty by a path, which is defined by the claim nonce. 74 | 75 | ```mermaid 76 | graph TB 77 | claim --> getNonce 78 | getNonce -- key --> SMTVerifier[SMTVerifier] 79 | 0 -- value --> SMTVerifier 80 | claimMTP -- siblings --> SMTVerifier 81 | treeRoot -- root --> SMTVerifier 82 | 1 -- enabled --> SMTVerifier 83 | zero1[1] -- fnc --> SMTVerifier 84 | noAux -- isOld0 --> SMTVerifier 85 | auxHi -- oldKey --> SMTVerifier 86 | auxHv -- oldValue --> SMTVerifier 87 | 88 | classDef inputStyle fill:#ecb3ff 89 | class claim,claimMTP,treeRoot,noAux,auxHi,auxHv inputStyle 90 | 91 | classDef circuitStyle fill:#b3ffd4,stroke-width:3px; 92 | class getNonce,SMTVerifier circuitStyle; 93 | ``` 94 | 95 | ### checkChallengeSignature 96 | 97 | This circuit checks if the challenge signature is correct. The public key for verification is extracted from the claim. 98 | 99 | ```mermaid 100 | graph TB 101 | claim --> getPubKeyFromClaim 102 | getPubKeyFromClaim -- Ax --> EdDSAPoseidonVerifier 103 | getPubKeyFromClaim -- Ay --> EdDSAPoseidonVerifier 104 | signatureS -- S --> EdDSAPoseidonVerifier 105 | signatureR8X -- R8X --> EdDSAPoseidonVerifier 106 | signatureR8Y -- R8Y --> EdDSAPoseidonVerifier 107 | challenge -- M --> EdDSAPoseidonVerifier 108 | 109 | classDef inputStyle fill:#ecb3ff 110 | class claim,getPubKey,signatureS,signatureR8Y,signatureR8X,challenge inputStyle 111 | 112 | classDef circuitStyle fill:#b3ffd4,stroke-width:3px 113 | class getPubKeyFromClaim,EdDSAPoseidonVerifier circuitStyle 114 | ``` 115 | 116 | ### verifyIdenStateMatchesRoot 117 | 118 | The circuit calculates the identity state from the three Merkle tree roots and checks if it is equal to the expected state. 119 | 120 | ```mermaid 121 | graph TB 122 | claimsTreeRoot --> calcRoot 123 | revTreeRoot --> calcRoot 124 | rootsTreeRoot --> calcRoot 125 | calcRoot --> equal[=] 126 | expectedState ---> equal 127 | 128 | classDef inputStyle fill:#ecb3ff 129 | class claimsTreeRoot,revTreeRoot,rootsTreeRoot,expectedState inputStyle 130 | 131 | classDef circuitStyle fill:#b3ffd4,stroke-width:3px 132 | class calcRoot,equal circuitStyle 133 | ``` 134 | 135 | ### Query 136 | 137 | This circuit checks that an expression within an operator and its value are true. 138 | 139 | For example in="1", operator="4", value=["5","2","3"] is true because "4" is "not in" operator and "1" is not in the ["5","2","3"] array. 140 | 141 | See all the operators in the circuit comments. The circuit graph is not represented here due to complexity. 142 | 143 | ## Functional Templates 144 | 145 | These are the templates that the Iden3 system mostly uses to generate and verify proofs directly. A functional template may use other functional templates as its building blocks. 146 | 147 | ### idOwnershipBySignature 148 | This circuit checks the ownership of a specific identity in the following way: 149 | 150 | 1. The claim with the public key should exist in the claims tree. 151 | 2. The claim with the public key should not be revoked. 152 | 3. The signature of a challenge should be valid. 153 | 4. The state should be equal to "expected" from the blockchain. 154 | 155 | The above criteria enable a verifier to check that the challenge is signed by an identity, which state is timestamped on the blockchain and if it includes the non-revoked claim with the relevant public key. 156 | 157 | ### CredentialAtomicQueryMTP 158 | This circuit checks that an issuer has issued a claim for identity and validates the ownership of that identity in the following manner: 159 | 160 | 1. Checks the identity ownership by idOwnershipBySignature template 161 | 2. Verifies the claim subject, the schema and the expiration time. 162 | 3. Checks if the issuer claim exists in the issuer claims tree. 163 | 4. Checks if the issuer claim is not revoked by an issuer. 164 | 5. Checks if the issuer claim satisfies a query. 165 | 166 | ### CredentialAtomicQuerySig 167 | This circuit checks that an issuer has issued a claim for identity and validates ownership of that identity in the following manner: 168 | 169 | 1. Checks the identity ownership by idOwnershipBySignature template. 170 | 2. Verifies the claim subject, the schema and the expiration time 171 | 3. Checks if the issuer claim exists in the issuer claims tree. 172 | 4. Verifies the claim signature by the issuer. 173 | 5. Verifies if the issuer state matches with the one from the blockchain as the public input. 174 | 6. Checks if the issuer claim satisfies a query. 175 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/claim-schema.md: -------------------------------------------------------------------------------- 1 | # Claim Schema 2 | 3 | In order to reuse claims across different services is necessary to keep consistent data formatting. A Claim Schema encodes the structure of a particular claim by defining a type, the fields that must be included inside a claim, and a description for these fields. 4 | 5 | Schemas are described via JSON-LD documents. A claim issuer could reuse existing claim schemas or create new ones from scratch. 6 | 7 | ## Example: KYCAgeCredential Schema 8 | 9 | - [Github Document](https://github.com/iden3/claim-schema-vocab/blob/main/schemas/json-ld/kyc-v4.jsonld) 10 | 11 | ```json 12 | { 13 | "@context": [ 14 | { 15 | "@version": 1.1, 16 | "@protected": true, 17 | "id": "@id", 18 | "type": "@type", 19 | "KYCAgeCredential": { 20 | "@id": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld#KYCAgeCredential", 21 | "@context": { 22 | "@version": 1.1, 23 | "@protected": true, 24 | "id": "@id", 25 | "type": "@type", 26 | "kyc-vocab": "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/kyc.md#", 27 | "xsd": "http://www.w3.org/2001/XMLSchema#", 28 | "birthday": { 29 | "@id": "kyc-vocab:birthday", 30 | "@type": "xsd:integer" 31 | }, 32 | "documentType": { 33 | "@id": "kyc-vocab:documentType", 34 | "@type": "xsd:integer" 35 | } 36 | } 37 | } 38 | } 39 | ] 40 | } 41 | ``` 42 | 43 | This document describes the schema for a claim of type `KYCAgeCredential`. 44 | The `@id` contains the unique url that contains the JSON-LD Document. 45 | The `kyc-vocab` contains a link to a url with a vocabulary description of the value types stored inside this claim, in this case `birthday` and `documentType`. 46 | The last part of the document contains a reference to the value types `birthday` and `documentType`. Their `@id` corresponds to their description in the kyc-vocab while the `@type` indicates where the data type of each field. In this case, `birthday` is an integer and `documentType` is also an integer. 47 | 48 | ## Schema Hash 49 | 50 | The Schema Hash is a unique identifier for a Claim Schema. It is derived by hashing the string that represents unique identifier `@id` of the Claim Schema type. In the previous example, the hash pre-image is the string `https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld#KYCAgeCredential`. 51 | ` 52 | For example, in the case of the Auth Claim the schema hash would be 53 | 54 | ```golang 55 | var sHash core.SchemaHash 56 | h := Keccak256([]byte("https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld#KYCAgeCredential")) 57 | copy(sHash[:], h[len(h)-16:]) 58 | sHashHex, _ := sHash.MarshalText() 59 | fmt.Println(string(sHashHex)) 60 | ``` 61 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/claims-structure.md: -------------------------------------------------------------------------------- 1 | # Claim Data Structure 2 | 3 | ```mermaid 4 | graph TD 5 | Hi-->i0 6 | Hi-->i1 7 | Hi-->i2 8 | Hi-->i3 9 | 10 | Hv-->v0 11 | Hv-->v1 12 | Hv-->v2 13 | Hv-->v3 14 | 15 | Ht-->Hi 16 | Ht-->Hv 17 | ``` 18 | 19 | ## Common Structure 20 | 21 | A claim always contains a subject, that can be: 22 | 23 | - **Self**: The claim says something about itself. The subject is implicit, and it's the identity that makes claim. 24 | - **OtherIden**: The claim says something about some other identity (identified by other's ID). 25 | - **Object**: The claim says something about an object (identified by the object's ID). 26 | 27 | If the subject is _Self_ - _identity_, sections i_1, v_1 can be empty. 28 | 29 | if the subject is NOT _Self_, the id(OtherIden) of the Identity/Object can be in the Index(i_1) or the Value(v_1) part of the claim. This is encoded in a header bit. 30 | 31 | Other flags contained inside i_0 indicate: 32 | 33 | - Whether the claim is expirable. In that case an expiration date must be added inside v_0 34 | - Whether the claim is updatable. 35 | - Whether the claim is merklized and where the root of the tree is located. It can be either inside i_2 or v_2 36 | 37 | ``` 38 | h_i = H(i_0, i_1, i_2, i_3) 39 | h_v = H(v_0, v_1, v_2, v_3) 40 | h_t = H(h_i, h_v) 41 | ``` 42 | 43 | ``` 44 | Index: 45 | i_0: [ 128 bits ] claim schema 46 | [ 32 bits ] option flags 47 | [3] Subject: 48 | 000: A.1 Self 49 | 001: invalid 50 | 010: A.2.i OtherIden Index 51 | 011: A.2.v OtherIden Value 52 | 100: B.i Object Index 53 | 101: B.v Object Value 54 | [1] Expiration: bool 55 | [1] Updatable: bool 56 | [3] Merklized: data is merklized root is stored in the: 57 | 000: none 58 | 001: C.i Root Index (root located in i_2) 59 | 010: C.v Root Value (root located in v_2) 60 | [24] 0 61 | [ 32 bits ] version (optional?) 62 | [ 61 bits ] 0 - reserved for future use 63 | i_1: [ 248 bits] identity (case b) (optional) 64 | [ 5 bits ] 0 65 | i_2: [ 253 bits] 0 66 | i_3: [ 253 bits] 0 67 | Value: 68 | v_0: [ 64 bits ] revocation nonce 69 | [ 64 bits ] expiration date (optional) 70 | [ 125 bits] 0 - reserved 71 | v_1: [ 248 bits] identity (case c) (optional) 72 | [ 5 bits ] 0 73 | v_2: [ 253 bits] 0 74 | v_3: [ 253 bits] 0 75 | ``` 76 | 77 | ### Claim Schema 78 | Schemas define the type of data inside a claim [link](https://github.com/iden3/docs/blob/master/mkdocs/docs/protocol/spec.md#claims). 79 | 80 | _Index slots_ **i_2**, **i_3** and _value slots_ **v_2**, **v_3** are the data slots for user data. 81 | 82 | #### Index vs Value 83 | **When to Use Index Slots and Value Slots?** 84 | 85 | Claims are stored in the Merkle tree and the hash of the index slots ( hash(i_0, i_1, i_2, i_3) ) is unique for the whole tree. It means that you cannot have two claims with the same index inside the tree. 86 | 87 | As opposite to the index, the values slots could be the same for different claims if their indexes are different. 88 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/non-merklized.md: -------------------------------------------------------------------------------- 1 | # Non-merklized credentials 2 | 3 | ## Motivation 4 | 5 | While Iden3 protocol allows to "merklize" the whole JSON-LD document (transform the document into key-value pairs and put them into a sparse merkle tree for later proving of credential field value in the tree), which removes limits on amount and structure of the credential data, there's still a need to issue a core claim with the data itself. This is particularly useful for onchain issuers, which can’t work with json-ld schemas in smart contracts (for many reasons), and also for use cases when the actual data must be saved for cheaper access inside circuits (e.g. Auth BJJ credential public key representation). 6 | 7 | **Core Concept** 8 | 9 | Non-merklized credentials now can be created relying on JSON-LD schemas. 10 | 11 | Example of such context: `https://schema.iden3.io/core/jsonld/auth.jsonld` 12 | 13 | ```json 14 | { 15 | "@context": [{ 16 | "@version": 1.1, 17 | "@protected": true, 18 | "id": "@id", 19 | "type": "@type", 20 | "AuthBJJCredential": { 21 | "@id": "https://schema.iden3.io/core/jsonld/auth.jsonld#AuthBJJCredential", 22 | "@context": { 23 | "@version": 1.1, 24 | "@protected": true, 25 | "id": "@id", 26 | "type": "@type", 27 | "iden3_serialization": "iden3:v1:slotIndexA=x&slotIndexB=y", 28 | "xsd": "http://www.w3.org/2001/XMLSchema#", 29 | "auth-vocab": "https://schema.iden3.io/core/vocab/auth.md#", 30 | "x": { 31 | "@id": "auth-vocab:x", 32 | "@type": "xsd:positiveInteger" 33 | }, 34 | "y": { 35 | "@id": "auth-vocab:y", 36 | "@type": "xsd:positiveInteger" 37 | } 38 | } 39 | } 40 | }] 41 | } 42 | ``` 43 | 44 | Schema is defined as a schema for non-merklized credentials by utilizing `iden3_serialization` attribute. 45 | 46 | It contains a map string represented mapping, where: 47 | 48 | `iden3:v1` - version of protocol serialization, constant. 49 | 50 | `slotIndexA=x` slotIndexA is index data slot A with index 2 for path to field `x` in credential 51 | 52 | `slotIndexB=y` slotIndexB is index data slot B with index 3 for path to field `y` in credential 53 | 54 | other possible values: 55 | 56 | `slotValueA` slotIndexB is value data slot with index 6 57 | 58 | `slotValueB` slotValueB is value data slot with index 7 59 | 60 | When a user creates a schema, he should choose the slot to put the field. 61 | 62 | Nested structures are supported and path is created using concatenation with `.` e.g for birthday field in the Index Data Slot A mapping entry looks like that: 63 | 64 | `"iden3:v1:slotIndexA=passportInfo.birthday"` 65 | 66 | ```json 67 | { 68 | "@context": [ 69 | { 70 | "@version": 1.1, 71 | "@protected": true, 72 | "id": "@id", 73 | "type": "@type", 74 | "Passport": { 75 | "@id": "uuid:urn:229a9afc-4aad-48e4-b113-bf2ca6f3a98f", 76 | "@context": { 77 | "@version": 1.1, 78 | "@protected": true, 79 | "id": "@id", 80 | "type": "@type", 81 | "kyc-vocab": "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/kyc.md#", 82 | "xsd": "http://www.w3.org/2001/XMLSchema#", 83 | "passportInfo": { 84 | "@id": "kyc-vocab:passportInfo", 85 | "@context": { 86 | "@version": 1.1, 87 | "@protected": true, 88 | "kyc-vocab": "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/kyc.md#", 89 | "xsd": "http://www.w3.org/2001/XMLSchema#", 90 | "id": "@id", 91 | "type": "@type", 92 | "birthday": { 93 | "@type": "xsd:integer", 94 | "@id": "kyc-vocab:birthday" 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | ] 102 | } 103 | ``` 104 | 105 | **Important**: 106 | 107 | 1. Fields in index slots make influence on the uniqueness of the claim in the clams tree of issuer, data in the value slots - don’t. 108 | 2. Data Slots number is 4, so there is a restriction to have only 4 fields for non-merklized credentials. 109 | 110 | Meanwhile `@type` filed for each field must contain one of the supported primitive types, so value can be written according to the data type. 111 | 112 | List of supported data types: 113 | 114 | ```json 115 | XSD namespace { 116 | Boolean = 'http://www.w3.org/2001/XMLSchema#boolean', 117 | Integer = 'http://www.w3.org/2001/XMLSchema#integer', 118 | NonNegativeInteger = 'http://www.w3.org/2001/XMLSchema#nonNegativeInteger', 119 | NonPositiveInteger = 'http://www.w3.org/2001/XMLSchema#nonPositiveInteger', 120 | NegativeInteger = 'http://www.w3.org/2001/XMLSchema#negativeInteger', 121 | PositiveInteger = 'http://www.w3.org/2001/XMLSchema#positiveInteger', 122 | DateTime = 'http://www.w3.org/2001/XMLSchema#dateTime', 123 | Double = 'http://www.w3.org/2001/XMLSchema#double' 124 | } 125 | ``` 126 | 127 | Libraries that support non-merklized credentials: 128 | https://github.com/iden3/go-schema-processor/releases/tag/v2.0.1 129 | https://github.com/0xPolygonID/js-sdk/releases/tag/v1.1.0 130 | 131 | To create non-merklized credential in go-schema-processor / JS-sdk merklized Root Position must be set to None (default value) and ld context must contain `iden3_serialization` attribute. 132 | 133 | ```golang 134 | processor.CoreClaimOptions{ 135 | .., 136 | MerklizedRootPosition: verifiable.CredentialMerklizedRootPositionNone, 137 | ... 138 | } 139 | ``` 140 | 141 | If context contains serialization attribute but MerklizedRootPosition is set to Index / Value error will be thrown. 142 | 143 | In case context doesn’t contain serialization attribute and MerklizedRootPosition is set to Index / Value. Merkle root will be written to corresponding position. If the MerklizedRootPosition is set to None Merkle root will be written to Index. 144 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/querylanguage.md: -------------------------------------------------------------------------------- 1 | # ZK Query Language 2 | 3 | ## Goal of the ZK Query Language 4 | 5 | The initial idea is to have a generic circuit with the possibility to do a verification based on user-claims. As circuit setup is not a trivial task and especially, the trusted setup is a challenging thing for regular developers, we have to provide a simple generic query language based on the generic prebuilt circuits. 6 | 7 | The use of the Query Language should not be limited to specific atomic circuits; it must be extendable to other circuits too. 8 | 9 | ## Syntax 10 | 11 | The first version is set to support only these operations: *>, <, =, in and notin*. Later on, this list could be extended. 12 | 13 | ***Comparison Operations*** 14 | 15 | - \> greater than 16 | - < less than 17 | - = equal to 18 | - notin - matches none of the values 19 | - in - matches one of the values 20 | 21 | > *We have to use some syntax instead of raw signs as it will be inconvenient to use signs such as <, >, and = in JS. For example, $eq can be used instead of = , $gt can be used instead of >,and so on.* 22 | > 23 | 24 | ***Simple Operations*** 25 | 26 | ```json 27 | { : { $eq: } } - equal 28 | { : { $gt: } } - greater than 29 | { : { $lt: } } - less than 30 | { : { $nin: [,] } } 31 | { : { $in: [,] } } 32 | ``` 33 | 34 | For atomic claims, these operations could cover a lot of use-cases. 35 | 36 | ## Atomic Circuit 37 | 38 | > The first implementation will cover only simple atomic verification of one field. It means that we will do query requests only to one data field. But we have to do all the required service verifications too such as check ownership, revocation, expiration, etc. 39 | > We also need to include some additional attributes specific to the identity: 40 | 41 | - Schemas List 42 | - List of Trusted Issuers 43 | - Challenge 44 | 45 | *Example: A simple query* 46 | 47 | ```json 48 | { 49 | "circuit_id": "attrQuery", 50 | "type": "zkp", 51 | "rules": { 52 | "query": [ 53 | { 54 | "allowedIssuers": [ 55 | "115zTGHKvFeFLPu3vF9Wx2gBqnxGnzvTpmkHPM2LCe" 56 | ], 57 | "schema": [ 58 | { 59 | "url": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld", 60 | "type": "KYCAgeCredential" 61 | } 62 | ], 63 | "challenge": 12345678, 64 | "req": { 65 | "birthdate": { 66 | "$lt": 20000101 67 | } 68 | } 69 | } 70 | ] 71 | } 72 | } 73 | ``` 74 | 75 | 76 | where: 77 | 78 | - *allowedIssuers*: A list of issuers whom the verifier trusts. 79 | - *schema*: A list of schemas that claims can use for proof generation. 80 | - *challenge*: Used to verify that the provided proof belongs to the existing user session. 81 | - *req*: A query request to the circuit. 82 | 83 | *Example: Multiple requests in one query* (WIP) 84 | 85 | ```json 86 | { 87 | "circuit_id": "atomicQueryMTP", 88 | "type": "zkp", 89 | "rules": { 90 | "query": [ 91 | { 92 | "allowedIssuers": [ 93 | "115zTGHKvFeFLPu3vF9Wx2gBqnxGnzvTpmkHPM2LCe" 94 | ], 95 | "schema": [ 96 | { 97 | "url": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld", 98 | "type": "KYCAgeCredential" 99 | } 100 | ], 101 | "challenge": 12345678, 102 | "req": { 103 | "birthdate": { 104 | "$lt": 20000101 105 | } 106 | } 107 | }, 108 | { 109 | "allowedIssuers": [ 110 | "115zTGHKvFeFLPu3vF9Wx2gBqnxGnzvTpmkHPM2LCe" 111 | ], 112 | "schema": [ 113 | { 114 | "type": "KYCCountryOfResidenceCredential", 115 | "url": "ipfs://QmP8NrKqoBKjmKwMsC8pwBCBxXR2PhwSepwXx31gnJxAbP" 116 | } 117 | ], 118 | "challenge": 12345678, 119 | "req": { 120 | "country": { 121 | "$nin": [ 122 | 840, 123 | 123 124 | ] 125 | } 126 | } 127 | } 128 | ] 129 | } 130 | } 131 | ``` 132 | 133 | 134 | A query circuit should accept query requests and perform the following mandatory verifications. 135 | 136 | **Mandatory Verifications** 137 | 138 | - Verifying the claim Id ownership (proof is generated by identity, which is the subject of the claim). 139 | - Verifying that the claim is not revoked. 140 | - Verifying that the claim is not expired. 141 | - Verifying that the identity key is not revoked. 142 | 143 | **Query** 144 | 145 | - Apply query request 146 | 147 | **Optional** 148 | 149 | - Check schema. 150 | - Check the issuer of the claim. 151 | 152 | > In some cases, *schema* and *issuer* are not important and therefore, we can have the possibility to omit these fields. 153 | 154 | **List of Signals for Circuit** 155 | 156 | ***Id Ownership Signals***: 157 | 158 | ``` 159 | signal input id; 160 | signal input hoIdenState; 161 | 162 | signal input hoClaimsTreeRoot; 163 | signal input authClaimMtp[IdOwnershipLevels]; 164 | signal input authClaim[8]; 165 | 166 | signal input hoRevTreeRoot; 167 | signal input authClaimNonRevMtp[IdOwnershipLevels]; 168 | signal input authClaimNonRevMtpNoAux; 169 | signal input authClaimNonRevMtpAuxHi; 170 | signal input authClaimNonRevMtpAuxHv; 171 | 172 | signal input hoRootsTreeRoot; 173 | 174 | signal input challenge; 175 | signal input challengeSignatureR8x; 176 | signal input challengeSignatureR8y; 177 | signal input challengeSignatureS; 178 | ``` 179 | 180 | ***Claim Signals***: 181 | 182 | ``` 183 | signal input claimSchema; 184 | signal input claim[8]; 185 | signal input claimIssuanceMtp[IssuerLevels]; 186 | signal input claimIssuanceClaimsTreeRoot; 187 | signal input claimIssuanceRevTreeRoot; 188 | signal input claimIssuanceRootsTreeRoot; 189 | signal input claimIssuanceIdenState; 190 | signal input issuerID; 191 | ``` 192 | 193 | ***Verify Claim Revocation Statuses***: 194 | 195 | ``` 196 | signal input claimNonRevMtp[IssuerLevels]; 197 | signal input claimNonRevMtpNoAux; 198 | signal input claimNonRevMtpAuxHi; 199 | signal input claimNonRevMtpAuxHv; 200 | signal input claimNonRevIssuerClaimsTreeRoot; 201 | signal input claimNonRevIssuerRevTreeRoot; 202 | signal input claimNonRevIssuerRootsTreeRoot; 203 | signal input claimNonRevIssuerState; 204 | ``` 205 | 206 | ***Query Requests***: 207 | 208 | ``` 209 | signal input slotIndex; // index of field slot in the claim 210 | signal input value[valueArraySize]; // value for check 211 | signal input operator; // >,<, =,in, notin operations of CQL 212 | ``` 213 | 214 | ***Public Inputs***: 215 | 216 | ```json 217 | challenge, 218 | id, 219 | hoIdenState, 220 | issuerID, 221 | claimIssuanceIdenState, 222 | claimSchema, 223 | slotIndex, 224 | operator, 225 | value, 226 | timestamp 227 | 228 | ``` 229 | 230 | ## Proof Request Workflow 231 | 232 | **Verifier (User)** 233 | 234 | 1. The verifier prepares a proof by requesting a query to the atomic circuit. 235 | *Request*: 236 | 237 | ```json 238 | { 239 | "circuit_id": "attrQuery", 240 | "type": "zkp", 241 | "rules": { 242 | "query": [ 243 | { 244 | "allowedIssuers": [ 245 | "115zTGHKvFeFLPu3vF9Wx2gBqnxGnzvTpmkHPM2LCe" 246 | ], 247 | "schema": [ 248 | { 249 | "url": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld", 250 | "type": "KYCAgeCredential" 251 | } 252 | ], 253 | "challenge": 12345678, 254 | "req": { 255 | "birthdate": { 256 | "$lt": 20000101 257 | } 258 | } 259 | } 260 | ] 261 | } 262 | } 263 | ``` 264 | 265 | 2. The user parses a proof request and performs the necessary checks: 266 | 1. The circuit is known. 267 | 2. The schema is known. 268 | 3. Claims by the specified issuer persist in the wallet. 269 | 4. Get the issuer public state for key non-revocation proof. 270 | 5. Prepare inputs for the circuit: 271 | 1. Prepare ownership / claim / issuer / query inputs. 272 | 2. Use schema to resolve field position in the claim. 273 | 6. Generate ZK proof. 274 | 7. Create proof-sharing response protocol message and send it to the verifier. 275 | 276 | **Flow Diagram**: 277 | 278 | ![verifier-user-query.png](../imgs/verifier-user-query.png) 279 | 280 | 281 | ## Next Steps (future enhancements) 282 | 283 | 1. Make it possible to query multiple fields from the same schema, still, it is limited to four available slots, two indexes, and two values. With this combination, we can cover the more advanced use cases. 284 | 2. Support more query operations. 285 | 3. Fields combinations. 286 | 4. Claim combinations. 287 | 5. Represent JSON-LD document as a tree and store root as a claim. Extend verifications to this new schema. Do an atomic query verification. 288 | 6. Extended query schema with multifield verifications from JSON-LD. 289 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/template-circuits.md: -------------------------------------------------------------------------------- 1 | # Template Circuits 2 | 3 | The template circuits are not are not used independently inside Iden3 protocols but rather as a building blocks inside the main circuits. 4 | 5 | Note: not all the templates are described here but only a few of them. Check [Iden3 Circuits](https://github.com/iden3/circuits) and [Iden3 Circomlib](https://github.com/iden3/circomlib) to see all the templates. 6 | 7 | ## idOwnershipBySignature 8 | 9 | - [**Github**](https://github.com/iden3/circuits/blob/master/circuits/lib/idOwnershipBySignature.circom) 10 | 11 | #### Inputs 12 | 13 | | Input | Description | 14 | | ----------- | ----------- | 15 | | userState | Identity State of the prover | 16 | | userClaimsTreeRoot | Prover's Claims Tree Root | 17 | | userAuthClaimMtp[nLevels] | Merkle Tree Proof of Auth Claim inside Prover's Claims tree | 18 | | userAuthClaim[8] | Prover's Auth Claim | 19 | | userRevTreeRoot | Prover's Revocation Tree Root | 20 | | userAuthClaimNonRevMtp[nLevels]| Merkle Tree Proof of non membership of Auth Claim inside Prover's Revocation Tree | 21 | | userAuthClaimNonRevMtpNoAux | Flag that indicates whether to check the auxiliary Node | 22 | | userAuthClaimNonRevMtpAuxHi | Auxiliary Node Index | 23 | | userAuthClaimNonRevMtpAuxHv | Auxiliary Node Value | 24 | | userRootsTreeRoot | Prover's Roots Tree Root | 25 | | challenge | Message to be signed by the prover | 26 | | challengeSignatureR8x | Signature of the challenge (Rx point) | 27 | | challengeSignatureR8y | Signature of the challenge (Ry point) | 28 | | challengeSignatureS | Signature of the challenge (S point) | 29 | 30 | #### Scope 31 | 32 | - Verifies that the `signature` was performed by the key contained in the `authClaim` and performs further verification on the auth claim using the [`VerifyAuthClaimAndSignature(nLevels)`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/treeUtils.circom#L136) template 33 | - The `state` generated by hashing the three roots should match the expected state from the blockchain (or be the genesis state) using the [`checkIdenStateMatchesRoots()`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/treeUtils.circom#L72) template 34 | 35 | ## VerifyAuthClaimAndSignature 36 | 37 | - [**Github**](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/treeUtils.circom#L136) 38 | 39 | #### Inputs 40 | 41 | | Input | Description | 42 | | ----------- | ----------- | 43 | | claimsTreeRoot | Prover's Claims Tree Root | 44 | | authClaimMtp[nLevels] | Merkle Tree Proof of Auth Claim inside Prover's Claims tree | 45 | | authClaim[8] | Prover's Auth Claim | 46 | | revTreeRoot | Prover's Revocation Tree Root | 47 | | userAuthClaimNonRevMtp[nLevels]| Merkle Tree Proof of non membership of Auth Claim inside Prover's Revocation Tree | 48 | | userAuthClaimNonRevMtpNoAux | Flag that indicates whether to check the auxiliary Node | 49 | | userAuthClaimNonRevMtpAuxHi | Auxiliary Node Index | 50 | | userAuthClaimNonRevMtpAuxHv | Auxiliary Node Value | 51 | | challenge | Message to be signed by the prover | 52 | | challengeSignatureR8x | Signature of the challenge (Rx point) | 53 | | challengeSignatureR8y | Signature of the challenge (Ry point) | 54 | | challengeSignatureS | Signature of the challenge (S point) 55 | 56 | #### Scope 57 | 58 | - The schema hash of the claim must match the expected AUTH_SCHEMA_HASH (hardcoded inside the circuit). Verification performed using the [`verifyCredentialSchema()`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/claimUtils.circom#L151) template 59 | - The authClaim exists inside the claims tree root by using the [`checkClaimExists()`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/treeUtils.circom#L27) template 60 | - The authClaim hasn't been revoked, namely verifies that the authClaim is not included inside the revocation tree root, using the [`checkClaimNotRevoked()`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/treeUtils.circom#L47) template 61 | - Verifies that the signature on the challenge has been performed by the publickey contained in the authClaim using the [`checkDataSignatureWithPubKeyInClaim()`](https://github.com/iden3/circuits/blob/master/circuits/lib/utils/claimUtils.circom#L187) template 62 | 63 | -------------------------------------------------------------------------------- /mkdocs/docs/protocol/zklogin.md: -------------------------------------------------------------------------------- 1 | # Server-side Login (ZKP Login) 2 | 3 | ## Introduction 4 | 5 | Iden3 is a Self-Sovereign Identity (SSI) solution that allows users to leverage their pre-existing validated identities. With SSI, they are able to prove they are who they claim to be based on the zero-knowledge proofs. One of the direct applications of the iden3 technology is to allow web applications to reuse these identities for logging into their portals. 6 | 7 | 8 | ## Login Workflow 9 | 10 | ![Login Workflow](../imgs/login.png) 11 | 12 | In a simple example, an application requests a user identifier; this is done through the zero-knowledge proof (zk proof) generation. The server generates an authentication request. 13 | 14 | _Auth request_ 15 | 16 | ```json 17 | { 18 | "type": "https://iden3-communication.io/authorization-request/v1", 19 | "data": { 20 | "callbackUrl": "https://test.com/callbackurl", 21 | "audience": "1125GJqgw6YEsKFwj63GY87MMxPL9kwDKxPUiwMLNZ", 22 | "scope": [ 23 | { 24 | "circuit_id": "auth", 25 | "type": "zeroknowledge", 26 | "rules": { 27 | "challenge": 12345 28 | } 29 | } 30 | ] 31 | } 32 | } 33 | ``` 34 | 35 | Shown above is an example of an authorization request. Scope field is a set of objects that describes an array of proofs that must be generated on a user device and presented later. 36 | Each scope member has a unique definition of a circuit that must be used and a set of rules (public inputs) that must be applied. 37 | 38 | This message can be delivered to a user through different communication channels: QR code, email, deep-linking, etc. 39 | On scanning, mobile needs to implement the following: 40 | 41 | 1. Parse the authorization request and understand which proof handler it should use. 42 | 2. Resolve the verifier identifier if required. 43 | 3. Generate proofs using a specific handler. It can be a signature proof or a zero-knowledge proof. 44 | 4. Prepare an authentication response message. 45 | 46 | On mobile, a user generates the ZK proof using [auth](https://github.com/iden3/circuits/blob/master/circuits/lib/authentication.circom) circuit that will prove identity ownership, and send the response to the callback URL. 47 | 48 | 49 | _Auth response_ 50 | 51 | ```json 52 | { 53 | "type": "https://iden3-communication.io/authorization-response/v1", 54 | "data": { 55 | "scope": [ 56 | { 57 | "type": "zeroknowledge", 58 | "circuit_id": "auth", 59 | "pub_signals": [ 60 | "371135506535866236563870411357090963344408827476607986362864968105378316288", 61 | "12345", 62 | "16751774198505232045539489584666775489135471631443877047826295522719290880931" 63 | ], 64 | "proof_data": { 65 | "pi_a": [ 66 | "8286889681087188684411199510889276918687181609540093440568310458198317956303", 67 | "20120810686068956496055592376395897424117861934161580256832624025185006492545", 68 | "1" 69 | ], 70 | "pi_b": [ 71 | [ 72 | "8781021494687726640921078755116610543888920881180197598360798979078295904948", 73 | "19202155147447713148677957576892776380573753514701598304555554559013661311518" 74 | ], 75 | [ 76 | "15726655173394887666308034684678118482468533753607200826879522418086507576197", 77 | "16663572050292231627606042532825469225281493999513959929720171494729819874292" 78 | ], 79 | [ 80 | "1", 81 | "0" 82 | ] 83 | ], 84 | "pi_c": [ 85 | "9723779257940517259310236863517792034982122114581325631102251752415874164616", 86 | "3242951480985471018890459433562773969741463856458716743271162635077379852479", 87 | "1" 88 | ], 89 | "protocol": "groth16" 90 | } 91 | } 92 | ] 93 | } 94 | } 95 | ``` 96 | 97 | The client, after receiving an authorization response, performs the verification process: 98 | 99 | 1. Verification with zero-knowledge proof. 100 | 2. Extraction of metadata (auth and circuit-specific). 101 | 3. Verification of the user identity states. 102 | 4. Verification of the circuit's public inputs (e.g. issuer state). 103 | 104 | 105 | ## Authentication based on Zero-knowledge Proof 106 | 107 | ZK proof is based on the [Circom 2.0](https://docs.circom.io/) language. 108 | 109 | Auth Circuit Repository: [auth](https://github.com/iden3/circuits/blob/master/circuits/lib/authentication.circom) 110 | 111 | The circuit verifies that the user is the owner of the identity and his auth key is not revoked in the provided user state. 112 | 113 | ## Prerequisites 114 | 115 | The identity wallet should be installed. 116 | 117 | ## Integration 118 | 119 | ### Back-end 120 | 121 | **Generate Auth Request** 122 | 123 | ```go 124 | request := auth.CreateAuthorizationRequest("","", "") // create auth request 125 | ``` 126 | 127 | **Validate Auth Request** 128 | 129 | ```go 130 | // unpack raw message 131 | message, err := packer.Unpack(msgBytes) 132 | // call library to verify zkp proofs 133 | err = auth.VerifyProofs(message) 134 | // extract metadata 135 | token, err := auth.ExtractMetadata(message) 136 | // verify state 137 | stateInfo, err := token.VerifyState(ctx.Background(),"< rpc url >", "< state contract address >") 138 | 139 | ``` 140 | 141 | In future releases of the auth library, the verification procedure will be simplified and optimized for a verifier. 142 | 143 | ### Front-end 144 | 145 | On the front-end, you need to embed a button to initiate the login process. After this button is pressed, the front-end makes a request to the back-end to generate an authentication request and displays it in the QR code. When a user scans the QR code, the phone generates a zk proof and sends this proof to the call-back URL from the QR code. 146 | Currently, we are working on the js-iden3-auth library. 147 | 148 | ## Tutorial: A Simple Go Application 149 | 150 | For this, we need a web server with two endpoints: 151 | 152 | - GET /sign-in should return auth request 153 | - POST /call-back endpoint to receive a callback request from the phone and validate the same 154 | 155 | Let us write a simple web server: 156 | 157 | ```go 158 | func main() { 159 | 160 | http.HandleFunc("/sign-in", signIn) 161 | http.HandleFunc("/call-back", callBack) 162 | 163 | http.ListenAndServe(":8001", nil) 164 | } 165 | 166 | func signIn(w http.ResponseWriter, req *http.Request) { 167 | 168 | } 169 | 170 | func callBack(w http.ResponseWriter, req *http.Request) { 171 | 172 | } 173 | ``` 174 | 175 | ### Auth Package 176 | 177 | Add the authorization package to the project. 178 | 179 | ```go 180 | go get https://github.com/iden3/go-iden3-auth 181 | ``` 182 | 183 | ### Sign-in 184 | 185 | To generate a zk auth request, we need a callback URL where we will receive a response from the mobile application along with an authentication response and the verifier's identity. 186 | 187 | The go-iden3-auth library contains a method for generating the authentication request. 188 | 189 | [Description] 190 | 191 | ```go 192 | func CreateAuthorizationRequest(challenge int64, aud, callbackURL string) *types.AuthorizationMessageRequest 193 | ``` 194 | 195 | Now, we are ready to generate the auth request: 196 | 197 | ```go 198 | const CallBackUrl = "http:localhost:8001/call-back" 199 | const VerifierIdentity = "1125GJqgw6YEsKFwj63GY87MMxPL9kwDKxPUiwMLNZ" 200 | 201 | func signIn(w http.ResponseWriter, req *http.Request) { 202 | 203 | request := auth.CreateAuthorizationRequest(10, VerifierIdentity, callBackURI) 204 | 205 | msgBytes, _ := json.Marshal(request) // error handling ommited for simplification 206 | 207 | w.Header().Set("Content-Type", "application/json") 208 | w.WriteHeader(http.StatusOK) 209 | w.Write(msgBytes) 210 | } 211 | ``` 212 | 213 | ### Callback 214 | 215 | When we receive a callback request with a zk response, to validate, we need to take the following actions: 216 | 217 | 1. Validate zk proof and make sure that the proof is valid. 218 | 2. Validate identity's state on-chain so as to verify that the user identity state is valid and his/her auth keys are not revoked. 219 | 220 | First, let’s validate the zk proof. For this, we have the following function: 221 | 222 | ```go 223 | func VerifyProofs(message types.Message) (err error) 224 | ``` 225 | 226 | But before we can call it, we need to unpack raw bytes to a message. Packer can be used to process the encrypted message for future releases. 227 | 228 | ```go 229 | p := &packer.PlainMessagePacker{} 230 | // Unpack msg 231 | message, _ := p.Unpack(msgBytes) 232 | // verify zkp 233 | proofErr := auth.VerifyProofs(message) 234 | ``` 235 | 236 | Now that the zk proof is verified, we can check the identity's status on-chain. 237 | 238 | First, we need access the RPC URL and the address of the identity's smart contract: 239 | 240 | ```go 241 | const rpc = "https://polygon-mumbai.infura.io/v3/" 242 | const IdentityContract = "0x3e95a7B12e8905E01126E1beA3F1a52D1624A725" 243 | ``` 244 | 245 | Before we can verify a state, we need to extract the metadata and then verify it on-chain. 246 | 247 | ```go 248 | token, _:= auth.ExtractMetadata(message) 249 | 250 | // verify match identifier with the state on chain 251 | stateInfo, err := token.VerifyState(ctx, rpc, IdentityContract) 252 | ``` 253 | 254 | ## Verification Procedure 255 | 256 | ### Zero-knowledge Proof Verification 257 | 258 | > Groth16 proofs are now supported by the auth library. 259 | 260 | Verification keys for the circuits can be referred to from the library. In the future, they can be resolved from the circuit registries. 261 | 262 | ### Extraction of Metadata 263 | 264 | Each circuit has a schema of its public inputs that links the public signal name to its position in the resulting array. This allows extracting user identifiers and challenges from the proof for authentication. 265 | 266 | Other signals are added to the user token (scope field) as attributes of a specific circuit. The circuit's public signal schemas are known by this library or can be retrieved from a registry. 267 | 268 | ### Verification of User Identity States 269 | 270 | The blockchain verification algorithm is used to: 271 | 272 | 1. Get state from the blockchain (address of the id state contract and URL must be provided by the caller of the library): 273 | 1. **Empty State is Returned**: It indicates that the identity state has not been updated or the updated state has not been published. We need to compare the id with the state. If they are different, it is not the genesis state of the identity and it is not valid. 274 | 2. **Non-empty State is Returned and Equals to the State Provided in Proof**: This indicates that the user state is new and we work with the latest user state. 275 | 3. **Non-empty State is Returned and is not Equal to the State Provided in Proof**: Gets the time of the state transition. The verification party can make a decision if it can accept this state based on that time frame. 276 | 277 | 2. Accept or reject the provided state (The verification party makes this decision). 278 | 279 | ### Verification of Circuit's Public Signals 280 | 281 | This verification includes the following: 282 | 1. Check if the issuer states of the provided claim proofs are published on the blockchain (same as for identity state). 283 | 2. Check the query signals so that the claim schema and the specific values can be verified. 284 | -------------------------------------------------------------------------------- /mkdocs/docs/publications/pdfs/Baby-Jubjub.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/publications/pdfs/Baby-Jubjub.pdf -------------------------------------------------------------------------------- /mkdocs/docs/publications/pdfs/Ed-DSA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/publications/pdfs/Ed-DSA.pdf -------------------------------------------------------------------------------- /mkdocs/docs/publications/pdfs/Merkle-Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/publications/pdfs/Merkle-Tree.pdf -------------------------------------------------------------------------------- /mkdocs/docs/publications/pdfs/Pedersen-Hash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/publications/pdfs/Pedersen-Hash.pdf -------------------------------------------------------------------------------- /mkdocs/docs/publications/pdfs/test.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/publications/pdfs/test.md -------------------------------------------------------------------------------- /mkdocs/docs/publications/publications.md: -------------------------------------------------------------------------------- 1 | # Publications 2 | 3 | ### Research Papers 4 | 5 | - [Baby Jubjub Elliptic Curve](https://github.com/iden3/iden3-docs/blob/master/source/iden3_repos/research/publications/zkproof-standards-workshop-2/baby-jubjub/baby-jubjub.rst) ([pdf](./pdfs/Baby-Jubjub.pdf ':ignore')) 6 | - [EdDSA For Baby Jubjub Elliptic Curve with MiMC-7 Hash](https://github.com/iden3/iden3-docs/blob/master/source/iden3_repos/research/publications/zkproof-standards-workshop-2/ed-dsa/ed-dsa.rst) ([pdf](./pdfs/Ed-DSA.pdf ':ignore')) 7 | - [4-bit Window Pedersen Hash on the Baby Jubjub Elliptic Curve](https://github.com/iden3/iden3-docs/blob/master/source/iden3_repos/research/publications/zkproof-standards-workshop-2/pedersen-hash/pedersen.rst) ([pdf](./pdfs/Pedersen-Hash.pdf ':ignore')) 8 | - [Sparse Merkle Trees](https://github.com/iden3/iden3-docs/blob/master/source/iden3_repos/research/publications/zkproof-standards-workshop-2/merkle-tree/merkle-tree.rst) ([pdf](./pdfs/Merkle-Tree.pdf ':ignore')) 9 | 10 | ### Videos 11 | 12 | - [Introduction to Iden3](https://www.youtube.com/watch?v=YzUSaCSzPaM) 13 | - [Circom and SnarkJS](https://www.youtube.com/watch?v=-9TJa1hVsKA) 14 | - [Scalable Distributed Identity Infrastructure Using Zero-knowledge Proofs to Guarantee Privacy](https://www.youtube.com/watch?v=VFD2Z_mlSbM) 15 | - [Websnarks - DappCon 2019](https://www.youtube.com/watch?v=IxkpYfNfo5o) 16 | - [Big ZkSNARK Circuits for Zk-rollups with Circom - EthCC 2020](https://www.youtube.com/watch?v=cF6sG47pcws) 17 | 18 | ### Slides 19 | 20 | - [Introduction to Iden3](https://github.com/iden3/iden3-docs/blob/master/source/docs/iden3_ethcc_presentation.pdf) 21 | - [Circom and SnarkJS](https://github.com/iden3/iden3-docs/blob/master/source/docs/circom_and_snarkJS.pdf) 22 | - [Scalable Distributed Identity Infrastructure Using Zero-knowledge Proofs to Guarantee Privacy](https://slideslive.com/38911825/iden3-scalable-distributed-identity-infrastructure-using-zeroknowledge-proofs-to-guarantee-privac) 23 | - [Big ZkSNARK Circuits for Zk-rollups with Circom - EthCC 2020](https://docs.google.com/presentation/d/1oz8K7y2LvfcWrOvEs8lfOodbTQ7mlHXr5Fj610nBiQg/) 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /mkdocs/docs/services/images/login_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/services/images/login_flow.png -------------------------------------------------------------------------------- /mkdocs/docs/services/images/login_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/services/images/login_overview.png -------------------------------------------------------------------------------- /mkdocs/docs/services/libraries.md: -------------------------------------------------------------------------------- 1 | # Iden3 Protocol Libraries 2 | 3 | - **Crypto Library ([go-iden3-crypto](https://github.com/iden3/go-iden3-crypto))** 4 |
Implementation of Poseidon Hash and Baby JubJub Eliptic Curve 5 | 6 | - **Merkle Tree SQL Library ([go-merkletree-sql](https://github.com/iden3/go-merkletree-sql))** 7 |
Implementation of Sparse Merkle Tree 8 | 9 | - **Core Library ([go-iden3-core](https://github.com/iden3/go-iden3-core))** 10 |
Identity Core Primitives 11 | 12 | - **Circuits ([circuits](https://github.com/iden3/circuits))** 13 |
Identity Circuits 14 | 15 | - **Go Circuits ([go-circuits](https://github.com/iden3/go-circuits))** 16 |
Library for Transforming Go-core Primitives to JSON Inputs for Identity Circuits 17 | 18 | - **Prover Server ([prover-server](https://github.com/iden3/prover-server))** 19 |
Wrapper on SnarkJSfor Zk-proof Generation 20 | 21 | - **Authorization Library ([go-iden3-auth](https://github.com/iden3/go-iden3-auth))** 22 |
Library for Authentication with Zk-proof Verification 23 | -------------------------------------------------------------------------------- /mkdocs/docs/services/rhs.md: -------------------------------------------------------------------------------- 1 | # Reverse Hash Service 2 | 3 | ## Overview 4 | 5 | The Reverse Hash Service (RHS) is a service that allows users to construct proofs of existence or non-existence of elements in sparse merkle trees without revealing the specific element being proved. This service aims to enhance privacy of credential revocation status checks for identities. 6 | 7 | ### Introduction 8 | 9 | [Identities](https://docs.iden3.io/protocol/spec/#identity) consist of both private and public data. Public data should be accessible to everyone, while private data should only be available to the identity owner. 10 | 11 | ![](https://i.imgur.com/3ZS1ZvJ.png) 12 | > Identity State Diagram for Direct Identity 13 | 14 | The public data of identity includes: 15 | 16 | - The identity state, which is stored on the blockchain. 17 | - Roots of the identity trees: Claims tree(ClT), Revocation tree(ReT), and Roots tree(RoT). 18 | - All the nodes of the Revocation tree and Roots tree are public. 19 | 20 | The Reverse Hash Service stores nodes of SMTs (In our case, the CIT / ReT / RoT and identity state). This service enables users to perform reverse hash lookups and construct proofs of `existence` or `non-existence` of elements without revealing the specific element being proved. The main objective of this service is to enhance the privacy and security of iden3 identities while ensuring data integrity. 21 | 22 | ### Non-revocation proof 23 | 24 | To build non-revocation proof, we must prove that revocation nonce is not in the revocation tree. 25 | 26 | 1. The first thing we need is to get the `latest state` of the identity from the State smart contract. 27 | 2. Then we can find `roots` of the trees (Clams tree root, Revocation tree root and Roots Tree root) from RHS. 28 | 3. Once we have the `roots`, we can do a reverse hash lookup to construct merkle tree proof for revocation nonce in Revocation Tree as follows: 29 | - Start at the root of the tree. Iterate through each level of the tree until reaching a leaf node or exceeding the maximum tree depth. 30 | - For each level, fetch the corresponding node using the RHS API. 31 | - Based on the type of node encountered (leaf or middle node), perform different actions: 32 | - If the node is a leaf node and its key matches the input key, the proof of existence is complete. Set the `exists` variable to `true`, and return the constructed proof. 33 | - If the node is a leaf node but its key does not match the input key, the `proof of non-existence` is complete. Set the `nodeAux` variable with the leaf node’s `key` and `value`, and return the constructed proof. 34 | - If the node is a middle node, determine how to traverse the tree by checking the input key’s corresponding bit at the current depth. Update the next key to traverse and add the sibling node to the siblings list for proof construction. 35 | - If the algorithm reaches the maximum tree depth without finding a leaf node or a matching key, return an error indicating the tree depth is too high. 36 | 37 | 38 | ```mermaid 39 | sequenceDiagram 40 | participant User 41 | participant SmartContract as State Smart Contract 42 | participant RHS as RHS Storage 43 | User->>SmartContract: Request latest identity state 44 | SmartContract->>User: Return latest identity state 45 | User->>RHS: Fetch roots of trees using identity state 46 | RHS->>User: Return roots of trees [ClR, ReR, RoR] 47 | User->>RHS: Request children of revocation root(ReR) 48 | RHS->>User: Return [left,right] nodes 49 | loop until leaf node is found or max depth is reached 50 | User->>RHS: Request children of node 51 | RHS->>User: Return [left,right] nodes 52 | end 53 | User->>User: Calculate Proof 54 | ``` 55 | By following these steps, the algorithm generates a Merkle proof of existence or non-existence for a given key in a Sparse Merkle Tree without revealing the specific element being proved. 56 | 57 | ### RHS Storage 58 | 59 | RHS Storage is a persistence layer that stores hashes of preimages. A preimage is an array of integers, which length can be theoretically any number starting from 1. In practice, only support arrays of length 2 and 3 is guaranteed as it is used in the Iden3 protocol. 60 | 61 | The storage implements key-value approach, where key is a hash of preimage and value is a preimage itself. It is only possible to set a value for a key, but not the key itself as the key is calculated by RHS Storage as a hash of preimage using Poseidon hash function in the transaction that sets the value. 62 | 63 | RHS Storage can be **on-chain** or **off-chain** type. 64 | 65 | In the case of **on-chain** storage, the key-value storage is a smart contract with an interface as follows: 66 | ```solidity 67 | interface IRHSStorage { 68 | /** 69 | * @dev Saves nodes array. Note that each node contains an array itself. 70 | * @param nodes An array of nodes 71 | */ 72 | function saveNodes(uint256[][] memory nodes) external; 73 | 74 | /** 75 | * @dev Returns a node by its key. Note that a node contains an array. 76 | * @param key The key of the node 77 | * @return The node 78 | */ 79 | function getNode(uint256 key) external view returns (uint256[] memory); 80 | } 81 | ``` 82 | In the case of **off-chain** storage, the key-value storage is may be implemented as a service on top of a database. It can be found in the [reverse-hash-service](https://github.com/iden3/reverse-hash-service) repository. 83 | 84 | The service exposes two endpoints: 85 | ```http 86 | /POST {{server}}/node 87 | Content-Type: application/json 88 | 89 | { 90 | "hash":"2c32381aebce52c0c5c5a1fb92e726f66d977b58a1c8a0c14bb31ef968187325", 91 | "children":[ 92 | "658c7a65594ebb0815e1cc20f54284ccdb51bb1625f103c116ce58444145381e", 93 | "e809a4ed2cf98922910e456f1e56862bb958777f5ff0ea6799360113257f220f" 94 | ] 95 | } 96 | 97 | 98 | /GET {{server}}/node/{{hash}} 99 | ``` 100 | 101 | ### RHS Client interface and Reverse Hash Lookup 102 | 103 | The RHS Client interface abstracts away the specific RHS Storage implementation. You are free to choose whether to connect your clients directly to RHS Storage or use RHS Client interface. 104 | 105 | The interface defines three methods: 106 | - **SaveNodes**: saves nodes of the tree to RHS 107 | - **GetNode**: gets node of the tree from RHS, so it does a reverse hash lookup and reveals the preimage of the hash 108 | - **GenerateProof**: generates proof of existence or non-existence of the element in the Sparse Merkle Tree according to the [algorithm](#smt-proof-generation) described below 109 | 110 | The library that implements the RHS Client interface is located in the [merkletree-proof](https://github.com/iden3/merkletree-proof) repository and the interface itself is as follows: 111 | 112 | ```go 113 | type ReverseHashCli interface { 114 | GenerateProof(ctx context.Context, 115 | treeRoot *merkletree.Hash, 116 | key *merkletree.Hash) (*merkletree.Proof, error) 117 | GetNode(ctx context.Context, 118 | hash *merkletree.Hash) (Node, error) 119 | SaveNodes(ctx context.Context, 120 | nodes []Node) error 121 | } 122 | ``` 123 | 124 | The Node struct is defined as follows: 125 | ```go 126 | type Node struct { 127 | Hash *merkletree.Hash // merkletree.Hash is an array of 32 bytes 128 | Children []*merkletree.Hash 129 | } 130 | ``` 131 | Note, that the Hash field of the Node struct is a hash of the Children field, however it is not saved to RHS in the SaveNodes() method as it is calculated by RHS Storage itself. 132 | 133 | ### Publishing identity state to RHS 134 | 135 | If identity holder wants to publish his identity state to RHS he needs to do the following: 136 | 137 | 1. Save the state of identity to RHS `{ Hash: state, Children: [ClaimsTreeRoot, RevocationTreeRoot, RootsTreeRoot] }` 138 | 2. Save the nodes of Revocation tree and Roots tree to RHS for the intermediate nodes `{ Hash: hash, Children: [left, right] }` where left and right are the hashes of the children of the node. And for the leaf nodes `{ Hash: hash, Children: [key, value, 1] }` 139 | 140 | ### Example with **off-chain RHS storage**: 141 | 142 | ```go 143 | 144 | package main 145 | 146 | import ( 147 | "context" 148 | "encoding/json" 149 | "fmt" 150 | "math/big" 151 | 152 | "github.com/iden3/go-merkletree-sql/v2" 153 | proof "github.com/iden3/merkletree-proof/http" 154 | ) 155 | 156 | func main() { 157 | ctx := context.Background() 158 | rhsURL := "https://rhs-staging.polygonid.me" 159 | state := "e12084d0d72c492c703a2053b371026bceda40afb9089c325652dfd2e5e11223" 160 | revocationNonce, _ := merkletree.NewHashFromBigInt(big.NewInt(670966937)) 161 | 162 | cli := &proof.ReverseHashCli{URL: rhsURL} 163 | 164 | // get identity state roots (ClT root, ReT root, RoT root) 165 | node := getIdentityStateRoots(cli, ctx, state) 166 | json, err := json.Marshal(node) 167 | if err != nil { 168 | panic(err) 169 | } 170 | fmt.Println(string(json)) 171 | 172 | // get non-revocation proof by ReT root and revocation nonce 173 | proof, err := cli.GenerateProof(ctx, node.Children[1], revocationNonce) 174 | if err != nil { 175 | panic(err) 176 | } 177 | jsonProof, err := proof.MarshalJSON() 178 | if err != nil { 179 | panic(err) 180 | } 181 | 182 | fmt.Println(string(jsonProof)) 183 | } 184 | 185 | func getIdentityStateRoots(cli *proof.HTTPReverseHashCli, ctx context.Context, state string) proof.Node { 186 | s, err := merkletree.NewHashFromHex(state) 187 | if err != nil { 188 | panic(err) 189 | } 190 | 191 | stateValues, err := cli.GetNode(ctx, s) 192 | if err != nil { 193 | panic(err) 194 | } 195 | 196 | return stateValues 197 | } 198 | ``` 199 | 200 | _!!! Note that on-chain RHS storage initialization is a bit more complex. Check merkletree-proof library for more details._ 201 | 202 | ### RHS Storage Implementation 203 | 204 | Off-chain: [https://github.com/iden3/reverse-hash-service](https://github.com/iden3/reverse-hash-service) 205 | 206 | On-chain: [https://github.com/iden3/contracts/blob/master/contracts/identitytreestore/IdentityTreeStore.sol](https://github.com/iden3/contracts/blob/master/contracts/identitytreestore/IdentityTreeStore.sol) 207 | 208 | _!!! Note that IdentityTreeStore implements SMT Proof generation algorithm on-chain as part of getRevocationStatusByIdAndState() method, so you are free to use it as alternative way to generate revocation proofs._ 209 | 210 | ### Library to interact with RHS Storage 211 | 212 | [https://github.com/iden3/merkletree-proof](https://github.com/iden3/merkletree-proof) 213 | 214 | ### Links 215 | 216 | [https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf](https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf) 217 | 218 | [https://github.com/iden3/go-merkletree-sql](https://github.com/iden3/go-merkletree-sql) 219 | 220 | [https://github.com/0xPolygonID/js-sdk](https://github.com/0xPolygonID/js-sdk) 221 | -------------------------------------------------------------------------------- /mkdocs/docs/w3c/images/json-mrklz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/docs/00d5f8c9c0d830f0dff84aa0d1724a8be91c8955/mkdocs/docs/w3c/images/json-mrklz.png -------------------------------------------------------------------------------- /mkdocs/docs/w3c/merklization.md: -------------------------------------------------------------------------------- 1 | # JSON-LD document merklization 2 | 3 | ## Motivation 4 | 5 | Implement a data structure that allows generating zero-knowledge proofs based on individual entries of [JSON-LD](https://www.w3.org/TR/json-ld11/) documents. 6 | This will enable users to prove certain statements about their data without revealing the actual content, thereby preserving privacy and ensuring data security.. 7 | 8 | ## Core Concept 9 | 10 | Convert a JSON-LD document into a Merkle Tree data structure (namely, merklize it), and prove the inclusion of the entries in the tree. 11 | 12 | To achieve this, take the JSON-LD document and convert it to an expanded form. Then, normalize it using the URDNA2015 algorithm, 13 | which results in a list of RDF Quads. For each Quad, construct key-value pairs and add them to the Merkle Tree. 14 | 15 | ``` 16 | map[path]value 17 | ``` 18 | 19 | Example 20 | 21 | ``` 22 | map[https://www.w3.org/2018/credentials#expirationDate] = 1890994792000000000 23 | ``` 24 | 25 | For example 26 | 27 | ```json 28 | { "@context": "http://schema.org/", "@type": "Person", "name": "Jane Doe", "jobTitle": "Professor", "telephone": "(425) 123-4567",} 29 | ``` 30 | 31 | Can be presented as 32 | 33 | | Path | Value | 34 | | --- | --- | 35 | | http://schema.org/jobTitle | Professor | 36 | | http://schema.org/name | Jane Doe | 37 | | http://schema.org/telephone | (425) 123-4567 | 38 | | http://www.w3.org/1999/02/22-rdf-syntax-ns#type | http://schema.org/Person | 39 | 40 | The data included in the map can be stored in a [Sparse Merkle tree](https://docs.iden3.io/basics/key-concepts/#sparse-merkle-trees) where: 41 | 42 | - the `index` of an entry in the tree is its path 43 | - the `value` of an entry in the tree is the hash of its value 44 | 45 | ![json-mrklz.png](images%2Fjson-mrklz.png) 46 | 47 | ## Merklization Algorithm 48 | 49 | Before splitting a JSON-LD document into tree entries, it must be converted into an expanded format and normalized using 50 | the URDNA2015 algorithm. Normalization is required to ensure a predictable order of array elements when multiple child 51 | elements exist under the same parent with the same predicate. Most JSON-LD documents use a compact format that employs 52 | shorthand terms to represent commonly used IRIs (Internationalized Resource Identifiers). In contrast, the expanded format uses full IRIs. 53 | 54 | This process dereferences all terms into fully-qualified IRI values, making it easier to work with the data in a 55 | standardized and predictable manner. 56 | 57 | Example: 58 | 59 | JSON-LD document compact format: 60 | 61 | ```json 62 | { 63 | "@context": [ 64 | "http://schema.org/", 65 | "https://w3id.org/citizenship/v1", 66 | "https://www.w3.org/2018/credentials/v1"], 67 | "@type": "Person", 68 | "name": "Jane Doe", 69 | "jobTitle": "Professor", 70 | "credentialSubject": { 71 | "@type": "PermanentResident", 72 | "birthCountry": "Spain" } 73 | } 74 | ``` 75 | 76 | Expanded format: 77 | 78 | ```json 79 | [ 80 | { 81 | "@type": [ 82 | "http://schema.org/Person" 83 | ], 84 | "http://schema.org/credentialSubject": [ 85 | { 86 | "@type": [ 87 | "https://w3id.org/citizenship#PermanentResident" 88 | ], 89 | "https://w3id.org/citizenship#birthCountry": [ 90 | { 91 | "@value": "Spain" 92 | } 93 | ] 94 | } 95 | ], 96 | "http://schema.org/jobTitle": [ 97 | { 98 | "@value": "Professor" 99 | } 100 | ], 101 | "http://schema.org/name": [ 102 | { 103 | "@value": "Jane Doe" 104 | } 105 | ] 106 | } 107 | ] 108 | ``` 109 | 110 | Starting from the expanded format, it is possible to build path-value entries for each entry of the JSON-LD Document to be stored inside the Merkle Tree. 111 | 112 | If there is an array of objects, we use integers as an index in the path. For example, if we have an array of `PermanentResident` objects in `credentialSubject` field, then the path will look like `["http://schema.org/credentialSubject", 0, “https://w3id.org/citizenship#birthCountry”]` 113 | 114 | To store an entry of the JSON-LD Document into a Merkle tree, we need to calculate hashes (of integer type) for the path and the value. The hashing interface has to have three methods: 115 | 116 | - Method #1: Return the Int value of hash from an array of other Ints 117 | 118 | ```tsx 119 | // PSEUDOCODE 120 | function hashInts (arr : int[]) :int 121 | ``` 122 | 123 | - Method #2: Return the Int value of hash from an arbitrary array of bytes. Poseidon uses sponge hashing. Split input byte array in 31-byte blocks. And hash in chunks of 16 blocks (the first element of the next 16-block chink is a hash of the previous chunk) 124 | 125 | ```tsx 126 | // PSEUDOCODE 127 | function hashBytes (arr : bytes[]) :int 128 | ``` 129 | 130 | - Method #3: Return the Prime of the field used. For Poseidon hashing, it equals `21888242871839275222246405745257275088548364400416034343698204186575808495617` 131 | 132 | ```tsx 133 | // PSEUDOCODE 134 | function prime () :int 135 | ``` 136 | 137 | **To calculate the hash of the path**, we replace all string elements of the path with hashes of those strings using method #2. All strings are interpreted as bytes array of UTF-8 representation of the string. Int index values are left as is in the path. In the end, we hash an array of Integers using method #1. 138 | 139 | ```jsx 140 | // PSEUDOCODE 141 | function hashPath (path : (string | int)[]) :int { 142 | 143 | for (let i = 0; i < path.length; i++) { 144 | 145 | if (typeof path[i] == string { 146 | let utf8Bytes = encode(path[i]); 147 | path[i] = hashBytes(utf8Bytes) 148 | } 149 | 150 | } 151 | 152 | return hashInts(path) 153 | } 154 | ``` 155 | 156 | **To calculate the hash of the value**, use different methods depending on the value type. 157 | 158 | - For positive integers, we use the value as is. 159 | - The negative integer `N` is represented as `prime() - abs(N)` 160 | - For boolean values, hash equals 0 for false and 1 for true. 161 | - For string values we use method #2 to hash byte array of UTF-8 representation of string 162 | - For DateTime the hash value is a Unix timestamp in nano-seconds. 163 | 164 | ```jsx 165 | // PSEUDOCODE 166 | function hashValue (value : (int | bool | string | DateTime) :int { 167 | 168 | if (typeof value == bool) { 169 | value ? return hashInts([1]) : return hashInts([0]) 170 | } 171 | 172 | if (typeof value == int) { 173 | if (value < 0) { 174 | value = prime() - abs(value) 175 | } 176 | return hashInts([value]) 177 | } 178 | 179 | if (typeof value == string) { 180 | const utf8Bytes = encode(value); 181 | return hashBytes(utf8Bytes) 182 | } 183 | 184 | if(typeof value == DateTime) { 185 | return value.UnixTimestampNano() 186 | } 187 | } 188 | ``` 189 | 190 | Given hash values for Path and Value, both in integer format, we put them into the [Sparse Merkle Tree.](https://docs.iden3.io/basics/key-concepts/#sparse-merkle-trees) 191 | 192 | ### Normalization example 193 | 194 | There are two cases we need to handle carefully during the normalization of the JSON-LD document 195 | 196 | - Multigraph document 197 | - Swapping array elements 198 | 199 | In the following document, the type of `verifiableCredential` is declared as `"@container": "@graph"` in the schema. In this case, we need to link those graphs correctly while building path keys. 200 | 201 | Also, during normalization, the object with the identifier `[http://example.com/vc3](http://example.com/vc3)` goes before the object with the identifier `http://example.com/vc1`. So it gets index 0, and `vc1` gets index 1. This is because during canonization, the name of the graph with id `http://example.com/vc3` is _:c14n1 and the name of the graph with id `http://example.com/vc1` is _:c14n2. When building indexing, embedded graphs are sorted in lexical order, so `http://example.com/vc3` comes before `http://example.com/vc1`. 202 | 203 | Example document: 204 | 205 | ```json 206 | { 207 | "@context":[ 208 | "https://www.w3.org/2018/credentials/v1", 209 | "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld", 210 | "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/iden3credential-v2.json-ld" 211 | ], 212 | "@type":"VerifiablePresentation", 213 | "verifiableCredential":[ 214 | { 215 | "@id": "http://example.com/vc1", 216 | "@type":"KYCAgeCredential", 217 | "birthday":19960424 218 | }, 219 | { 220 | "@id": "http://example.com/vc3", 221 | "@type": "Iden3SparseMerkleTreeProof", 222 | "issuerData": { 223 | "state": { 224 | "blockTimestamp": 123 225 | } 226 | } 227 | } 228 | ] 229 | } 230 | ``` 231 | 232 | After normalization nodes under `verifiableCredential` will be swapped, and the path to `blockTimestamp` would look like 233 | 234 | ```json 235 | [ 236 | "https://www.w3.org/2018/credentials#verifiableCredential", 237 | 0, 238 | "https://github.com/iden3/claim-schema-vocab/blob/main/proofs/Iden3SparseMerkleTreeProof-v2.md#issuerData", 239 | "https://github.com/iden3/claim-schema-vocab/blob/main/proofs/Iden3SparseMerkleTreeProof-v2.md#state", 240 | "https://github.com/iden3/claim-schema-vocab/blob/main/proofs/Iden3SparseMerkleTreeProof-v2.md#blockTimestamp" 241 | ] 242 | ``` 243 | 244 | And the path to `birthday` is 245 | 246 | ```json 247 | [ 248 | "https://www.w3.org/2018/credentials#verifiableCredential", 249 | 1, 250 | "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/kyc.md#birthday" 251 | ] 252 | ``` 253 | 254 | ## Proof of Inclusion and Non-Inclusion 255 | 256 | Each entry of the JSON-LD document can now be added inside the Sparse Merkle Tree. For example, the entry `(birthCountry->Spain)` can be express as 257 | 258 | ``` 259 | map["http://schema.org/credentialSubject", "https://w3id.org/citizenship#birthCountry"] = "Spain" 260 | ``` 261 | 262 | After having performed the hashing to `path` and `value` as described in the algorithm section and adding it to the Sparse Merkle Tree, it is possible to [generate `proof of inclusion`](https://docs.iden3.io/getting-started/mt/) of the element inside the tree. The implementation of that will be described in the next paragraph. 263 | 264 | Sparse Merkle Tree also allows to [generate `proof of non-inclusion`](https://docs.iden3.io/getting-started/mt/) of entries inside the JSON-LD document. For example, we can prove that an entry with a field `name` is not included in the document by starting from its path. 265 | 266 | ``` 267 | ["http://schema.org/credentialSubject", “https://w3id.org/citizenship#name”] 268 | ``` 269 | 270 | ## Implementation - Merklize 271 | 272 | The following code snippet describes how to use the [go schema processor Library](https://github.com/iden3/go-schema-processor) to merklize a JSON-LD document. Starting from the merklized version of the JSON-LD it is possible to generate proof of inclusion (or of non-inclusion) of entries starting from their `path` 273 | 274 | This implementation makes use of `[poseidonHash](https://www.poseidon-hash.info)` as hashing algorithm inside the tree. 275 | 276 | ```go 277 | package main 278 | 279 | import ( 280 | "context" 281 | "fmt" 282 | "strings" 283 | "github.com/iden3/go-schema-processor/merklize" 284 | ) 285 | 286 | func main() { 287 | 288 | // Start from a standard JSON-LD Document 289 | const doc = `{ 290 | "@context": [ 291 | "http://schema.org/", 292 | "https://w3id.org/citizenship/v1", 293 | "https://www.w3.org/2018/credentials/v1" 294 | ], 295 | "@type": "Person", 296 | "name": "Jane Doe", 297 | "jobTitle": "Professor", 298 | "credentialSubject": { 299 | "@type": "PermanentResident", 300 | "birthCountry": "Spain" 301 | } 302 | }` 303 | 304 | // Merklize the JSON-LD Document 305 | mz, err := merklize.MerklizeJSONLD(context.Background(), strings.NewReader(doc)) 306 | if err != nil { 307 | panic(err) 308 | } 309 | 310 | // Print the root of the newly generated Sparse Merkle Tree 311 | fmt.Println("Root:", mz.Root().Hex()) 312 | 313 | // Now let's generate a proof of inclusion for a specific path 314 | 315 | // Parse the path 316 | path, err := merklize.NewPath("http://schema.org/credentialSubject", "https://w3id.org/citizenship#birthCountry") 317 | if err != nil { 318 | panic(err) 319 | } 320 | 321 | // Generate the proof of inclusion for an entry corresponding to that path 322 | proof, value, err := mz.Proof(context.Background(), path) 323 | if err != nil { 324 | panic(err) 325 | } 326 | 327 | // Print the proof 328 | fmt.Println("Proof:", proof) 329 | fmt.Println("Existence:", proof.Existence) 330 | fmt.Println("Siblings:", proof.AllSiblings()) 331 | fmt.Println("Aux:", proof.NodeAux) 332 | 333 | // Print the value inside the SMT associated with that path 334 | fmt.Println("Value:", value) 335 | 336 | } 337 | ``` 338 | 339 | ## Implementation - ZK Prover 340 | 341 | The following provides an example of a [general-purpose zk circuit](https://github.com/iden3/circomlib/blob/master/circuits/smt/smtverifier.circom), written in [circom](https://docs.circom.io/), that proves inclusion of an element inside a Sparse Merkle Tree. This implementation can be adapted to prove inclusion of an entry inside a JSON-LD Document starting from its path. 342 | 343 | ``` 344 | template MTVerifier() { 345 | signal input root; 346 | 347 | // expiration time 348 | signal input expirationDate; // timestamp 349 | signal input expirationValue; 350 | signal input expirationMtp[32]; 351 | 352 | // expiration date 353 | // https://www.w3.org/2018/credentials#expirationDate 354 | // https://www.w3.org/2018/credentials#expirationDate < expirationDate 355 | component expirationInMT = SMTVerifier(32); 356 | expirationInMT.enabled <== 1; 357 | expirationInMT.fnc <== 0; // inclusion 358 | expirationInMT.root <== root; 359 | for (var i=0; i<32; i++) { expirationInMT.siblings[i] <== expirationMtp[i]; } 360 | expirationInMT.oldKey <== 0; 361 | expirationInMT.oldValue <== 0; 362 | expirationInMT.isOld0 <== 0; 363 | expirationInMT.key <== 13483382060079230067188057675928039600565406666878111320562435194759310415773; 364 | expirationInMT.value <== expirationValue; 365 | } 366 | ``` 367 | 368 | Base verifications can be extended with any combination of fields, although some verification can be required by specific circuits. For example, verification of expiration time can be required without reviling expiration time to the verifier. Verifier will know only that the expiration time is greater than the current time. 369 | 370 | ## Conclusion 371 | 372 | The proposed approach enables to generate ZK proofs based over [Verifiable Credentials](https://www.w3.org/TR/vc-data-model/) (VC), which are formatted into JSON-LD data format. This open ups new possibilities: 373 | 374 | - Do selective disclosure over entries of a VC. Namely, a user can disclose a single entry inside a proof without revealing any other entry of the document 375 | - Do [query request](https://0xpolygonid.github.io/tutorials/verifier/verification-library/zk-query-language/) over entries of a VC. Namely, a user can prove that an entry satisfies a certain query without revealing the value of the entry itself (and any other entry of the document) 376 | - Prove non membership of an entry with a specific path. Namely, a user can prove that an entry with a specific path doesn’t exist inside a VC. 377 | - Prove non membership of a entry with a specific path and value. Namely, a user can prove that an entry with a specific path and value doesn’t exist inside a VC. 378 | - The proof can be verified inside smart contract making VC compatible with on-chain interactions. 379 | 380 | ## Implementations 381 | 382 | Implementation of the proposed approach is available in the following repositories: 383 | 384 | - Go - https://github.com/iden3/go-schema-processor 385 | - JS - https://github.com/iden3/js-jsonld-merklization -------------------------------------------------------------------------------- /mkdocs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Iden3 Documentation 2 | site_url: https://docs.iden3.io/ 3 | theme: 4 | name: material 5 | palette: 6 | primary: black 7 | logo: logo.svg 8 | favicon: favicon.ico 9 | features: 10 | - navigation.tabs 11 | - navigation.tabs.sticky 12 | - navigation.tracking 13 | - content.code.copy 14 | repo_url: https://github.com/iden3/docs 15 | markdown_extensions: 16 | - pymdownx.arithmatex: 17 | generic: true 18 | - mkdocs_graphviz 19 | - def_list 20 | - attr_list 21 | - md_in_html 22 | - admonition 23 | - pymdownx.details 24 | - pymdownx.superfences 25 | - pymdownx.superfences: 26 | custom_fences: 27 | - name: mermaid 28 | class: mermaid 29 | format: !!python/name:pymdownx.superfences.fence_code_format 30 | 31 | 32 | 33 | extra_javascript: 34 | - javascripts/mathjax.js 35 | - https://polyfill.io/v3/polyfill.min.js?features=es6 36 | - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js 37 | extra: 38 | social: 39 | - icon: fontawesome/brands/telegram 40 | link: https://t.me/iden3io 41 | - icon: fontawesome/brands/github 42 | link: https://github.com/iden3/docs 43 | - icon: octicons/browser-24 44 | link: https://iden3.io/ 45 | 46 | nav: 47 | - The basics: 48 | - Introduction: "basics/introduction.md" 49 | - Key concepts: "basics/key-concepts.md" 50 | - Getting started: "basics/getting-started.md" 51 | - Iden3 protocol: 52 | - Iden3 protocol specs: "protocol/spec.md" 53 | - Claim: 54 | - Structure: "protocol/claims-structure.md" 55 | - AuthBJJCredential: "protocol/bjjkey.md" 56 | - Claim Schema : "protocol/claim-schema.md" 57 | - Core Tutorial: 58 | - Introduction: "getting-started/getting-started.md" 59 | - Core Components: 60 | - Baby Jubjub Keypair: "getting-started/babyjubjub.md" 61 | - Sparse Merkle Tree: "getting-started/mt.md" 62 | - Claim: 63 | - Generic Claim: "getting-started/claim/generic-claim.md" 64 | - Auth Claim: "getting-started/claim/auth-claim.md" 65 | # - Claim Schema: "getting-started/claim/claim-schema.md" 66 | - Identity: 67 | - Identity Types: "getting-started/identity/identity-types.md" 68 | - Identity State: "getting-started/identity/identity-state.md" 69 | - Identifier: "getting-started/identity/identifier.md" 70 | - Identity Profiles: "getting-started/identity/identity-profile.md" 71 | - OnChain Identity: "getting-started/identity/onchain-identity.md" 72 | - Issue Claim: 73 | - Overview: "getting-started/issue-claim-overview.md" 74 | - via Signature: "getting-started/signature-claim/signature.md" 75 | - via Merkle Tree: 76 | - Intro to State Transition: "getting-started/state-transition/state-transition.md" 77 | - Add Claim to the Claims Tree: "getting-started/state-transition/new-identity-state.md" 78 | - Generate Proof for State Transition: "getting-started/state-transition/state-transition-proof.md" 79 | - Verify the Proof On-Chain: "getting-started/state-transition/on-chain-state-transition.md" 80 | - Claim Revocation: 81 | - Revoke Claim: "getting-started/claim-revocation.md" 82 | 83 | - Services and protocols: 84 | # - Libraries: "services/libraries.md" 85 | - Login protocol: "protocol/zklogin.md" 86 | - Proof Query language: "protocol/querylanguage.md" 87 | - Non-merklized credentials: "protocol/non-merklized.md" 88 | - JSON-LD merklization: "w3c/merklization.md" 89 | - Reverse hash service: "services/rhs.md" 90 | - Circuits: 91 | - Main Circuits: "protocol/main-circuits.md" 92 | - Template Circuits: "protocol/template-circuits.md" 93 | - Circom / snarkjs: "circom-snarkjs/index.md" 94 | - Contracts: "contracts/contracts.md" 95 | - Publications: "publications/publications.md" 96 | 97 | # If you declare plugins, you need to declare all of them, 98 | # including search (which would otherwise have been installed by default.) 99 | plugins: 100 | - search 101 | - mermaid2 102 | --------------------------------------------------------------------------------