forked from openssi/peer-did-method-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
724 lines (679 loc) · 47.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Peer DID Method Specification</title>
<style>
#instructions {
border: dashed 1px black;
padding: 1em;
background-color:#d0d0d0;
}
.replace-me {
font-style:italic;
color:magenta
}
</style>
<script
src='https://www.w3.org/Tools/respec/respec-w3c-common'
class='remove'></script>
<script class='remove'>
var respecConfig = {
specStatus: "ED",
editors: [{
name: "Daniel Hardman",
url: "https://github.com/dhh1128"
},
{
name: "Sam Curren",
url: "https://github.com/TelegramSam"
},
{
name: "Devin Fisher",
url: "https://github.com/devin-fisher"
},
{
name: "Tobias Looker",
url: "https://github.com/tplooker"
}
],
processVersion: 2017,
edDraftURI: "https://github.com/openssi/peer-did-method-spec",
shortName: "peer",
subtitle: "A blockchain-agnostic decentralized identifier method",
github: "https://github.com/openssi/peer-did-method-spec",
wg: "greater SSI community"
};
</script>
</head>
<body>
<section class="introductory">
<h2>About</h2>
<p>This <a href="https://w3c-ccg.github.io/did-spec/#specific-did-method-schemes">DID method spec</a> conforms
to the requirements in the DID specification currently published by the W3C Credentials Community Group.
For more information about DIDs and DID method specifications, please see the <a
href="http://bit.ly/2RX0xm2" target="_blank">DID Primer</a>
and <a href="https://w3c-ccg.github.io/did-spec/">DID Spec</a>.</p>
</section>
<section id='abstract'>
<p>This document defines a "peer" <a href="https://w3c-ccg.github.io/did-spec/#specific-did-method-schemes">DID Method</a>
that can be used independent of any central source of truth. The method is intended to be cheap, fast, scalable,
and secure. It is suitable for most private relationships between people, organizations, and things.
DIDs associated with this method are also promotable to a more public context. That is, blockchains with
different DID methods could choose to graft some or all peer DIDs into their namespace(s) with no risk of accidental
collision, and no loss of meaning. A particular peer DID would have a recognizable and consistent identity
in all of them.
</p>
<p>We expect that peer-to-peer relationships in every blockchain ecosystem can benefit by offloading pairwise
and n-wise relationships to peer DIDs.
</p>
</section>
<section id='sotd'>
<p>
</p>
</section>
<section>
<h1>Introduction</h1>
<p>Most introductions to DIDs describe them as identifiers that are rooted in a public source of truth like a
blockchain, a database, a distributed filesystem, or similar. This publicness lets arbitrary parties resolve
the DIDs to an endpoint and keys. It is an important feature for many use cases.</p>
<p>However, the vast majority of relationships between people, organizations, and things are simpler. When
Alice(Corp|Device) and Bob want to interact, there are exactly and only 2 parties in the world who should
care: Alice and Bob. We call these parties "peers" because there is an equality rather than a hierarchy
to them, at least insofar as their DID management is concerned. Letting the world resolve the identifiers
and keys that only peers care about is unnecessary, and it represents a privacy and security risk as well
as a problem of cost, scale, and performance.</p>
<section>
<h2>DIDs as Pseudonyms</h2>
<p>
DIDs are by nature pseudonyms, in the sense that an entity can use a DID as an alias for themselves in
some context i.e a relationship. Therefore the different forms of a DID acting as a pseudonym can be
defined in three ways.
</p>
<ol>
<li>
<em>
Pairwise DID - A DID with the intent that it is known by exactly one other.
</em>
</li>
<li>
<em>
N-wise DID - A DID with the intent that it is known by exactly n parties, where each of the n parties are known.
</em>
</li>
<li>
<em>
Anywise DID - A DID where by the number of known parties is un-bounded, i.e the DID is publically resolvable and hence can be known by anyone.
</em>
</li>
</ol>
<p>
The omnipresence of peer relationships raises the possibility of DIDs that are only resolvable and usable
by peers within the context of a given relationship. Such pairwise or n-wise identifiers can still have
all the other characteristics that make DIDs useful -- DID Documents, endpoints, keys, authorizations,
interoperability, and tooling.
</p>
<blockquote><p><em>Terminology note</em>: as used in this spec, "peer DID" means a DID that uses the "did:peer"
DID method we're defining. Such DIDs are often pairwise, but "pairwise DID" is not a synonym, since peer DIDs
can also be used to model n-wise relationships. Similarly, "peer DID" is not intended to be a synonym for a
DID that is not publicly resolvable. Many different approaches to such DIDs might exist; "peer DID" is just
the name for the approach described here.</p>
</blockquote>
</section>
<section>
<h3>Guarantees</h3>
<p>This spec uses a protocol, rather than a public oracle, as the root of trust. It is worthy
of trust because it guarantees the following properties:</p>
<ol>
<li><em>DIDs are associated with a key pair at the moment of creation</em>. This prevents a
category of man-in-the-middle attacks where an attacker could rotate a DID's keys
at the outset of a relationship unbeknownst to peers.</li>
<li><em>DIDs have an acceptable level of uniqueness.</em> This is NOT a guarantee that DIDs will
never be reused by their owner, NOR is it a guarantee that collusion cannot subvert uniqueness.
Thus, it is not a uniqueness upon which deep trust can be based.
Rather, it is a guarantee that good behavior will not produce accidental collisions. In this
sense, it is rather like the uniqueness offered by NATing mechanisms in IPv4. It provides
enough uniqueness that a DID can be used as an index in a database or as a routing target
in DID communication. It also makes it possible for blockchains to "adopt" a peer DID
by mapping it into their namespace, without incurring the risk of ambiguity. Any time a peer
DID is discovered to be less than unique, a true problem exists and systems can fairly
raise an exception.
</li>
<li><em>The values of DIDs are securely random.</em> This prevents attackers from discovering patterns
in DIDs that might undermine privacy.</li>
<li><em>Parties to a relationship can prove the orderly and authorized evolution of their
keys to one another.</em></li>
</ol>
</section>
<section>
<h3>Advantages</h3>
<p>Peer DIDs are not suitable for anywise use cases, which are <a
href="http://bit.ly/2GaYWHN">usually public by intent</a>. However, peer DIDs have certain
virtues that make them desirable for private relationships between a small number of enumerable parties:</p>
<ul>
<li>They have no transaction costs, making them essentially free to create, store, and maintain.</li>
<li>They scale and perform entirely as a function of participants, not with any central system's capacity.</li>
<li>Because they are not persisted in any central system, there is no trove to protect.</li>
<li>Because only the parties to a given relationship know them, there is no concern about personal data and
privacy regulations due to third-party data controllers or processors.</li>
<li>Because they are not beholden to any particular blockchain, they have minimal political or technical
baggage.</li>
<li>They can be mapped into the namespaces of other DID ecosystems, allowing a peer DID to have
predictable meaning in 1 or more other blockchains. This solves a problem with blockchain forks
fighting over the ownership of a DID and promotes interoperability.</li>
</ul>
</section>
</section>
<section>
<h3>Comparison Peer DID with public-ledger-based DIDs</h3>
<p>Public-ledger-based DIDs (e.g. did:sov:...) could be used, in principle, for pairwise and
N-wise. The disadvantage of that is the associated registration and maintenance cost, as
the number of pairwise or n-wise relationships is likely to become large, even for small
organisations. Also privacy considerations make public-ledger-based DIDs less desirable for
pairwise and (small-scale) n-wise.</p>
<p>Similarly, Peer DID (did:peer:...) could be used, hypothetically, for public use. The main disadvantage
is the lack of a formal publication mechanism. Whereas nothing refrains a user to publish a Peer DID
and its associated DID Document on some website, such publication will be hard to discover, maintain
(DID Document roll-over) and integrate into interoperable applications. Public-ledger-based DIDs all
have their intrinsic and authoratitive publication mechanism, as identified by its DID method name.
</p>
</section>
<section>
<h2>Groups</h2>
<p>Most of this doc is framed by a pairwise Alice:Bob context. This sort of pair (no matter whether its
members are people, IoT devices, or institutions) will be the most common peer relationship in the SSI
landscape. Groups larger than 2 can also have a peer-style relationship--but not all groups will be
modeled that way. Therefore, applying this method to groups should be done thoughtfully.</p>
<p><a target="_blank" href="https://docs.google.com/document/d/17wn4zah37ATGXClWfbvTu07v_YmkDgQfGEWhBiROZBo/edit">
Some groups, such as Doctor+Hospital+Patient, are clearly n-wise</a>. Each party can enumerate all the
other parties, and each party uses the same identifier in all directions within the group. N-wise
groups are peer groups by definition: (see <a target="_blank"
href="https://github.com/hyperledger/indy-hipe/blob/master/text/0014-ssi-notation/README.md">
HIPE 0014</a> for help on the SSI notation used in this diagram).</p>
<img src="n-wise.png"/>
<p>N-wise groups often exist alongside pairwise relationships. For example, a 3-wise business
partnership between Alice, Bob, and Carol is probably preceded by pairwise relationships between
each of the parties. When the business is founded, a new 3-wise relationship is created, with the
parties allocating new DIDs, keys, and DID Docs to this relationship independent of the ones
they use in their pairwise friendships. This keeps business and personal relationships separate.
If a new partner is added, the 3-wise relationship can become 4-wise; if a partner dies, the
partnership can lose an active participant, but continue to recognize that party in the
relationship history. This shows the close affinity but also the separation between pairwise and
n-wise. For more details, see <a target="_blank"
href="https://docs.google.com/document/d/1BjYdivGQ9GxIz9CJ2ymNvMA68uHZm8bFOTyCHDmziOU/edit">this
exploratory doc</a>.</p>
<p>Groups can also be modeled with a hub-and-spoke model. That model is commonly used in group chats,
for example: each member of the group chat sends and receives via a central service, which in turn
broadcasts to all other members of the group. This hub-and-spoke model is actually just a pairwise
variant, because the relationship is between a member and the hub; all other relationships are only
indirect:</p>
<img src="hub-wise.png"/>
<p>We do not cover hub-and-spoke groups explicitly below. They are compatible with this method, if
reanalyzed as pairwise. Otherwise, the protocol may need adaptation.</p>
</section>
<section>
<h2>Enforcement</h2>
<p>In centralized systems, security is enforced at the center. This is so obvious that we take it for
granted--you can't access a database unless you log in first, and it's the database that enforces this.</p>
<p>Despite their other decentralized features, blockchains are no different in this respect. If a
blockchain accepts updates to a DID Doc, then the blockchain must guarantee that those updates are
only made by authorized parties. Thus, most DID methods imagine a blockchain parsing the
authorization section of a DID Doc, and rejecting mischief from hackers.</p>
<p>However, in a peer relationship, there IS no centralized authority. This leads to an interesting
inversion of responsibility that must be understood: Bob enforces Alice's authorization policy,
and Alice enforces Bob's.</p>
<p>This might seem wrong--shouldn't Alice enforce her own security? But it is quite rational. Who cares
whether the agents he is dealing with truly belong to Alice and are authorized by her? Bob does.
And if one of Alice's agents gets hacked and attempts to subvert the Alice:Bob relationship,
who is the uncontaminated party that can refuse to cooperate with the rogue agent? Bob is.</p>
<p>Another way to think about this is that, within the Alice:Bob relationship, Bob acts as a substitute
for a centralized resource that Alice's agents try to access. In such a mental model, of course, Bob
would be a logical place to enforce access rules for Alice.</p>
</section>
</section>
<section>
<h2>Core Characteristics</h2>
<section>
<h3>Namestring</h3>
<p>The namestring that shall identify this DID method is: <code>peer</code></p>
<p>A DID that uses this method MUST begin with the following prefix: <code>did:peer</code>.
Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix,
is the namespace specific identifier specified below.</p>
<p>Early feedback on this method suggested that we embed it beneath the namespace of a particular blockchain,
as in <code>did:sov:peer</code> or <a
target="_blank" href="https://w3c-ccg.github.io/didm-veres-one/#veres-one-did-format"><code>did:v1:nym</code></a>.
However, this DID method is not captive to any particular blockchain, does not take its resolution rules
from a parent method, and does not require anchoring or reference to a blockchain to be valid.
Furthermore, any direct or indirect anchoring of a peer DID to a specific blockchain is driven by
circumstance and changeable at any time. For example, a peer DID could specify that it is using
a dead drop on blockchain 1, then change to blockchain 2, then change to blockchains 3 and 4 at
the same time. Therefore, "peer" belongs at the top of the DID namespace. How this method may be
used in conjunction with various blockchains is discussed <a
href="#grafting-peer-dids-into-another-did-method-namespace">later</a>.</p>
</section>
<section>
<h3>Target System(s)</h3>
<p>This DID method applies to any identity management implementation that meets the following two
requirements:</p>
<ul>
<li><em>Cryptonyms</em> -- The DIDs are created using the <a href="#gen_method">algorithm described below</a>,
endowing them with properties vital to trust between peers that is not dependent on a central source of truth.</li>
<li><em>Protocol</em> -- The metadata for DIDs (what would be stored in an on-chain DID Doc in other methods)
is communicated as described below.</li>
</ul>
</section>
<section>
<h3>Namespace Specific Identifier (NSI)</h3>
<p><a name="gen_method"></a>
The Peer DID scheme is defined by the following <a href="ftp://ftp.rfc-editor.org/in-notes/std/std68.txt">ABNF</a>:<br><br>
<code>
peer-did = "did:peer:" keyfmtchar ":" idstring<br>
keyfmtchar = "1"<br>
idstring = 21*22base58char<br>
base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / "C"<br/>
/ "D" / "E" / "F" / "G" / "H" / "J" / "K" / "L" / "M" / "N" / "P" / "Q"<br/>
/ "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z" / "a" / "b" / "c"<br/>
/ "d" / "e" / "f" / "g" / "h" / "i" / "j" / "k" / "m" / "n" / "o" / "p"<br/>
/ "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / "y" / "z"<br>
</code><br>
<p>All Peer DIDs are base58 encoded values. The underlying number represented in base58 is a cryptographic
public key or a derivative (e.g., hash) thereof. For future extensibility, the scheme includes a key format
character field (<code>keyfmtchar</code>) that identifies the corresponding <code>idstring</code> to define
the length of the NSI.</p>
<p>At the time of this writing, only one <code>keyfmtchar</code> is defined. This is "1", denoting a format
where <code>idstring</code> is the upper 16 bytes of an Ed25519 public key. This gives <code>idstring</code>
a length of either 21 or 22 base58 characters. The encoding of <code>idstring</code> uses most alphas and digits,
omitting 0 (zero), O (capital o), I (capital i), and l (lower L) to avoid readability problems. Regardless of
the length of <code>idstring</code>, peer DIDs are case-sensitive and may not be case-normalized, even though
the prefix is always lower-case.</p>
<p>Note that this spec may be updated to include other <code>keyfmtchar</code> variants for
SecP256, Curve448, or similar. Such updates might change the length of <code>idstring</code> as well.</p>
</p>
</section>
<section>
<h3>Namestring Generation Method</h3>
<p>The unique numeric value underlying a Peer DID MUST be generated by using a cryptographically robust
algorithm with secure randomness to create an Ed25519 keypair (or, when additional formats are supported,
an analogous keypair on a different curve), and then selecting as the NSI a subset of the public
verification key that is at least 128 bits, and that is dependent on <code>keyfmtchar</code>. For
<code>keyfmtchar</code> = "1", the NSI = the most significant 16 bytes of the public verification key.</p>
<p>In this way, the DID can be known to begin its existence already associated with keys, and the controller
of the new DID can immediately assert they are the only entity in the world who possesses the private key.
This guarantees the initial integrity of the DID's chain of custody.
</p>
</section>
<section>
<h3>Examples</h3>
<p>A convenient regex to match <code>peer</code> DIDs is: <br><br>
<code>^did:peer:1:[1-9A-HJ-NP-Za-km-z]{21,22}$</code>.
</p>
<p>A valid <code>peer</code> DID might be: <code>did:peer:1:YTEFYzByfU2RwJPyULfLLn</code>.</p>
</section>
</section>
<section>
<h2>Protocol</h2>
<section>
<h3>Roles</h3>
<p>We call this the "peer" DID method because it enables peers--parties with no relative hierarchy--to
exchange DIDs without recourse to a central authority. Thus, we expect only one role in our
protocol: <code>peer</code>. And this is the case, at a high level.</p>
<p>However, at another level of detail, each peer may interact through various pieces of software
and hardware that proxy them. They may need to reveal a modest amount of information about such agents to
achieve cooperative security. For example, Alice may control 3 devices and may wish to protect
herself from hacking by saying that at least 2 of her existing devices must agree before a new
device can be added or an existing device can be revoked. This requires her to share her M-of-N
policy with Bob, with enough information about agent keys that he can validate a multi-party
digital signature. Thus, our protocol must occasionally contemplate details about this more
granular level of each peer's <a target="_blank"
href="https://docs.google.com/document/d/1gfIz5TT0cNp2kxGMLFXr19x1uoZsruUe_0glHst2fZ8/edit#heading=h.pufsrf9ucjvv">
sovereign domain</a>.</p>
</section>
<section>
<h3>Messages</h3>
<p><em>Peers interact via messages</em>. This is a more general claim than saying that peers expose an API
because it doesn't assume that peers are directly callable by each other. It must be possible to
exchange DIDs in this method in a very asynchronous fashion (e.g., one party sends a message while the
other party is offline; a response is returned when the original sender may not be actively listening).</p>
<p><em>Message transmission is transport-agnostic</em>. That is, the messages can flow over any combination
of HTTP, Bluetooth, NFC, email, AMPRNet (TCP/IP over ham radio), snail mail, sneakernet, intermediaries,
or future protocols we have not yet invented.</p>
<p><em>Messages are <a target="_blank" href="https://tools.ietf.org/html/rfc8259">JSON</a></em>. They are
compatible with <a target="_blank" href="https://w3c.github.io/json-ld-syntax/#basic-concepts">basic
concepts of JSON-LD</a>, but <a target="_blank"
href="https://github.com/hyperledger/indy-hipe/blob/64e16d3b/text/json-ld-compatibility/README.md">no
deep knowledge of JSON-LD is required to understand them, and no dependency
on JSON-LD libraries is necessary</a>. The specifics of JSON format are discussed below.</p>
<p><em>Messages are serialized and encrypted</em> in a standard way for transport. This method associates
security guarantees with the message envelope rather than the transport, and is aligned philosophically with
the approach of <a target="_blank" href="https://datatracker.ietf.org/wg/mls/about/">IETF's Message
Level Security initiative</a>. However, the first version of this spec predates MLS's maturity, so
the wire format uses <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc7516.txt">JWEs</a>
with some extensions, instead. The extensions allow the same message to be encrypted once for multiple
recipients and sent to them all in an efficient manner:</p>
<img src="multiplex.png"/>
<p>These extensions are under review by the
maintainers of JWE/JWT and are likely to be mainstreamed eventually.
The particulars are detailed in <a target="_blank"
href="https://github.com/hyperledger/indy-hipe/blob/master/text/0028-wire-message-format/README.md">
a doc</a> that explains how agents in the Hyperledger Indy ecosystem have implemented the format -
but the format is easy to implement without any Indy dependencies, and its design has no
connection to the Indy blockchain. See <a target="_blank"
href="https://github.com/dbluhm/indy-pack-unpack-js/blob/db9d83e4/index.js">this implementation
in pure javascript</a>, and <a target="_blank" href="https://github.com/bcgov/indy-catalyst/blob/bba2ef5c/agent/indy_catalyst_agent/wallet/crypto.py#L402">
this one in pure python</a>, in addition to
<a target="_blank" href="https://github.com/hyperledger/indy-sdk/blob/fbad7422/libindy/src/api/crypto.rs#L634">
Indy's C-callable implementation in Rust</a>.
</p>
<p>All JSON messages in this protocol are part of a "message family" named <code>connections</code>. This
family is identified by the following <a target="_blank" href="https://w3c-ccg.github.io/did-spec/#the-generic-did-scheme">DID
reference</a>:</p>
<pre>did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0</pre>
<p>Of course, subsequent evolutions of the message family will replace `1.0` with
an appropriate update per <a target="_blank" href="https://semver.org">semver</a> rules.</p>
</section>
<section>
<h3>CRUD Operations</h3>
<section>
<h4>Create (Register)</h4>
<p>Although the cryptographic operation of <em>creating</em> a peer DID and its first keypair can be done at
any time and does not require a message, <em>registering</em> a peer DID with the other party or parties in a
relationship involves a specific sequence of messages known as the <em>connection protocol</em>. The
protocol is <a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/b3f5c388/text/connection-protocol/README.md">
formally documented in a HIPE</a>; only a summary is offered here. It has 3 steps:</p>
<ol>
<li>One of the parties (the <em>inviter</em>) sends an <em>invitation</em> to connect. The
invitation is NOT encrypted, and it does NOT require the recipient (the <em>invitee</em>) to
have special software that understands this protocol. Instead, it is a specially formatted URI
that can be a deep link, helping the invitee to learn about SSI, get an SSI-capable app, and
otherwise onboard into the ecosystem. If the invitee already has SSI-aware software, the URI
can be recognized by a registered handler, short-circuiting the URI fetch and the onboarding/
learning process. This invitation URI may be transmitted by email, SMS, QR code, or any other
convenient method. If it is important to the inviter that it be secured, the inviter can share
the invitation on a secure channel.</li>
<li>The invitee sends an encrypted <em>connection request</em> back to the inviter, using the
endpoint that the inviter supplied in the invitation. This connection request includes the
invitee's DID Doc, DID, and keys.</li>
<li>The inviter sends an encrypted <em>connection response</em> the other direction. This response
includes the inviter's DID Doc, DID, and keys.</li>
</ol>
<p>These three steps have been carefully defined to achieve a number of important goals:</p>
<ul>
<li>Because the invitation can be sent to someone who does not know about DIDs or SSI at all,
and because it can be sent over insecure channels, establishing DID relationships has an
extremely low bar. This is vital to the virality of SSI.</li>
<li>The invitation identifies an endpoint over which the
connection can occur, but it does not communicate peer keys or a peer DID from the inviter,
and the endpoint that the inviter uses (as well as the inviter's DID and keys) are only
transmitted once security and privacy are guaranteed.</li>
<li>The protocol can be used by parties using any DID method. One of the parties can be using
a peer DID, both can, or neither can.</li>
<li>The invitation can be sent by a third party, allow introductions (Alice introduces Carol to Bob).
However, an introducer is prevented from seeing the secure and private connection built by the
two parties.</li>
</ul>
</section>
<section>
<h4>Read (Resolve)</h4>
<blockquote><p>(This operation, as well as Update and Delete, are documented in greater detail in
a <a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/19e22644/text/conn-mgmt-protocols/README.md">HIPE about connection management protocols</a>. Here, we offer only a summary.)</p></blockquote>
<p>A peer DID can be resolved to a DID Document by sending a <a
href="https://github.com/hyperledger/indy-hipe/blob/826ce818/text/conn-mgmt-protocols/README.md#state_request">state_request
</a> message from one peer to another:</p>
<pre>
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/state_request",
"@id": "6a4986dd-f50e-4ed5-a389-718e61517207",
"for": "did:peer:rjHiqAzCbsNYhMZDTUASHg",
"as_of_time": "2019-07-23 18:05:06.123Z"
}
</pre>
<p>The <code>as_of_time</code> property is optional and often omitted; if so, the DID Doc at
the current time is returned.</p>
<p>A <a href="https://github.com/hyperledger/indy-hipe/blob/826ce818/text/conn-mgmt-protocols/README.md#state_response">state_response
</a> message is returned. It includes a DID Doc and some additional metadata, and looks like this:
</p>
<pre>
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/relmgmt/1.0/state_response",
"@id": "1517207d-f50e-4ed5-a389-6a4986d718e6",
"~thread": { "thid": "6a4986dd-f50e-4ed5-a389-718e61517207" },
"for": "did:peer:1:rjHiqAzCbsNYhMZDTUASHg",
"did_doc": {
"@context": "https://w3id.org/did/v1",
"id": "did:peer:1:qQk1twjzCmEMgLDRNmo7oS",
"publicKey": [
{"id": "routing", "type": "Ed25519Verkey2018", "owner": "did:peer:1:rjHiqAzCbsNYhMZDTUASHg","publicKey": "4x6qAfCNrqQqEB3nS7Zfu7K8HH5gYEeNc3z7PYXmd54d"},
{"id": "1", "type": "Ed25519Verkey2018", "owner": "did:peer:1:rjHiqAzCbsNYhMZDTUASHg","publicKey": "Ar5P8bBr3vXMguTw3U14S6mN2rxrDsYV8Tt75FZ2ZTu4"}
],
"authentication": [
{"type": "Ed25519Verkey2018", "publicKey": "#1"}
],
"service": [
{"type": "Agency", "serviceEndpoint": "did:sov:Av1e1Cpu2MavT6QN8nuLJ4" }
]
},
"as_of_time": "2019-07-23 18:05:06.123Z"
} </pre>
<p>Note the use of <code>~thread</code> in the response, with <code>thid</code> equal to the
<code>@id</code> property of the previous request, to connect the two messages. This is a
<a target="_blank" href="https://github.com/hyperledger/indy-hipe/tree/master/text/0027-message-id-and-threading#threaded-messages">
standard message threading feature of DID Communication</a>, and also shows up in other
message interactions described here.</p>
</section>
<section>
<h4>Update</h4>
<p>The owner of a peer DID can update their associated DID Document with anyone who knows the
DID--one or more agents of the peer, or agents of the owner itself--by sending a <a
href="https://github.com/hyperledger/indy-hipe/blob/826ce818/text/conn-mgmt-protocols/README.md#sync_state">sync_state
</a> message to another peer. An example of this type of message is:</p>
<pre>
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/relmgmt/1.0/sync_state",
"@id": "e61586dd-f50e-4ed5-a389-716a49817207",
"for": "did:peer:1:rjHiqAzCbsNYhMZDTUASHg",
"base_hash": "d48f058771956a305e12a3b062a3ac81bd8653d7b1a88dd07db8f663f37bf8e0",
"base_hash_time": "2019-07-23 18:05:06.123Z",
"deltas": [
{
"ops": [
{
"op": "add_key",
"fragment": {
"id": "6", "type": "Ed25519Verkey2018",
"owner": "did:peer:1:EMmo7oSqQk1twmgLDRNjzC",
"publicKey": "DjbU8jgf1MjGWu6hGwr4N4EoAfhfTjutjWc8fgdxb3QP"
}
},
{
"op": "remove_key",
"fragment": {"id": "5"}
}
],
"delta_time": "2019-07:23 19:00:01",
"result_hash": "058771956a305e12a3b062a3ac81d48fbd8653d7f663f37bf8e0b1a88dd07db8",
"proofs": [
{
"by": "#4",
"signature": "MIIB6gYJKoZIhvcNAQcCoIIB2zCCAdcCAQE...wYDVQQKEwR"
}
]
}
]
}
</pre>
<p>This message does not follow a simple request~response pattern, and does not have "update"
in its name, because either party
may know details that the other party lacks. The sender picks a point in time, <code>delta_time</code>,
where it believes it and the receiver were probably in sync; it then describes the <a target="_blank"
href="https://github.com/hyperledger/indy-hipe/blob/d014879d/text/conn-mgmt-protocols/README.md#did-doc-deltas">deltas</a>
that it knows about, that have happened since.</p>
<p>If the recipient already has the same state, it replies with an <a target="_blank"
href="https://github.com/hyperledger/indy-hipe/blob/518b5a9a/text/acks/README.md">ACK</a>.</p>
<p>If the recipient knew about a subset of the delta, but not all of it, it applies what is left of the
delta, and sends an ACK.</p>
<p>If the recipient has a more evolved state, the recipient sends a reply
that is a new <code>sync_state</code> message informing the sender of hitherto unknown information. As with
the ACKs, this new message is known to be a reply to the original <code>sync_state</code> because its
<a target="_blank" href="https://github.com/hyperledger/indy-hipe/tree/master/text/0027-message-id-and-threading#threaded-messages">
<code>~thread</code> decorator identifies the previous message's <code>@id</code> as its <code>thid</code></a>.</p>
<p>If the recipient does not recognize the base_hash, it selects a hash from a point in time earlier than
<code>base_hash_time</code> and sends back a new <code>sync_state</code> message with that earlier base.</p>
<p>If the recipient detects a conflict, it attempts to merge states. If the merge is successful, it sends a
new <code>sync_state</code> that shows the merge. If the merge is not successful, then a merge
conflict exists, and the merge conflict policy for the sovereign domain of the associated DID is
invoked. See <a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/d014879d/text/conn-mgmt-protocols/README.md#merges-and-merge-conflicts">"Merges and Merge Conflicts"</a>.
</p>
</section>
<section>
<h4>Delete</h4>
<p>In a self-sovereign paradigm, abandoning a relationship can be done unilaterally, and does not
require formal announcement; one party can simply stop communicating with the other. Since there
is no public record of the relationship to delete, no further action is strictly required.
Indeed, sometimes a formal announcement is impossible, if one of the parties
is offline.</p>
<p>However, it is best practice to announce that the relationship is being abandoned. This
should cause the other party to clean up by removing the DID, DID Doc, and associated metadata from its
local cache. It should also prevent the other party from trying to communicate in the future.
Formally terminating a connection happens by sending a
<a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/d014879d/text/conn-mgmt-protocols/README.md#leave"><code>leave</code>
message</a> to a peer:</p>
<pre>
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connection/1.0/leave",
"@id": "c17147d2-ada6-4d3c-a489-dc1e1bf778ab",
"~please_ack": {}
}
</pre>
<p>If Bob receives a message like this, he should assume that Alice no longer considers
herself connected, and take appropriate action. This could include destroying
data about Alice that he has accumulated over the course of their relationship,
removing her peer DID and its public key(s) and endpoints from his wallet, and so
forth. The nature of the relationship, the need for a historical audit trail, regulatory
requirements, and many other factors may influence what's appropriate; the protocol
simply requires that the message be understood to have permanent termination semantics.</p>
<p>The <a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/518b5a9a/text/acks/README.md#requesting-an-ack-please_ack">
<code>~please_ack</code> decorator</a> is optional. It asks the receiver to
send an acknowledgement that it has processed the message. If used, the receiver
should send an ACK that looks like this:</p>
<pre>
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/ack",
"@thread": { "thid": "c17147d2-ada6-4d3c-a489-dc1e1bf778ab" }
}
</pre>
</section>
</section>
</section>
<section>
<h2>Security Considerations</h2>
<section>
<h3>Secure communication</h3>
<p>All the messages in this protocol (except for a connection invitation that requires no security, by design)
must be sent encrypted, using the encryption format
specified in <a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/master/text/0028-wire-message-format/README.md">DIDComm's wire format</a>.
This gives strong guarantees about the confidentiality and integrity of exchanged
data, regardless of the transport mechanism used to transmit the messages.</p>
</section>
<section>
<h3>Cryptonyms</h3>
<p>Because peer DIDs are generated from their initial public key, they cannot be created without the creator
controlling them. As mentioned earlier, this prevents man-in-the-middle attacks at the time of creation.
Since keys must be created from keys generated by a secure random number generator, they are guaranteed
to be unpredictable and globally unique at creation time.</p>
</section>
<section>
<h3>Key Authorizations</h3>
<p>The keys authorized to participate in a peer relationship may not all have the same
privileges. All keys have the privilege of rotating themselves. Keys that have the privilege
of adding keys can only add keys with equal or lesser privileges than themselves. All other
authorizations on keys must be specified in the <code>authorization</code> section of a peer DID doc.
Its structure is:</p>
<p>
“authorization”: [ list of <b>grant</b>s ]<br/>
<b>grant</b> = { "let": <b>recipient</b> , “do”: <b>privs</b> }<br/>
<b>recipient block</b> = one of the following:<br/>
“key”: keyref, e.g., “#1”<br/>
"group":<br/>
“and”: [ list of recipient block ]<br/>
“or”: [ list of recipient block ]<br/>
“m_of_n”: {“m”: number, “n”: [ list of recipient block ]}<br/>
<b>privs</b> = a string that enumerates the privileges being granted.
This string is list-like but is not modeled using a JSON list or dict
because of some specialized syntax that conflicts with canonicalization
requirements. Its format is a space-delimited list of privileges in string form, where each
privilege is an op code name. The list must be sorted in ascending
alphabetical order to aid normalization.
</p>
<p>Basically, authorizations are a series of grants. Grants identify the recipient, which is either a key or a combination of keys, and the privileges that the recipient is receiving.</p>
<p>An example might be:</p>
<img src="authorization.png"/>
<p>What this says is:</p>
<ul>
<li>Key #1 ("let":"#1") can add keys, add key references to the authentication section, remove keys, remove keys from the authentication section, and remove any authorization from any key or group of keys.</li>
<li>Adding authorizations to a key can be done in either ("let":{"or"...) of the following ways:<br/>
<ul><li>Key #1 and one other key can approve the change.</li>
<li>Any three ("m_of_n":{"m":3...) of keys #2-#5 can approve the change.</li>
</ul>
</li>
</ul>
</section>
<section>
<h3>Key Management</h3>
<p>Keys used to control peer DIDs, or keys authorized to communicate and update the DID Docs
for peer DIDs, should be managed according to best practices for DKMS, as described in
<a target="_blank" href="https://github.com/hyperledger/indy-hipe/blob/9223b7fe/text/dkms/dkms-v4.md">the DKMS spec</a>.</p>
</section>
</section>
<section>
<h2>Privacy Considerations</h2>
<p>Peer DIDs should remain pairwise or n-wise, not being reused across relationships. This
allows proper isolation to defeat correlation. It also enables granular exercise of sovereignty in a
robust, <a target="_blank" href="https://medium.com/evernym/three-dimensions-of-identity-bc06ae4aec1c">
multidimensional identity</a>.</p>
<img src="pairwise.png"/>
</section>
<section>
<h2>Grafting Peer DIDs Into Another DID Method Namespace</h2>
<p>Because peer DIDs are guaranteed to be globally unique at the moment of creation,
their 128-bit NSI should not exist on any blockchain. Blockchain-based DID methods
can register a peer DID Doc using their own method. As the DID value, they can either
combine their own method prefix with peer DID's NSI ("did:peer:abc123" --> "did:xyz:abc123"),
or they can create a child namespace for peer DIDs beneath their own ("did:peer:abc123" -->
did:xyz:peer:abc123").</p>
<p>If a peer DID is registered and grafted into another DID namespace, using either method,
the result is two DIDs with different namespaces, one peer and one anchored, each with
its own DID Doc. A decision must be made about which DID is normative for the relationship,
or whether both should continue to be used. If both will be used, it should be understood that
the two DID Docs hold keys and other data for two different DIDs, regardless of the shared
history of those DIDs. Ideally, there would be no difference between the DID Docs stored in each place,
but even with the best intentions of the DID controller, differences may arise.</p>
<p>One reason why this grafting and cross-registering feature is interesting is that peer DIDs
could be supported by existing DID tools (e.g., the universal resolver) that require a
blockchain, without any retooling.</p>
</section>
<section>
<h2>Reference Implementations</h2>
<p>The wire format for DID Communication encryption has three independent implementations--one in
<a target="_blank" href="https://github.com/hyperledger/indy-sdk/blob/fbad7422/libindy/src/api/crypto.rs#L634">
libindy</a>, one in
<a target="_blank" href="https://github.com/bcgov/indy-catalyst/blob/bba2ef5c/agent/indy_catalyst_agent/wallet/crypto.py#L402">
python with no Indy dependencies</a>, and one in
<a target="_blank" href="https://github.com/dbluhm/indy-pack-unpack-js/blob/db9d83e4/index.js">
javascript with no Indy dependencies</a>.</p>
<p>The connection protocol that creates and registers peer DIDs, including support for DID resolution
after forming a connection, has been fully implemented by
half a dozen different organizations, as of March 2019. One of these organizations did not use
libindy. The connection management protocols that allow update of DIDs are in various states of
implementation. An up-to-date summary of implementation status, including links to the implementations,
can be found in the <a target="_blank" href="https://github.com/hyperledger/indy-agent">indy-agent repo on github</a>.</p>
<p>There is a formal test suite for the protocols as well, in the same github repo.</p>
</section>
<section>
<h2>Resources</h2>
<p>Developers maintaining this spec and its reference implementations are often found on RocketChat at
chat.hyperledger.org, #indy, #indy-sdk, and #aries. You might also connect with them via the Hyperledger Indy
mailing list at indy@lists.hyperledger.org, the Hyperledger Aries mailing list at aries@lists.hyperledger.org,
in Hyperledger and W3C working groups, or at the semi-annual Internet Identity Workshop conferences.</p>
</section>
</body>
</html>