|
| 1 | +# RFC: Identity Proofs |
| 2 | + |
| 3 | +* Author: @kim |
| 4 | +* Date: 2021-02-23 |
| 5 | +* Status: draft |
| 6 | +* Community discussion: n/a |
| 7 | + |
| 8 | +## Motivation |
| 9 | + |
| 10 | +A `radicle-link` [identity][ids] is a hash-linked sequence of signed statements |
| 11 | +about public-key delegations: if an entry in this sequence is found to conform |
| 12 | +to a quorum rule of cryptographic signatures, the set of keys it delegates to |
| 13 | +can be considered trustworthy _iff_ the previous set was. Yet, how can we trust |
| 14 | +the initial set of keys in this chain? |
| 15 | + |
| 16 | +## Overview |
| 17 | + |
| 18 | +We consider it impractical for most participants in the `radicle-link` network |
| 19 | +to exchange public keys out-of-band, given a pattern of casual interaction with |
| 20 | +others. While the protocol mandates connections between participants, similar to |
| 21 | +"following" relationships found in social media, we thus consider it |
| 22 | +insufficient to infer a [web of trust][wot] from those relationships. |
| 23 | + |
| 24 | +To lift the requirement for physical authenticity checks, but still increase |
| 25 | +confidence of a given public key being associated with a particular person, |
| 26 | +[keybase] have popularised a scheme dubbed "Social Proofs": a statement claiming |
| 27 | +ownership of a particular account on a social media site is written to the |
| 28 | +keybase "sigchain" (which has properties similar to a `radicle-link` identity). |
| 29 | +This claim (implying also the history of the sigchain) is signed using a key |
| 30 | +currently valid according to the chain, and the signature (along with the public |
| 31 | +key) is stored at the social media site. To verify the claim, the signature is |
| 32 | +retrieved from the social media site in such a way that it could _plausibly_ |
| 33 | +only be created by the owner of the claimed account. If both the sigchain |
| 34 | +integrity and the claim signature can be verified, the association is proven. |
| 35 | + |
| 36 | +This mechanism can be considered a practical application of the [Turing test]: |
| 37 | +even though it can not be proven beyond doubt that the account is indeed |
| 38 | +associated with a real person, the evidence of others accepting it as such, as |
| 39 | +well as conversational behaviour, can increase the confidence in the |
| 40 | +authenticity of the online persona. Because key and account ownership at a given |
| 41 | +point in time can be cryptographically verified, this confidence can be extended |
| 42 | +to the proving side. |
| 43 | + |
| 44 | +We conclude that this mechanism would be a good fit for `radicle-link` (due to |
| 45 | +the similarities), and a desirable feature of applications built on top of it. |
| 46 | + |
| 47 | +The following sections describe how such claims shall be stored in the identity |
| 48 | +payload of a `radicle-link` identity, how to obtain a publishable proof, and how |
| 49 | +to verify it. |
| 50 | + |
| 51 | +## Claims |
| 52 | + |
| 53 | +Claims can only be made by identities of kind `Person`, and claim a single |
| 54 | +external account identifier. They are introduced by defining a new payload type, |
| 55 | +identified by the URL: |
| 56 | + |
| 57 | + https://radicle.xyz/link/claim/v1 |
| 58 | + |
| 59 | +The shape of the JSON structure is: |
| 60 | + |
| 61 | +```json |
| 62 | +{ |
| 63 | + "service": { |
| 64 | + "name": "STRING", |
| 65 | + "account": "STRING" |
| 66 | + }, |
| 67 | + "expiration": { |
| 68 | + "created": INTEGER, |
| 69 | + "expires": INTEGER |
| 70 | + }, |
| 71 | + "proof": "URL" |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +Where the fields denote: |
| 76 | + |
| 77 | +* `service` |
| 78 | + * `name` |
| 79 | + |
| 80 | + A conventional identifier of the external service, e.g. "github", |
| 81 | + "twitter", "radicle-ethereum" |
| 82 | + |
| 83 | + * `account` |
| 84 | + |
| 85 | + The unique account identifier within the service, using the service- |
| 86 | + specific canonical string representation e.g. "kim", |
| 87 | + "0x32be343b94f860124dc4fee278fdcbd38c102d88". |
| 88 | + |
| 89 | +* `expiration` (optional) |
| 90 | + * `created` |
| 91 | + |
| 92 | + Creation timestamp of the claim, in seconds since 1970-01-01T00:00:00Z. |
| 93 | + |
| 94 | + * `expires` |
| 95 | + |
| 96 | + Seconds relative to `created`, after which the claim should no longer be |
| 97 | + considered. |
| 98 | + |
| 99 | +* `proof` (optional) |
| 100 | + |
| 101 | + A URL to assist verification tooling in retrieving the proof from the external |
| 102 | + system. This is mainly a convenience, and obviously requires creation of a new |
| 103 | + revision after the fact. |
| 104 | + |
| 105 | +## Proof Generation |
| 106 | + |
| 107 | +The above claim payload is committed to the identity history as a new revision. |
| 108 | +Technically, this revision needs to be approved by all key delegations for |
| 109 | +verification to pass later on, but since we assume that eligible keys are held |
| 110 | +by the same person, it may be acceptable to publish the proof right away for |
| 111 | +user experience reasons. |
| 112 | + |
| 113 | +The actual proof consists of the following tuple: |
| 114 | + |
| 115 | + (root, revision, public key, signature) |
| 116 | + |
| 117 | +> TODO: include a protocol bit (denoting "git"), for forwards compat? |
| 118 | +
|
| 119 | +The values `root`, `revision`, and `public key` are specified in |
| 120 | +[identities][ids], and it is RECOMMENDED to follow the serialisation formats |
| 121 | +devised there. `signature` is the Ed25519 signature over `revision`, in much the |
| 122 | +same way as the actual revision is signed. All values can thus be obtained by |
| 123 | +inspecting the identity storage. |
| 124 | + |
| 125 | +It is beyond the scope of this document to devise the exact external format to |
| 126 | +serialise the tuple into, as this is expected to vary from service to service. |
| 127 | + |
| 128 | +## Revocation |
| 129 | + |
| 130 | +A claim can be revoked by creating a new identity revision which simply does not |
| 131 | +contain the claim payload. Likewise, a later claim describing the same `(service |
| 132 | +name, account)` mapping invalidates an earlier one. |
| 133 | + |
| 134 | +> NOTE: claiming multiple accounts per service is permissible in principle, but |
| 135 | +> might be undesirable for certain services. In this case, service-specific |
| 136 | +> post-validation is required. |
| 137 | +
|
| 138 | +## Verification |
| 139 | + |
| 140 | +1. Given the 4-tuple specified [above][#proof-generation], it is first verified |
| 141 | + that the signature is valid for the given `revision` and `public key`. |
| 142 | + |
| 143 | +2. If it is, the identity history needs to be resolved from local storage, or |
| 144 | + the network. |
| 145 | + |
| 146 | + 2.1 If persistence of verification results is available, the identity document |
| 147 | + at the given `revision` is retrieved, its `root` compared against the |
| 148 | + supplied one, and it is verified that the given `public key` is a member |
| 149 | + of the `delegations` set. If expiration is specified in the claim, it is |
| 150 | + determined if `expiration` seconds already elapsed since `created` |
| 151 | + according to the clock, in which case verification fails. |
| 152 | + 2.2 Otherwise, the identity verification procedure is run first, after which |
| 153 | + the history is walked backwards until the `revision` is found. Then, step |
| 154 | + 2.1 is performed. |
| 155 | + |
| 156 | +3. Lastly, the identity history needs to be examined for revocations. |
| 157 | + |
| 158 | +## Discussion |
| 159 | + |
| 160 | +The inclusion of the `revision` in the proof allows to assert that `root` is |
| 161 | +indeed an ancestor, which opens up another way to detect "forks" of the identity |
| 162 | +history: due to the peer-to-peer nature of the `radicle-link` network, it is |
| 163 | +vulnerable to attacks which involve withholding data from other participants, in |
| 164 | +which case a fork may go unnoticed. |
| 165 | + |
| 166 | +It should be noted, however, that refreshing the proof from time to time in |
| 167 | +order to ensure freshness of the data retrieved through `radicle-link` is not |
| 168 | +always practicable. |
| 169 | + |
| 170 | +In order to prove that the(ir own) server is not lying by omission, Keybase |
| 171 | +[anchors a merkle root][keybase-stellar] on a blockchain, which includes all |
| 172 | +sigchains registered in the Keybase directory. Because `radicle-link` does not |
| 173 | +have such a central directory, this approach could only be applied to a partial |
| 174 | +view of the network. |
| 175 | + |
| 176 | +While conceivable that, given the right incentives, such a directory service |
| 177 | +could be operated independently (similar to what the [ceramic] network devises), |
| 178 | +it is unclear what value blockchain anchors of individual identities have, given |
| 179 | +that transaction costs discourage frequent updates. |
| 180 | + |
| 181 | +It has also been proposed to employ a mutual attestation scheme with a |
| 182 | +blockchain (namely the [radicle-contracts]), but we haven't been able to |
| 183 | +convince ourselves that this is practical (or even beneficial) because: |
| 184 | + |
| 185 | +1. the verification obligation becomes more complex |
| 186 | +2. the creation procedure becomes more complex |
| 187 | +3. it is unclear what to do in case of conflicting statements (in the presence |
| 188 | + of revocations) |
| 189 | +4. the lying by omission problem is not solved, due to the disincentive to |
| 190 | + refresh proofs |
| 191 | + |
| 192 | +We thus RECOMMEND to either: |
| 193 | + |
| 194 | +* incentivise bulk anchoring |
| 195 | + |
| 196 | +* integrate with an existing bulk anchoring service |
| 197 | + |
| 198 | + Note that in this case the external service becomes authoritative, and no |
| 199 | + extension to the `radicle-link` protocol as described here is necessary. |
| 200 | + |
| 201 | +* treat "web3"- like any other web-service |
| 202 | + |
| 203 | + This may entail finding ways to reduce costs, for example by storing the proof |
| 204 | + payload in transaction logs (which can be verified separately). |
| 205 | + |
| 206 | +--- |
| 207 | + |
| 208 | +[ids]: ../spec/identities.md |
| 209 | +[wot]: https://en.wikipedia.org/wiki/Web_of_trust |
| 210 | +[keybase]: https://keybase.io |
| 211 | +[tt]: https://en.wikipedia.org/wiki/Turing_test |
| 212 | +[keybase-stellar]: https://book.keybase.io/docs/server/stellar |
| 213 | +[ceramic]: https://github.com/ceramicnetwork/ceramic/blob/master/SPECIFICATION.md#blockchain-anchoring |
| 214 | +[radicle-contracts]: https://github.com/radicle-dev/radicle-contracts |
0 commit comments