-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.html
1600 lines (1463 loc) · 59.8 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
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<title>Cryptographic Event Log v0.1</title>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>
<!--
=== NOTA BENE ===
For the three scripts below, if your spec resides on dev.w3 you can check them
out in the same tree and use relative links so that they'll work offline,
-->
<script src='https://www.w3.org/Tools/respec/respec-w3c' class='remove'></script>
<script class="remove"
src="https://cdn.jsdelivr.net/gh/digitalbazaar/respec-vc@3.3.5/dist/main.js"></script>
<script class="remove">
var respecConfig = {
group: "credentials",
// specification status (for example, WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "CG-DRAFT",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "cel-1.0",
// subtitle for the spec
subtitle: "A cryptographic protocol for verifying a log of changes to data",
// if you wish the publication date to be other than today, set this
//publishDate: "2024-11-05",
//crEnd: "2024-12-05",
//prEnd: "2019-10-01",
//implementationReportURI: "https://w3c.github.io/vc-data-model-2.0-test-suite/",
//errata: "https://w3c.github.io/vc-data-model/errata.html",
//previousMaturity: "REC",
//previousPublishDate: "2022-03-03",
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
// previousPublishDate: "1977-03-15",
// previousMaturity: "WD",
// extend the bibliography entries
localBiblio: {},
doJsonLd: true,
// Uncomment these to use the respec extension that generates a list of
// normative statements:
preProcess: [/*prepare_reqlist*/],
postProcess: [
window.respecVc.createVcExamples
/*add_reqlist_button*/
],
github: "https://github.com/digitalbazaar/cel-spec/",
includePermalinks: false,
// if there a publicly available Editor's Draft, this is the link
edDraftURI: "https://digitalbazaar.github.io/cel-spec/",
// if this is a LCWD, uncomment and set the end of its review period
// lcEnd: "2009-08-05",
// editors, add as many as you like
// only "name" is required
editors: [
{ name: "Manu Sporny", url: "https://www.linkedin.com/in/manusporny/",
company: "Digital Bazaar", companyURL: "https://digitalbazaar.com/",
w3cid: 41758}
],
formerEditors: [
],
// authors, add as many as you like.
// This is optional, uncomment if you have authors as well as editors.
// only "name" is required. Same format as editors.
authors:
[
{ name: "Dave Longley", url: "https://digitalbazaar.com/",
company: "Digital Bazaar", companyURL: "https://digitalbazaar.com/",
w3cid: 48025
},
{ name: "Manu Sporny", url: "https://digitalbazaar.com/",
company: "Digital Bazaar", companyURL: "https://digitalbazaar.com/",
w3cid: 41758
},
{ name: "Christine Lemmer-Webber",
url: "https://dustycloud.org/",
company: "Spritely Institute",
companyURL: "https://spritely.institute/",
w3cid: 0
}
],
xref: ["URL", "I18N-GLOSSARY", "INFRA", "VC-DATA-INTEGRITY"],
lint: { "informative-dfn": false },
maxTocLevel: 3,
inlineCSS: true
};
</script>
<style>
code {
color: rgb(199, 73, 0);
font-weight: bold;
}
pre {
overflow-x: auto;
white-space: pre-wrap;
}
pre .highlight {
font-weight: bold;
color: Green;
}
pre .subject {
font-weight: bold;
color: RoyalBlue;
}
pre .property {
font-weight: bold;
color: DarkGoldenrod;
}
pre .comment {
font-weight: bold;
color: SteelBlue;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ol.algorithm {
counter-reset: numsection;
list-style-type: none;
}
ol.algorithm li {
margin: 0.5em 0;
}
ol.algorithm li:before {
font-weight: bold;
counter-increment: numsection;
content: counters(numsection, ".") ") ";
}
table.simple {
border-collapse: collapse;
margin: 25px 0;
min-width: 400px;
border: 1px solid #dddddd;
}
table.simple thead tr {
background-color: #005a9c;
color: #ffffff;
text-align: left;
}
table.simple th,
table.simple td {
padding: 12px 15px;
vertical-align: top;
text-align: left;
}
table.simple tbody tr {
border-bottom: 1px solid #dddddd;
}
table.simple tbody tr:nth-of-type(even) {
background-color: #00000008;
}
table.simple tbody tr:last-of-type {
border-bottom: 2px solid #005a9c;
}
</style>
</head>
<body>
<section id='abstract'>
<p>
This specification defines a data model for an author to express changes to data
over time and the means for a verifier to cryptographically verify those
changes.
</p>
</section>
<section id='sotd'>
<p>
An experimental thought exercise, for now. Potentially, a data structure for
cryptographic event logging of data objects such as DID Documents, ActivityPub
objects, and other data formats.
</p>
</section>
<section class="informative">
<h2>Introduction</h2>
<p>
In decentralized systems, coordination relies on a shared view of reality to
make decisions. This shared reality can include various types of information,
such as the balance of a financial account, the current holder of cryptographic
material (like a public key), the location of a physical asset, or the sequence
of comments in an online forum. When this information is expressed digitally, it
is important to understand the order of events that led to the current state.
Additionally, it is crucial for systems to be able to share this information in
a decentralized way, with guarantees that the event log has not been tampered
with over time.
</p>
<p>
One approach to securing a cryptographic log of information is to establish a
cryptographic key to be associated with a particular piece of data and then only
trust changes to that information where each change is digitally signed by the
controller of the cryptographic key. One challenge with this approach is that
the controller might modify the sequence of events at any point, effectively
rewriting history, if it provides an advantage for them in a decentralized
system.
</p>
<p>
To prevent rewriting history, some decentralized systems have turned to
centralized solutions to "witness" the log of events that change the underlying
data. Centralized solutions tend to create problems with the power dynamics in
an ecosystem and, unsurprisingly, centralize previously decentralized solutions.
</p>
<p>
Other decentralized systems have turned to solutions such as decentralized
ledger technologies (also known as blockchains) to share the state of a system.
Some of these decentralized solutions tend to create their own problems such as
energy use that some view as excessive (proof of work) or an excessive
centralization of capital (proof of stake). Decentralized solutions also tend to
make some governments nervous and slow adoption due to the uncertainty
associated with the political dynamic of the underlying cryptocurrency.
</p>
<p>
This specification defines a decentralized cryptographic event log format where
a verifier depends on the controller of a particular piece of data, as well as
external witnesses that they trust, to establish trust in the current state of a
particular object in a decentralized system.
</p>
<p class="issue" data-number="1" title="Cite prior art">
A reader of this specification might presume that the authors are not aware of
the 30+ years of prior art around time stamping and cryptographic log services
such as <a href="https://w3c.github.io/web-ledger/">Web Ledger</a>,
<a href="https://opentimestamps.org/">opentimestamps.org</a>, cryptographically
signing a transaction log, blockchains and decentralized ledgers, Tahoe LAFS,
did:peer, Trusted DID Web's log, did:dht, IPFS, and other technologies that
provide technologies similar to what this specification provides. We probably
need to have a section highlighting all the prior art in the space and what sets
this specification apart. Readers of this specification are urged to provide
citations to prior art that they feel apply.
</p>
<section class="nonnormative">
<h2>Goals</h2>
<p>
This specification satisfies the following design goals:
</p>
<dl>
<dt>Generalized</dt>
<dd>
The log format provided in this specification can contain events that record
arbitrary operations on data objects, making it broadly useful in different
market verticals.
</dd>
<dt>Cryptographically Verifiable</dt>
<dd>
The log format is cryptographically verifiable, which can be used to detect log
tampering, and reduces the reliance on centralized systems and services.
</dd>
<dt>Post-Quantum Ready</dt>
<dd>
The log format uses cryptographic digests, which are secure against quantum
computers, as the primary mechanism to link events together. The elliptic-curve
cryptographic signatures, which are not secure against quantum computers, are a
secondary mechanism used to witness events. This separation of concerns enables
the cryptographic signature mechanism to be smoothly upgraded to a post-quantum
secure cryptographic signature scheme on a per-log basis as post-quantum
resistant digital proofs become more widely adopted.
</dd>
<dt>Decentralized Witnesses</dt>
<dd>
The event witnessing mechanism does not rely on a central authority and
does not rely on coordination among witnesses.
</dd>
<dt>Oblivous Signatures</dt>
<dd>
The witnessing mechanism relies on oblivious signatures which greatly reduces
liability related to cryptographic signatures produced by a witness.
</dd>
<dt>Separation of Concerns</dt>
<dd>
The log layer is a separate architectural layer from the event layer, which
is a separate layer from the operation layer, which defines the algorithms
that the state machine uses to validate the lifecycle of the data object.
</dd>
</dl>
</section>
<section class="nonnormative">
<h2>Use Cases and Requirements</h2>
<p>
The following use cases have been identified as ones that this specification
is capable of addressing.
</p>
<dl>
<dt>DID Document Change Log</dt>
<dd>
Stephen is creating a new DID Method and would like to provide an independently
verifiable cryptographic log file for DID Document changes.
</dd>
<dt>Social Web Posting Change Log</dt>
<dd>
Christine is launching a new social network and would like to provide a way of
publishing content that is portable across providers.
</dd>
<dt>Portable Account Data</dt>
<dd>
Paul would like to enable the people that use his service to easily move their
content history to other services.
</dd>
<dt>Journalism Witnessing</dt>
<dd>
Georg is a journalist that archives media from a variety of news outlets and
would like to provide a witnessing service to prove precisely when certain
publication and redaction events happened across various forms of digital
publishing.
</dd>
</dl>
</section>
<section id="conformance">
<p>
A <dfn>conforming log</dfn> is any [=byte sequence=] that can be
converted to a
<a data-cite="INFRA#parse-json-bytes-to-a-javascript-value">
JSON document</a> that follows the relevant normative requirements in
Sections [[[#data-model]]].
</p>
<p>
A <dfn class="lint-ignore">conforming [=application specification=]</dfn> is
any specification that follows the relevant normative requirements in Section
[[[#application-specifications]]].
</p>
<p>
A <dfn class="lint-ignore">conforming processor</dfn> is any algorithm realized
as software and/or hardware that generates and/or consumes a
[=conforming log=] according to the relevant normative statements
in Section [[[#algorithms]]]. Conforming processors MUST produce errors when
non-conforming documents are consumed.
</p>
</section>
</section>
<section class="normative">
<h2>Data Model</h2>
<p>
This section defines the data model for expressing protected events that enable
an author to express changes to a specific instance of data over time in a way
that is tamper-evident and that can be cryptographically authenticated by
verifiers in a decentralized manner.
</p>
<p class="issue" data-number="3"></p>
<section class="normative">
<h2>Event Log</h2>
<p>
A <dfn data-lt="event log">cryptographic event log</dfn> contains a [=list=] of
witnessed events. The log's basic structure is shown below:
</p>
<pre class="example nohighlight" title="An event log containing multiple events">
{
"log": [{
"event": {<span class="comment">...</span>}, <span class="comment">// the first event in the event log</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the event</span>
}, {
"event": {<span class="comment">...</span>}, <span class="comment">// the second event</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the second event</span>
}, {
"event": {<span class="comment">...</span>}, <span class="comment">// the third event</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the third event</span>
}]
}
</pre>
<p>
An [=event log=] MUST conform to the following format:
</p>
<table class="simple">
<thead>
<tr>
<th style="white-space: nowrap">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>log</td>
<td>
A REQUIRED property whose value is a [=list=] of one or more entries that
conform to the following format:
<table class="simple">
<thead>
<tr>
<th style="white-space: nowrap">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>event</td>
<td>
A REQUIRED property whose value conforms to the data structure defined in
Section [[[#event-entry]]].
</td>
</tr>
<tr>
<td>proof</td>
<td>
A REQUIRED property whose value conforms to a [=data integrity proof=]
as defined by the [[VC-DATA-INTEGRITY]] specification. [=Conforming processors=]
MUST support at least the `ecdsa-jcs-2019` cryptosuite as defined by the
[[[VC-DI-ECDSA]]] specification.
<p class="issue" data-number="2"></p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>previousLog</td>
<td>
An OPTIONAL property whose value MUST conform to an external reference as
defined in Section [[[#external-reference]]]. The value MUST also contain a
`proof` property whose value conforms to a [=data integrity proof=] as defined
by the [[VC-DATA-INTEGRITY]] specification. [=Conforming processors=] MUST
support at least the `ecdsa-jcs-2019` cryptosuite as defined by the
[[[VC-DI-ECDSA]]] specification. Event logs MUST have a default maximum size of
10MB which can be overridden by [=application specification=]s and SHOULD be at
least 1MB in size before creating a new chunk.
</td>
</tr>
</tbody>
</table>
<p>
To support chunking, the `previousLog` property is provided to ensure that
arbitrarily long change histories are supported.
</p>
<pre class="example nohighlight" title="An event log containing multiple events">
{
"previousLog" : {
<span class="comment">// URLs that can be used to retrieve the previous event log</span>
"url": [
"https://website.example/log123.cel",
"3jxop4cs2lu5ur2<span class="comment">...</span>sseqdsp3k262uwy4.onion/log123.cel",
"ipfs://QmCQFJGkARStJbTy8w65yBXgyfG2ZBg5TrfB2hPjrDQH3R"
],
<span class="comment">// The media type associated with the previous log</span>
"mediaType": "application/cel",
<span class="comment">// a cryptographic digest of the previous log (sha2-256 base64-url-nopad)</span>
"digestMultibase": "uEiwLZcLK9EBguM5WZlbAgfXBDuQAkoYyQ6YVtUmER8pN24"
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the previous event log</span>
},
"log": [{
"event": {<span class="comment">...</span>}, <span class="comment">// the first event in the event log</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the event</span>
}, {
"event": {<span class="comment">...</span>}, <span class="comment">// the second event</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the second event</span>
}, {
"event": {<span class="comment">...</span>}, <span class="comment">// the third event</span>
"proof": [<span class="comment">...</span>] <span class="comment">// a list of witness proofs securing the third event</span>
}]
}
</pre>
</section>
<section class="normative">
<h2>External Reference</h2>
<p>
An external reference points to data outside of the event log in a way
that is cryptographically verifiable. The reference can provide a list of
URLs where the data can be retrieved, a media type to use when performing
the data retrieval, and a cryptographic hash of the data.
</p>
<table class="simple">
<thead>
<tr>
<th style="white-space: nowrap">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>url</td>
<td>
An OPTIONAL property whose value MUST be a [=list=] of one or more URLs that
can be used to retrieve the data being secured. If no `url` value is specified,
the mechanism used to retrieve the data is application-specific.
</td>
</tr>
<tr>
<td>mediaType</td>
<td>
An OPTIONAL property whose value MUST be a media type as defined by the
[[[RFC6838]]].
</td>
</tr>
<tr>
<td>digestMultibase</td>
<td>
A REQUIRED property whose value MUST be a <a
data-cite="CONTROLLER-DOCUMENT#multibase-0">Multibase-encoded</a> (base64-url-nopad) <a
data-cite="CONTROLLER-DOCUMENT#multihash">Multihash</a> (sha2-256) value.
</td>
</tr>
</tbody>
</table>
<pre class="example nohighlight" title="An external reference to a file containing multiple download locations">
{
<span class="comment">// URLs that can be used to retrieve the data</span>
"url": [
"https://website.example/file.dat",
"cs2lu5ur23jxop4<span class="comment">...</span>p3k262uwy4sseqds.onion/file.dat",
"ipfs://QmJbTy8w65yBXgyCQFJGkARStfB2hPjrDQH3RG2ZBg5Trf"
],
<span class="comment">// The media type of the file</span>
"mediaType": "application/octet-stream",
<span class="comment">// a cryptographic digest of the file (sha2-256 base64-url-nopad)</span>
"digestMultibase": "uEQ6YVtUmER8pN24iwLZcLK9EBguM5WZlbAgfXBDuQAkoYy"
}
</pre>
</section>
<section class="normative">
<h2>Event Entry</h2>
<p>
A <dfn data-lt="log entry">cryptographic event log entry</dfn> is used to
establish an event that can be independently authenticated by a verifier. The
[=log entry=] MUST be composed of at least a single `event` and one or more
associated `proof` values that can be used to verify the validity of the event.
</p>
<p class="issue" data-number="6"></p>
<table class="simple">
<thead>
<tr>
<th style="white-space: nowrap">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>operation</td>
<td>
A REQUIRED property that captures an operation that was observed during the
event. The `operation` value MUST include either a `data` property or
a `dataReference` property and MUST conform to the following data format:
<table class="simple">
<thead>
<tr>
<th style="white-space: nowrap">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>type</td>
<td>
A REQUIRED property whose value is the type of event being expressed. A
[=conforming processor=] MUST support the following [=string=] values: `create`,
`update`, and `deactivate` and MAY support other values defined by a
[=conforming application specification=].
<div class="issue" data-number="7"></div>
</td>
</tr>
<tr>
<td>data</td>
<td>
An OPTIONAL property whose value contains the JSON expression of the data
being secured. If this property is specified, the `dataReference` property
MUST NOT be specified.
</td>
</tr>
<tr>
<td>dataReference</td>
<td>
An OPTIONAL property whose value contains a reference and cryptographic hash
to the data being secured. If this property is specified, the `data` property
MUST NOT be specified. The format for the value is defined in
Section [[[#external-reference]]].
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>previousEvent</td>
<td>
If `type` is not set to `create`, this property is REQUIRED and its [=string=]
value MUST be a Multibase-encoded (base64-url-nopad) Multihash (sha2-256) of the
event immediately preceding this event.
</td>
</tr>
</tbody>
</table>
<p>
The example below shows the first [=log entry=] containing a `create`
operation:
</p>
<pre class="example nohighlight" title="An initial event log entry containing data embedded directly in the event.">
{
"log": [{
"event": {
<span class="comment">// the cryptographic hash of the previous event</span>
"previousEvent": "uEBguM5WZlbAgfXBDuQiAkoYyQ6YVtUmER8pN24wLZcLK9E",
"operation": {
<span class="comment">// the type of operation observed by the event</span>
"type": "create",
<span class="comment">// the data associated with the event (in JSON format)</span>
"data": {
"name": "Hello World!",
<span class="comment">// one or more proofs that secure the integrity of the event above</span>
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "ecdsa-jcs-2019",
"created": "2024-11-29T13:56:28Z",
<span class="comment">// the cryptographic authority for the data is application specific</span>
<span class="comment">// in this example, it is established by the proof in the create operation</span>
"verificationMethod": "https://website.example/crypto#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "zq6PrUMCtqY5obCSsrQxuFJd<span class="comment">...</span>wVWgHYrXxoV93gBHqGDBtQLPFxpZxz"
}
}
}
}
}]
}
</pre>
<p>
The example below shows the second [=log entry=] containing an `update`
operation that refers to the previous example via the `previousEvent` property:
</p>
<pre class="example nohighlight" title="An event log entry containing data embedded directly in the event.">
{
"log": [{
<span class="comment">... // first event log entry</span>
}, {
"event": {
<span class="comment">// the cryptographic hash of the previous event</span>
"previousEvent": "uEBguM5WZlbAgfXBDuQiAkoYyQ6YVtUmER8pN24wLZcLK9E",
"operation": {
<span class="comment">// the type of operation is an "update"</span>
"type": "update",
"data": {
<span class="comment">// the "name" value is changed in the update</span>
"name": "Updated Hello World!",
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "ecdsa-jcs-2019",
"created": "2024-11-30T11:29:11Z",
"verificationMethod": "https://website.example/crypto#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "zqY5obCSsrQxuFJdq6PrUMCt<span class="comment">...</span>93gBHqGDBtQLPFxpZxzwVWgHYrXxoV"
}
}
}
}
}]
}
</pre>
<p>
Some data are too large to include in the event log itself. For these cases,
it is possible to refer to data outside of the event log and digitally sign
a cryptographic hash of the external data. It is also possible to provide
multiple URLs for a verifier to use when retrieving the external data.
</p>
<pre class="example nohighlight" title="An event log entry containing a reference to data.">
{
"log": [{
"event": {
"operation": {
"type": "create",
<span class="comment">// a reference to the data associated with the event</span>
"dataReference": {
<span class="comment">// URLs that can be used to retrieve the data</span>
"url": [
"https://website.example/file.dat",
"3jxop4cs2lu5ur2<span class="comment">...</span>sseqdsp3k262uwy4.onion/file.dat",
"ipfs://QmTy8w65yBXgyfG2ZBg5TrfB2hPjrDQH3RCQFJGkARStJb"
],
<span class="comment">// The media type of the associated data</span>
"mediaType": "application/octet-stream",
<span class="comment">// a cryptographic digest of the data (sha2-256 base64-url-nopad)</span>
"digestMultibase": "uEiAkoYyQ6YVtUmER8pN24wLZcLK9EBguM5WZlbAgfXBDuQ"
}
}
}
}]
}
</pre>
</section>
<section class="normative">
<h2>Event Witness</h2>
<p>
An <dfn>event witness</dfn> is a service that can attest to the existence of
data at a particular point in time. These services are trusted by the verifier
to attest to the existence of data at a particular point in time by digitally
signing a cryptographic hash that is provided to them such that they do not
see the data, but confirm the existence of the data.
</p>
<p>
The [=event witness=] performs their function by providing a [=data integrity
proof=] for a particular event digest. The log controller then appends the
proof onto the array of `proof` values.
</p>
<pre class="example nohighlight" title="An event log entry containing a reference to data.">
{
"log": [{
"event": {
"operation": {
"type": "create",
<span class="comment">// a reference to the data associated with the event</span>
"dataReference": {
<span class="comment">// URLs that can be used to retrieve the data</span>
"url": [
"https://website.example/file.dat",
"3jxop4cs2lu5ur2<span class="comment">...</span>sseqdsp3k262uwy4.onion/file.dat",
"ipfs://QmTy8w65yBXgyfG2ZBg5TrfB2hPjrDQH3RCQFJGkARStJb"
],
<span class="comment">// The media type of the associated data</span>
"mediaType": "application/octet-stream",
<span class="comment">// a cryptographic digest of the data (sha2-256 base64-url-nopad)</span>
"digestMultibase": "uEiAkoYyQ6YVtUmER8pN24wLZcLK9EBguM5WZlbAgfXBDuQ"
}
}
},
<span class="comment">// one or more proofs that witness the event above</span>
"proof": [{
"type": "DataIntegrityProof",
"cryptosuite": "ecdsa-jcs-2019",
"created": "2024-11-29T13:56:45Z",
"verificationMethod": "https://witness.example/attestation#key-P8",
"proofPurpose": "assertionMethod",
"proofValue": "zJdq6PrUMCtqY5obCSsrQxuF<span class="comment">...</span>tQLPFxpZxzwVWgHYrXxoV93gBHqGDB"
}]
}]
}
</pre>
</section>
<section class="normative">
<h2>Minimizing Event Logs</h2>
<p>
Event logs that contain all data necessary to reconstruct the current state of
data from an event log can be verbose, especially when many event witnesses are
used. For these use cases, a compact format is provided that can be further
compressed into a minimal binary CBOR stream. A minimum viable
[=cryptographic event log=] is shown below:
</p>
<p class="issue" data-number="5"></p>
<!--code><span class="vc-hash" data-hash-url="index.html"
data-hash-format="multihash sha2-256" /></code-->
<pre class="example nohighlight" title="A minimum viable cryptographic event log">
{
"log": [{
"event": {
"operation": {
"type": "create",
"dataReference": "uEiBfhmMyElIQPrulFu-5ETYVLgzyvoPsmxTMpEds7iQPBw"
}
},
"proof": [
"uEiAJEdA64FgSCB6yPqXIRU_x8hg5wcEwwvT-EfHxm44lCA",
"uEiD4MvIoKbDn7yHUl_G4ivWNtQZ6v8p2tfDvcRBJ2NQTVw",
"uEiDlAVvCcKUxn9XeLMOzDoJyLevPfX91pyi1Ry5l92pHsw"
]
}, {
"event": {
"previousEvent": "uEcusg0U2pL9sdsusEuMCdQiCLcgmToC-2b9qCWNHZt3ouO",
"operation": {
"type": "update",
"dataReference": "uEiCLcgmToC-2b9qCWNHZt3ouOcusg0U2pL9sdsusEuMCdQ"
}
},
"proof": [
"uEiCsH8n2phXA-tYy_bcTpuAMkWEDyiZLZyqv1PwehHCqsA",
"uEiDXyzlypk757_ZTKxRZINMUDZQPOInYcj6k_vj3ro--bw",
"uEiCqA7hqFj5THapravk_wh_ViKu6h8BC0uqhKoWTERLBZA"
]
}]
}
</pre>
<p>
The event log above (651 bytes) can be compressed to CBOR (350 bytes; 53%
compression), where each [=log entry=] has an overhead of roughly 19
bytes (12% overhead). The event log above is shown below in CBOR Diagnostic
notation format:
</p>
<pre class="example nohighlight" title="A minimum viable cryptographic event log">
A1 # map(1)
20 # log
82 # array(2)
A2 # map(2)
21 # event
A1 # map(1)
22 # negative(2)
A2 # map(2)
23 # type
38 63 # create
24 # dataReference
58 22 # bytes(34)
12205F8663321252103EBBA516EFB91136152E0CF2BE83EC9B14CCA4476CEE240F07
26 # proof
83 # array(3)
58 22 # bytes(34)
12200911D03AE05812081EB23EA5C8454FF1F21839C1C130C2F4FE11F1F19B8E2508
58 22 # bytes(34)
1220F832F22829B0E7EF21D497F1B88AF58DB5067ABFCA76B5F0EF711049D8D41357
58 22 # bytes(34)
1220E5015BC270A5319FD5DE2CC3B30E82722DEBCF7D7F75A728B5472E65F76A47B3
A2 # map(2)
21 # negative(1)
A2 # map(2)
25 # previousEvent
58 22 # bytes(34)
11CBAC834536A4BF6C76CBAC12E3027508822DC8264E80BED9BF6A09634766DDE8B8
22 # negative(2)
A2 # map(2)
23 # type
38 64 # update
24 # dataReference
58 22 # bytes(34)
12208B720993A02FB66FDA8258D1D9B77A2E39CBAC834536A4BF6C76CBAC12E30275
26 # proof
83 # array(3)
58 22 # bytes(34)
1220AC1FC9F6A615C0FAD632FDB713A6E00C916103CA264B672AAFD4FC1E8470AAB0
58 22 # bytes(34)
1220D7CB3972A64EF9EFF6532B145920D3140D940F3889D8723EA4FEF8F7AE8FBE6F
58 22 # bytes(34)
1220AA03B86A163E531DAA6B6AF93FC21FD588ABBA87C042D2EAA12A85931112C164
</pre>
</section>
</section>
<section class="normative">
<h2>Serializations</h2>
<p>
The data model described in this specification can be serialized as JSON or
CBOR.
</p>
<p class="issue" title="Multiple serializations increase complexity">
If we do not provide a CBOR serialization, some subset of the developer
community will complain. The only argument for a CBOR serialization is
ensuring a byte-optimized storage format. We could make CBOR the default
serialization, but at the cost of alienating developers that don't work in
CBOR (which is most of them). The only time size restrictions come into
play is with large event logs (or large binaries in event logs), which are a
possibility. We're going to start out with JSON, see how far it gets us, and
see if the pro-CBOR community would be willing to trade CPU cycles to
convert to/from CBOR from JSON (ensuring a stable round-tripping). The number
of fields we'd have to pick CBOR values for is minimal.
<br><br>
An approach for a bi-directional mapping is provided in Section
[[[#minimizing-event-logs]]].
</p>
<section class="normative">
<h3>JSON</h3>
<p class="issue" title="Default representation is JSON">
The default representation for a [=cryptographic event log=] is JSON. That
might change if we get enough developer feedback to use CBOR.
<br><br>
An approach for a bi-directional mapping is provided in Section
[[[#minimizing-event-logs]]].
</p>
</section>
<section class="normative">
<h3>CBOR</h3>
<p class="issue" title="Default representation is JSON">
The default representation for a [=cryptographic event log=] is JSON. That
might change if we get enough developer feedback to use CBOR. The alternative
is to provide a bi-directional mapping to CBOR which reduces storage
requirements.
<br><br>
An approach for a bi-directional mapping is provided in Section
[[[#minimizing-event-logs]]].
</p>
</section>
</section>
<section class="normative">
<h2>Algorithms</h2>
<p>
The algorithms described in this section outline the procedures used to ensure
the integrity and security of the event log. These algorithms provide the means
for securely recording, verifying, and sharing changes to data in a
decentralized system. By leveraging cryptographic techniques, the algorithms
ensure that the event log is tamper-proof and verifiable, allowing parties to
independently confirm the authenticity of the data. The following subsections
detail the specific algorithms used for creating event entries, verifying their
integrity, and ensuring consistency across systems.
</p>
<section class="normative">
<h2>Create Event Log</h2>
<p>
The following algorithm defines the process for creating an event log.
</p>
<ol class="algorithm">
<li>
Let |eventLog| be an empty [=list=].
</li>
<li>
Let |event| be the output of Section [[[#create-event]]].
</li>
<li>
Append |event| to |eventLog|.
</li>
<li>
Return |eventLog|.
</li>
</ol>
</section>
<section class="normative">
<h2>Create Event</h2>
<p>
The following algorithm defines the process for creating an event log entry.
The event log serves as a record of changes to data within a system, capturing
key information such as the type of event, the associated cryptographic hash of
the protected data, and a proof that secures both. The algorithm ensures that
each event is securely logged and that the integrity of the data is maintained
over time. By following this process, systems can reliably document and share
events, providing verifiable evidence of changes while maintaining
decentralization and security.
</p>
<p>
Required inputs are an [=event log=] ([=map=] inputEventLog), and
[=log entry=] ([=map=] |inputEvent|) and a set of
options ([=map=] |options|). An [=event log=] ([=map=]), or an error,
is produced as output.
</p>
<ol class="algorithm">
<li>
Let |event| be a deep copy of |inputEvent| and let |eventLog| be a deep copy of