|
| 1 | +# How Credential Revocation Works |
| 2 | + |
| 3 | +This doc aims to explain credential revocation at a conceptual level. |
| 4 | +If this doc still feels too low-level, you might consider watching [this |
| 5 | +introductory video](https://drive.google.com/open?id=1FxdgkYwwLfpln6MnsZJAwnYjM6LpCoP0) from time offset 0:30 to 4:30. |
| 6 | + |
| 7 | +## Background: Cryptographic Accumulators |
| 8 | + |
| 9 | +Before explaining the mechanism in detail, it's necessary to understand |
| 10 | +__cryptographic accumulators__ at a very high level. |
| 11 | +We will try to avoid daunting math in our explanation. |
| 12 | + |
| 13 | +You can think of an accumulator as the product of multiplying many numbers |
| 14 | +together. In the equation `a * b * c * d = ` __`e`__, |
| 15 | +the accumulator would be __`e`__; |
| 16 | +it _accumulates_ a value as each new factor is multiplied in. We could |
| 17 | +plug in numbers; if `a`=2 and `b`=3 and `c`=5 and `d`=7, then our accumulator |
| 18 | +__`e`__ has a value of 210. If `e` has this value, we |
| 19 | +say that 3 is "in" `e` because it is a factor. If we want to take 3 out |
| 20 | +of the accumulator, we divide 210 by 3 and get 70 (=2*5*7); 3 has now been |
| 21 | +"removed". |
| 22 | + |
| 23 | +Notice that you can also produce __`e`__ by multiplying any single |
| 24 | +factor such as `a` by the product of all the other factors (`b * c * d`). |
| 25 | +This is a useful characteristic; it means you can tell someone else |
| 26 | +the value of `a` and _the product of all the other inputs to the accumulator, |
| 27 | +but not the other inputs themselves_, and they can produce the output. |
| 28 | + |
| 29 | +## Background: Tails Files |
| 30 | + |
| 31 | +In our simple example above, we only have 4 factors, and we are using small |
| 32 | +numbers. We are also using standard arithmetic, where you can reverse |
| 33 | +multiplication by dividing. In such a system, the contents of an accumulator |
| 34 | +can be reverse-engineered by simple prime factorization. |
| 35 | + |
| 36 | +To be useful for revocation, Indy's accumulators can't be reversible; that is, |
| 37 | +it must be the case that the only way to derive the accumulator |
| 38 | +value is to know the factors. |
| 39 | +We accomplish this by using modular arithmetic (where division is undefined), |
| 40 | +and by using massive numbers for the factors and accumulators. |
| 41 | + |
| 42 | +A __tails file__ is associated with an accumulator |
| 43 | +and its factors. It is a binary file that contains an |
| 44 | +array of randomly generated factors for an accumulator. Instead of small |
| 45 | +numbers like 2 and 3 and 7, these factors are massive numbers, far too |
| 46 | +big to display conveniently on a screen. Typically the quantity of these |
| 47 | +numeric factors in a tails file is large--hundreds of thousands to tens of |
| 48 | +millions. |
| 49 | + |
| 50 | +A tails file is not secret; it is published as plain text to the world |
| 51 | +and freely downloadable by anyone. The contents of this file never change. |
| 52 | + |
| 53 | +Each potential or actual credential issued by a particular issuer is |
| 54 | +assigned an index to an accumulator factor in a tails file. However, |
| 55 | +only credentials that have not been revoked contribute to the value of the |
| 56 | +accumulator. We will see how this works, below. |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +## Setup |
| 61 | + |
| 62 | +Before revocable credentials can be issued, a number of things must be |
| 63 | +true about the ecosystem: |
| 64 | + |
| 65 | +1. A __schema__ for each credential type |
| 66 | + must be written to the ledger. |
| 67 | + For example, if companies wish to issue proof of employment, then |
| 68 | + a "Employee Credential" schema would need to be published. Similarly, |
| 69 | + before birth certificate credentials can be issued, a "Birth Certificate" |
| 70 | + schema would need to be defined and made available to the public. Any number |
| 71 | + of issuers can reference the same schema. Schemas can be versioned and |
| 72 | + evolved over time. Any individual or institution can write a schema |
| 73 | + to the ledger; it does not require special privileges. |
| 74 | + |
| 75 | +2. Each issuer must publish on the ledger one __credential |
| 76 | + definition__ for each credential type they intend |
| 77 | + to create. The definition announces the issuer's intention to |
| 78 | + create credentials that match a particular schema, and specifies the |
| 79 | + keys that the issuer will use to sign such credentials. (The verkey+ |
| 80 | + signing key pair used to authenticate the issuer's DID should be kept |
| 81 | + separate from the keys used to sign credentials, so that each key |
| 82 | + pair can be rotated independently; it would be bad if a sysadmin |
| 83 | + rotated a DID keypair and accidentally invalidated all credentials |
| 84 | + issued by an institution...) |
| 85 | + |
| 86 | +3. Each issuer must also publish on the ledger a __revocation |
| 87 | + registry__. This metadata references a credential definition and |
| 88 | + specifies how revocation for that credential type will be handled. |
| 89 | + The revocation registry tells which cryptographic __accumulator__ |
| 90 | + can be used to test revocation, and gives the URI and |
| 91 | + hash of the associated __tails file__. |
| 92 | + |
| 93 | +4. Each issuer must publish on the ledger an accumulator value that |
| 94 | + describes the revocation status for all associated credentials. This |
| 95 | + accumulator must be updated on a periodic or as-needed basis. For |
| 96 | + example, if a driver's license division revokes 3 licenses during a |
| 97 | + given work day, then when they close their doors at 5 pm, they might |
| 98 | + issue a ledger transaction that updates the accumulator value for |
| 99 | + their driver's license credentials, removing the 3 revoked credentials |
| 100 | + from the accumulator. What we mean by "removing" is as described above-- |
| 101 | + the factors listed in the tails file for the indexes associated with |
| 102 | + the 3 revoked credentials are no longer multiplied into the accumulator. |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | +## How Revocation Will Be Tested |
| 107 | + |
| 108 | +Let us now skip ahead to think about what needs to happen much later. |
| 109 | +When a prover gives proof to a verifier, we normally think about the proof |
| 110 | +as focusing on core information demands: _What is your birthdate?_ _Please |
| 111 | +disclose your address_. This is __primary proof__. |
| 112 | + |
| 113 | +But there is another dimension of proof that's also necessary: _The prover |
| 114 | +must demonstrate that the credentials behind the primary proof have not |
| 115 | +been revoked._ This is called __proof of non-revocation__. |
| 116 | + |
| 117 | +In Indy, proof of non-revocation is accomplished by having provers show |
| 118 | +that they can derive the value of the accumulator for their credential |
| 119 | +using a factor for the accumulator that they know, plus the product of |
| 120 | +all other factors. |
| 121 | +The verifier can see that the prover produces the right answer (because |
| 122 | +the answer is on the ledger), but does not know certain details of how the |
| 123 | +prover derived it. The issuer can revoke by changing the answer to the |
| 124 | +math problem in a way that defeats the prover. |
| 125 | + |
| 126 | +## Preparing for Revocation at Issuance |
| 127 | + |
| 128 | +When a credential is issued, the actual credential file is transmitted |
| 129 | +to the holder (who will later become a prover). In addition, the issuer |
| 130 | +communicates two other pieces of vital information: |
| 131 | + |
| 132 | +* The index corresponding to this credential, in the tails file. This |
| 133 | + lets the holder look up their private factor, which we could map to |
| 134 | + `a` in the simple equation from the accumulator background section |
| 135 | + at the top of the doc. |
| 136 | +* The product of the _other_ factors contributing to the accumulator (all |
| 137 | + factors except the private one for this credential). |
| 138 | + This value is like `b * c * d` from the simple equation above, and |
| 139 | + is called a __witness__. |
| 140 | + |
| 141 | +## Presenting Proof of Non-Revocation |
| 142 | + |
| 143 | +When the prover needs to demonstrate that her credential is not revoked, |
| 144 | +she shows that she can provide math that derives the accumulator value |
| 145 | +on the ledger using her private factor times the witness. She does this |
| 146 | +without actually disclosing what her private value is; this is important |
| 147 | +to avoid correlation. |
| 148 | + |
| 149 | +But there is a complication: what if the accumulator has changed value |
| 150 | +since the time the credential was issued? In this case, the private |
| 151 | +factor times the witness will not equal the accumulator... |
| 152 | + |
| 153 | +This is handled by requiring accumulator updates to also publish a |
| 154 | +__witness delta__ as part of the same transaction. |
| 155 | +This tells provers how to adjust their witness (referencing other indexes |
| 156 | +in the public tails file) to bring it back into |
| 157 | +harmony with the current value of the accumulator. Updating witnesses |
| 158 | +requires the prover (but not the verifier) to download the tails file. |
| 159 | + |
| 160 | +## Putting It All Together |
| 161 | + |
| 162 | +This discussion has suppressed some details. The math has been simplified, |
| 163 | +and we haven't discussed how an issuer copes with multiple tails files |
| 164 | +and revocation registries, or why that might be desirable. However, the |
| 165 | +broad flow of the mechanism should be apparent, and its features are |
| 166 | +now easy to summarize: |
| 167 | + |
| 168 | +* Issuers revoke by changing a number on the ledger. They can revoke |
| 169 | + as many credentials as they want in a single transaction, since |
| 170 | + they are just changing the answer to a math problem that either does |
| 171 | + or doesn't include the factors they choose. Issuers do not have to |
| 172 | + contact anybody--provers or verifiers--to revoke. Changes take place |
| 173 | + globally, the instant the accumulator update transaction appears |
| 174 | + on the ledger. |
| 175 | +* Revocation is reversible. |
| 176 | +* Provers demonstrate proof of non-revocation in a privacy-preserving |
| 177 | + way. They cannot be correlated by something like a credential ID or |
| 178 | + a tails index. This is radically different from a revocation list |
| 179 | + approach, which requires correlation to test. |
| 180 | +* Verification of proof of non-revocation is extremely easy and cheap. |
| 181 | + No tails files are needed by verifiers, and computation is trivial. |
| 182 | + Proving non-revocation is somewhat more expensive for provers, but |
| 183 | + is also not overly complex. |
| 184 | +* Verifiers do not need to contact issuers or consult a revocation list |
| 185 | + to test revocation. |
0 commit comments