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 |
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 | 
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 | 
136 |
137 | Next, we group these parent nodes into pairs and store the hash of each pair one level up the tree.
138 |
139 | 
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 | 
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 | 
152 |
153 | If an adversary tampers with a block at the leaf of our tree,
154 |
155 | 
156 |
157 | it will cause the mismatch with the hash in the node that’s one level up.
158 |
159 | 
160 |
161 | So the adversary will have to tamper with that too.
162 |
163 | 
164 |
165 | This means s/he has to tamper with the node one level up from there.
166 |
167 | 
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 | 
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 | 
180 |
181 | All we need are the blocks on the path from the data block to the root.
182 |
183 | 
184 |
185 | And each of data0's siblings on the way up.
186 |
187 | 
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 | 
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 | 
196 |
197 | In our case, we start by calculating the hash of data0 and storing it in the block labeled 0.
198 |
199 | 
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 | 
204 |
205 | Finally, we calculate the hash of blocks 4 and 5 to obtain the recalculated root.
206 |
207 | 
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 | 
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 | 
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 | 
239 |
240 | With this placeholder, we can now build up the rest of the tree.
241 |
242 | 
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 | 
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 | 
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 |
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 | 
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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------