|
| 1 | +--- |
| 2 | +title: Issuance Status |
| 3 | +sidebar_label: Issuance Status |
| 4 | +--- |
| 5 | + |
| 6 | +OpenAttestation checks that the document has been issued and that it's issuance status is in good standing (for instance, that it hasn't been revoked). As of today, OpenAttestation supports two ways to issue documents: DIDs and Ethereum Smart Contracts. |
| 7 | + |
| 8 | +## Ethereum Smart Contracts |
| 9 | + |
| 10 | +The [document store](/docs/verifiable-document/document-store) is a smart contract on the Ethereum network that records the issuance and revocation status of OpenAttestation documents. It stores the hashes of wrapped documents, which are the records of the owner of the document store having issued the documents. Before we explain the verification process in detail, we need to introduce a new concept: the `merkleRoot`. |
| 11 | + |
| 12 | +Let's imagine that we need to wrap thousands of files and had to issue the `targetHash` for each of them. It would be extremely inefficient because Ethereum is slow, and we would have to pay for each transaction. |
| 13 | + |
| 14 | +That's where the `merkleRoot` will come in handy. |
| 15 | + |
| 16 | +### merkleRoot |
| 17 | + |
| 18 | +Once the `targetHash` of a document is computed, OpenAttestation will determine the `merkleRoot`. The `merkleRoot` value is the merkle root hash computed from the [merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) using the `targetHash` of all the document wrapped together. Each `targetHash` is a leaf in the tree. After computing the merkle tree, the `merkleRoot` associated to a document will be added to it as well as the proofs (intermediate hashes) needed to ensure that the `targetHash` has been used to compute the `merkleRoot`. The proofs are added into the `proof` property. |
| 19 | + |
| 20 | +On a side note, when we wrap only one document at a time, the `targetHash` and the `merkelRoot` are identical and the `proof` is empty. This is completely normal. When we wrap at least 2 documents at the same time, we will notice a difference between `targetHash` and the `merkelRoot`, and proofs appended. |
| 21 | + |
| 22 | +> The `merkleRoot` will always be the same for all the documents wrapped together (in a batch). It will be different for documents wrapped separately. |
| 23 | +
|
| 24 | +### Issuance |
| 25 | + |
| 26 | +Now that our batch of documents has a common identifier and that we can prove (thanks to the merkle tree algorithm) that the `targetHash` of a document was used to create a specific `merkleRoot`, we can use the `merkleRoot` in our document store and issue it. |
| 27 | + |
| 28 | +### Revocation |
| 29 | + |
| 30 | +As discussed above, issuance of documents can happen individually or by batch. Issuing a batch documents is by far the more efficient way. When it comes to revocation both values can also be used: |
| 31 | + |
| 32 | +- `targetHash` will allow for the revocation of a specific document. |
| 33 | +- `merkleRoot` will allow for the revocation of the whole batch of documents. |
| 34 | + |
| 35 | +### Issuance process and verification |
| 36 | + |
| 37 | +To issue a document, an institution or individual : |
| 38 | + |
| 39 | +- [Deploys a new document store](/docs/verifiable-document/document-store) on Ethereum and get the address of the deployed contract. (this action needs to be performed only once) |
| 40 | +- Adds the address of the deployed contract into the document (before wrapping). |
| 41 | +- Wraps a document (or a batch of documents) and get a `merkleRoot`. The wrapped documents can be shared to the recipients. |
| 42 | +- Issues the `merkleRoot` by calling the `issue` function from the document store contract. |
| 43 | + |
| 44 | +An OpenAttestation verifier: |
| 45 | + |
| 46 | +- Checks the `merkleRoot` of the document has been issued: |
| 47 | + 1. Gets back the document store contract address from the document itself. |
| 48 | + 1. Ensures that the `targetHash` and the `proof` matches the `merkleRoot`. |
| 49 | + 1. Checks the `merkleRoot` is in the document store provided, by calling the `isIssued` function from the deployed contract. |
| 50 | +- Checks the `merkleRoot` of the document has been issued: |
| 51 | + 1. Gets back the document store contract address from the document itself. |
| 52 | + 1. Checks the `targetHash` is **not** in the document store provided, by calling the `isRevoked` function from the deployed contract. |
| 53 | + 1. Checks the `merkleRoot` is **not** in the document store provided, by calling the `isRevoked` function from the deployed contract. |
| 54 | + |
| 55 | +## DIDs |
| 56 | + |
| 57 | +Decentralized identifiers (DIDs) are a new type of identifier that enables verifiable, decentralized digital identity. DID document associated with DIDs contains a verification method, often a public key. The owner of a DID can use the private key associated and anyone can verify that the owner control the public key. |
| 58 | + |
| 59 | +At the moment, OpenAttestation only supports one DID method: `ethr`. |
| 60 | + |
| 61 | +### Issuance |
| 62 | + |
| 63 | +DIDs [are significantly faster and incur not costs](/docs/verifiable-document/comparison). They could directly use the `targetHash` of the document (which is unique) and sign it using the private key associated. However for consistency with our initial design, we sign the `merkleRoot`. |
| 64 | + |
| 65 | +The information about the signature are added to the document, into the `proof` property. That's it, the document has been issued. |
| 66 | + |
| 67 | +Let's dig a bit more to understand how it works. |
| 68 | + |
| 69 | +An [`ethr` DID document](https://dev.uniresolver.io/1.0/identifiers/did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69) looks like :: |
| 70 | + |
| 71 | +```json |
| 72 | +{ |
| 73 | + "@context": "https://w3id.org/did/v1", |
| 74 | + "id": "did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69", |
| 75 | + "publicKey": [ |
| 76 | + { |
| 77 | + "id": "did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69#controller", |
| 78 | + "type": "Secp256k1VerificationKey2018", |
| 79 | + "controller": "did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69", |
| 80 | + "ethereumAddress": "0x6813eb9362372eef6200f3b1dbc3f819671cba69" |
| 81 | + } |
| 82 | + ], |
| 83 | + "authentication": [ |
| 84 | + { |
| 85 | + "type": "Secp256k1SignatureAuthentication2018", |
| 86 | + "publicKey": "did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69#controller" |
| 87 | + } |
| 88 | + ] |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +Three important information can be found: |
| 93 | + |
| 94 | +- the DID identifier (here `did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69`). It's used to identify the DID and must be added into the `issuer.id` property of the document. |
| 95 | +- The DID controller (here `did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69#controller`). It's used to identify which public key control the DID and must be added into the `issuer.identityProof.key` property of the document. It's also worth to note that the value is equal to the DID identifier, appended with `#controller`. |
| 96 | +- The ethereum address associated to the DID controller (here `0x6813eb9362372eef6200f3b1dbc3f819671cba69`). We will use it to verify the signature. |
| 97 | + |
| 98 | +> You can find an example of document using DID in our [guide](/docs/verifiable-document/did/raw-document). |
| 99 | +
|
| 100 | +A proof of signature looks like: |
| 101 | + |
| 102 | +```json |
| 103 | +{ |
| 104 | + "proof": [ |
| 105 | + { |
| 106 | + "type": "OpenAttestationSignature2018", |
| 107 | + "created": "2020-10-05T09:05:35.171Z", |
| 108 | + "proofPurpose": "assertionMethod", |
| 109 | + "verificationMethod": "did:ethr:0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69#controller", |
| 110 | + "signature": "0x6d0ff5c64b8230cdc471f38267495002f2c762acf7a80250599809ee32b4255377f1adcb56fb712dee66bfeb21be6b5d802f299aea1f1edca129e88e4c1742ce1c" |
| 111 | + } |
| 112 | + ] |
| 113 | +} |
| 114 | +``` |
| 115 | + |
| 116 | +- `signature` is the signed `merkleRoot` |
| 117 | +- `verificationMethod` is the DID controller. |
| 118 | + |
| 119 | +That's all the information that we need to verify that the document has been signed with the correct private key. Indeed,`ethr` DID uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) with [Secp256k1](https://en.bitcoin.it/wiki/Secp256k1) as parameter of the elliptic curve which provides an interesting property: when we verify a signature, using the initial value (`merkleRoot`), and the signed value (`signature`) it will recover the ethereum address associated with the private key used. We can then compare the ethereum address from the DID document, with the ethereum address returned by the verification. If it matches, the signature is valid. |
| 120 | + |
| 121 | +If you want to dig more on ECDSA, you can read this guide from [Yos Riady](https://yos.io/2018/11/16/ethereum-signatures/). |
| 122 | + |
| 123 | +### Revocation |
| 124 | + |
| 125 | +At the moment, there are no ways to revoke documents issued using DIDs. |
| 126 | + |
| 127 | +### Issuance process and verification |
| 128 | + |
| 129 | +To issue a document, an institution or individual : |
| 130 | + |
| 131 | +- [Creates a new ethr DID](/docs/verifiable-document/did/create) (this action needs to be performed only once) and get the private key and the public address. |
| 132 | +- Adds the DID address and controller into the document (before wrapping). |
| 133 | +- Wraps a document and get a `merkleRoot`. |
| 134 | +- Sign the `merkleRoot` using the private key. The signature must be appended into the wrapped document. |
| 135 | +- The wrapped document can be shared to the recipients. |
| 136 | + |
| 137 | +An OpenAttestation verifier: |
| 138 | + |
| 139 | +- Retrieves the ethereum address associated with the DID identifier and DID controller from the document. |
| 140 | +- Retrieves the ethereum used to sign the merkle root. |
| 141 | +- Makes sure both addresses match. |
0 commit comments