Skip to content
This repository was archived by the owner on Apr 16, 2025. It is now read-only.

Commit b27d30b

Browse files
committed
RFC: Identity Proofs
Signed-off-by: Kim Altintop <[email protected]>
1 parent cadaf46 commit b27d30b

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

docs/rfc/identity_proofs.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
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
37+
test][tt]: even though it can not be proven beyond doubt that the account is
38+
indeed associated with a real person, the evidence of others accepting it as
39+
such, as 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+
"account": "STRING"
65+
"expiration": {
66+
"created": INTEGER,
67+
"expires": INTEGER
68+
},
69+
"proof": "URL"
70+
}
71+
}
72+
```
73+
74+
Where the fields denote:
75+
76+
* `SERVICE`
77+
78+
A conventional identifier of the external service, e.g. "github", "twitter",
79+
"radicle-ethereum"
80+
81+
* `account`
82+
83+
The unique account identifier within the service, using the service-specific
84+
canonical string representation e.g. "kim", "0x32be343b94f860124dc4fee278fdcbd38c102d88".
85+
86+
* `expiration` (optional)
87+
* `created`
88+
89+
Creation timestamp of the claim, in seconds since 1970-01-01T00:00:00Z.
90+
91+
* `expires`
92+
93+
Seconds relative to `created`, after which the claim should no longer be
94+
considered.
95+
96+
* `proof` (optional)
97+
98+
A URL to assist verification tooling in retrieving the proof from the external
99+
system. This is mainly a convenience, and obviously requires creation of a new
100+
revision after the fact.
101+
102+
## Proof Generation
103+
104+
The above claim payload is committed to the identity history as a new revision.
105+
Technically, this revision needs to be approved by all key delegations for
106+
verification to pass later on, but since we assume that eligible keys are held
107+
by the same person, it may be acceptable to publish the proof right away for
108+
user experience reasons.
109+
110+
The actual proof consists of the following tuple:
111+
112+
(root, revision, public-key, signature)
113+
114+
Note that the "git" protocol specifier of `radicle-link` URNs is implied, that
115+
is, future version MUST treat the absence of a disambiguating value as denoting
116+
"git".
117+
118+
The values `root`, `revision`, and `public-key` are specified in
119+
[identities][ids], and it is RECOMMENDED to follow the serialisation formats
120+
devised there. `signature` is the Ed25519 signature over `revision`, in much the
121+
same way as the actual revision is signed. All values can thus be obtained by
122+
inspecting the identity storage.
123+
124+
It is beyond the scope of this document to devise the exact external format to
125+
serialise the tuple into, as this is expected to vary from service to service.
126+
127+
## Revocation
128+
129+
A claim can be revoked by creating a new identity revision which simply does not
130+
contain the claim payload. Likewise, a later claim describing the same `SERVICE`
131+
invalidates an earlier one.
132+
133+
## Verification
134+
135+
Inputs: the 4-tuple as specified [above](#proof-generation), and the `SERVICE`
136+
as inferred from the source it was retrieved from.
137+
138+
1. Given the 4-tuple specified, it is first verified that the signature is valid
139+
for the given `revision` and `public-key`.
140+
141+
2. If it is, the identity history needs to be resolved from local storage, or
142+
the network.
143+
144+
Using `git` storage, the history tip should be located at
145+
146+
refs/namespaces/<root>/refs/remotes/<public-key>/rad/id
147+
148+
substituting `<root>` and `<public-key>` with their respective encodings as
149+
defined in [`Identities`][ids].
150+
151+
3. If the history tip could be resolved, the identity MUST be verified as per
152+
[`Identities`][ids]. If this fails, the proof is rejected.
153+
154+
4. If the identity could be verified, the identity document is read from its
155+
latest valid tip (recall that this is not necessarily the same as what the
156+
ref points to). The proof is rejected if one of the following is true:
157+
158+
4.1 `root` does not match
159+
4.2 the document does not contain a claim for `SERVICE`
160+
4.3 the document contains a claim for `SERVICE`, has an `expiration`, and
161+
`expiration.expires` is smaller than `time() - expiration.created`
162+
163+
5. Lastly, the identity history is walked backwards until `revision` is found
164+
(or else, the proof is rejected). The proof is accepted _iff_ all of the
165+
following are true:
166+
167+
5.1 the document's `delegations` at `revision` contain `public-key`
168+
5.2 the document at `revision` contains a claim for `SERVICE`, and the claim
169+
is not expired as described in 4.3
170+
171+
Note that steps 3.-5. can be optimised by persisting verification results, or by
172+
adding an additional accumulator to the verification fold which yields the
173+
targeted `revision`.
174+
175+
## Discussion
176+
177+
The inclusion of the `revision` in the proof allows to assert that `root` is
178+
indeed an ancestor, which opens up another way to detect "forks" of the identity
179+
history: due to the peer-to-peer nature of the `radicle-link` network, it is
180+
vulnerable to attacks which involve withholding data from other participants, in
181+
which case a fork may go unnoticed.
182+
183+
It should be noted, however, that refreshing the proof from time to time in
184+
order to ensure freshness of the data retrieved through `radicle-link` is not
185+
always practicable.
186+
187+
In order to prove that the(ir own) server is not lying by omission, Keybase
188+
[anchors a merkle root][keybase-stellar] on a blockchain, which includes all
189+
sigchains registered in the Keybase directory. Because `radicle-link` does not
190+
have such a central directory, this approach could only be applied to a partial
191+
view of the network.
192+
193+
While conceivable that, given the right incentives, such a directory service
194+
could be operated independently (similar to what the [ceramic] network devises),
195+
it is unclear what value blockchain anchors of individual identities have, given
196+
that transaction costs discourage frequent updates.
197+
198+
It has also been proposed to employ a mutual attestation scheme with a
199+
blockchain (namely the [radicle-contracts]), but we haven't been able to
200+
convince ourselves that this is practical (or even beneficial) because:
201+
202+
1. the verification obligation becomes more complex
203+
2. the creation procedure becomes more complex
204+
3. it is unclear what to do in case of conflicting statements (in the presence
205+
of revocations)
206+
4. the lying by omission problem is not solved, due to the disincentive to
207+
refresh proofs
208+
209+
We thus RECOMMEND to either:
210+
211+
* incentivise bulk anchoring
212+
213+
* integrate with an existing bulk anchoring service
214+
215+
Note that in this case the external service becomes authoritative, and no
216+
extension to the `radicle-link` protocol as described here is necessary.
217+
218+
* treat "web3"- like any other web-service
219+
220+
This may entail finding ways to reduce costs, for example by storing the proof
221+
payload in transaction logs (which can be verified separately).
222+
223+
---
224+
225+
[ids]: ../spec/identities.md
226+
[wot]: https://en.wikipedia.org/wiki/Web_of_trust
227+
[keybase]: https://keybase.io
228+
[tt]: https://en.wikipedia.org/wiki/Turing_test
229+
[keybase-stellar]: https://book.keybase.io/docs/server/stellar
230+
[ceramic]: https://github.com/ceramicnetwork/ceramic/blob/master/SPECIFICATION.md#blockchain-anchoring
231+
[radicle-contracts]: https://github.com/radicle-dev/radicle-contracts

0 commit comments

Comments
 (0)