@twin.org/immutable-proof-service 0.0.1-next.3 → 0.0.1-next.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,81 @@
1
- import { Guards, ComponentFactory, StringHelper, Validation, Converter, RandomHelper, ObjectHelper, Urn, GeneralError, Is, NotFoundError, JsonHelper } from '@twin.org/core';
2
- import { ImmutableProofTypes, ImmutableProofFailure } from '@twin.org/immutable-proof-models';
3
- import { DidContexts, DidTypes, DidCryptoSuites } from '@twin.org/standards-w3c-did';
1
+ import { property, SortDirection, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
2
+ import { Guards, ComponentFactory, StringHelper, Is, Validation, Converter, RandomHelper, ObjectHelper, Urn, GeneralError, NotFoundError, JsonHelper } from '@twin.org/core';
3
+ import { ImmutableProofTypes, ImmutableProofContexts, ImmutableProofFailure, ImmutableProofTopics } from '@twin.org/immutable-proof-models';
4
+ import { DidCryptoSuites, ProofTypes, DidContexts } from '@twin.org/standards-w3c-did';
4
5
  import { HttpStatusCode, HeaderTypes, MimeTypes } from '@twin.org/web';
5
- import { Blake2b, Sha256 } from '@twin.org/crypto';
6
+ import { BackgroundTaskConnectorFactory, TaskStatus } from '@twin.org/background-task-models';
7
+ import { Sha256 } from '@twin.org/crypto';
6
8
  import { JsonLdHelper, JsonLdProcessor } from '@twin.org/data-json-ld';
7
- import { SchemaOrgDataTypes, SchemaOrgTypes } from '@twin.org/data-schema-org';
8
- import { ComparisonOperator, SortDirection, property, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
9
9
  import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
10
10
  import { IdentityConnectorFactory } from '@twin.org/identity-models';
11
- import { ImmutableStorageConnectorFactory } from '@twin.org/immutable-storage-models';
12
- import { VaultConnectorFactory } from '@twin.org/vault-models';
11
+ import { VerifiableStorageConnectorFactory } from '@twin.org/verifiable-storage-models';
12
+
13
+ // Copyright 2024 IOTA Stiftung.
14
+ // SPDX-License-Identifier: Apache-2.0.
15
+ /**
16
+ * Class describing the immutable proof.
17
+ */
18
+ let ImmutableProof = class ImmutableProof {
19
+ /**
20
+ * The id of the proof.
21
+ */
22
+ id;
23
+ /**
24
+ * The identity of the node which controls the proof.
25
+ */
26
+ nodeIdentity;
27
+ /**
28
+ * The identity of the user which created the proof.
29
+ */
30
+ userIdentity;
31
+ /**
32
+ * The date/time of when the proof was created.
33
+ */
34
+ dateCreated;
35
+ /**
36
+ * The associated id for the item.
37
+ */
38
+ proofObjectId;
39
+ /**
40
+ * The associated hash for the item.
41
+ */
42
+ proofObjectHash;
43
+ /**
44
+ * The verifiable storage id.
45
+ */
46
+ verifiableStorageId;
47
+ };
48
+ __decorate([
49
+ property({ type: "string", isPrimary: true }),
50
+ __metadata("design:type", String)
51
+ ], ImmutableProof.prototype, "id", void 0);
52
+ __decorate([
53
+ property({ type: "string" }),
54
+ __metadata("design:type", String)
55
+ ], ImmutableProof.prototype, "nodeIdentity", void 0);
56
+ __decorate([
57
+ property({ type: "string" }),
58
+ __metadata("design:type", String)
59
+ ], ImmutableProof.prototype, "userIdentity", void 0);
60
+ __decorate([
61
+ property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
62
+ __metadata("design:type", String)
63
+ ], ImmutableProof.prototype, "dateCreated", void 0);
64
+ __decorate([
65
+ property({ type: "string", optional: true }),
66
+ __metadata("design:type", String)
67
+ ], ImmutableProof.prototype, "proofObjectId", void 0);
68
+ __decorate([
69
+ property({ type: "string" }),
70
+ __metadata("design:type", String)
71
+ ], ImmutableProof.prototype, "proofObjectHash", void 0);
72
+ __decorate([
73
+ property({ type: "string", optional: true }),
74
+ __metadata("design:type", String)
75
+ ], ImmutableProof.prototype, "verifiableStorageId", void 0);
76
+ ImmutableProof = __decorate([
77
+ entity()
78
+ ], ImmutableProof);
13
79
 
14
80
  /**
15
81
  * The source used when communicating about these routes.
@@ -45,8 +111,8 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
45
111
  id: "immutableProofCreateRequestExample",
46
112
  request: {
47
113
  body: {
48
- proofObject: {
49
- "@context": "http://schema.org",
114
+ document: {
115
+ "@context": "https://schema.org",
50
116
  type: "Person",
51
117
  name: "John Smith"
52
118
  }
@@ -106,15 +172,19 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
106
172
  id: "immutableProofGetResponseExample",
107
173
  response: {
108
174
  body: {
109
- "@context": ImmutableProofTypes.ContextRoot,
175
+ "@context": [
176
+ ImmutableProofContexts.ContextRoot,
177
+ ImmutableProofContexts.ContextRootCommon
178
+ ],
110
179
  type: ImmutableProofTypes.ImmutableProof,
111
180
  id: "ais:1234567890",
181
+ nodeIdentity: "node-1",
112
182
  userIdentity: "user-1",
113
183
  proofObjectId: "test:1234567890",
114
184
  proofObjectHash: "EAOKyDN0mYQbBh91eMdVeroxQx1H4GfnRbmt6n/2L/Y=",
115
185
  proof: {
116
- "@context": DidContexts.ContextVCDataIntegrity,
117
- type: DidTypes.DataIntegrityProof,
186
+ "@context": DidContexts.ContextDataIntegrity,
187
+ type: ProofTypes.DataIntegrityProof,
118
188
  cryptosuite: DidCryptoSuites.EdDSAJcs2022,
119
189
  created: "2024-08-22T11:56:56.272Z",
120
190
  proofPurpose: "assertionMethod",
@@ -136,15 +206,19 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
136
206
  [HeaderTypes.ContentType]: MimeTypes.JsonLd
137
207
  },
138
208
  body: {
139
- "@context": ImmutableProofTypes.ContextRoot,
209
+ "@context": [
210
+ ImmutableProofContexts.ContextRoot,
211
+ ImmutableProofContexts.ContextRootCommon
212
+ ],
140
213
  type: ImmutableProofTypes.ImmutableProof,
141
214
  id: "ais:1234567890",
215
+ nodeIdentity: "node-1",
142
216
  userIdentity: "user-1",
143
217
  proofObjectId: "test:1234567890",
144
218
  proofObjectHash: "EAOKyDN0mYQbBh91eMdVeroxQx1H4GfnRbmt6n/2L/Y=",
145
219
  proof: {
146
- "@context": DidContexts.ContextVCDataIntegrity,
147
- type: DidTypes.DataIntegrityProof,
220
+ "@context": DidContexts.ContextDataIntegrity,
221
+ type: ProofTypes.DataIntegrityProof,
148
222
  cryptosuite: DidCryptoSuites.EdDSAJcs2022,
149
223
  created: "2024-08-22T11:56:56.272Z",
150
224
  proofPurpose: "assertionMethod",
@@ -164,8 +238,8 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
164
238
  operationId: "immutableProofVerify",
165
239
  summary: "Verify a proof",
166
240
  tag: tagsImmutableProof[0].name,
167
- method: "POST",
168
- path: `${baseRouteName}/:id`,
241
+ method: "GET",
242
+ path: `${baseRouteName}/:id/verify`,
169
243
  handler: async (httpRequestContext, request) => immutableProofVerify(httpRequestContext, componentName, request),
170
244
  requestType: {
171
245
  type: "IImmutableProofVerifyRequest",
@@ -175,13 +249,6 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
175
249
  request: {
176
250
  pathParams: {
177
251
  id: "ais:1234567890"
178
- },
179
- body: {
180
- proofObject: {
181
- "@context": "http://schema.org",
182
- type: "Person",
183
- name: "John Smith"
184
- }
185
252
  }
186
253
  }
187
254
  }
@@ -195,7 +262,7 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
195
262
  id: "immutableProofVerifyResponseExample",
196
263
  response: {
197
264
  body: {
198
- "@context": ImmutableProofTypes.ContextRoot,
265
+ "@context": ImmutableProofContexts.ContextRoot,
199
266
  type: ImmutableProofTypes.ImmutableProofVerification,
200
267
  verified: true
201
268
  }
@@ -210,7 +277,7 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
210
277
  id: "immutableProofVerifyResponseFailExample",
211
278
  response: {
212
279
  body: {
213
- "@context": ImmutableProofTypes.ContextRoot,
280
+ "@context": ImmutableProofContexts.ContextRoot,
214
281
  type: ImmutableProofTypes.ImmutableProofVerification,
215
282
  verified: false,
216
283
  failure: ImmutableProofFailure.ProofTypeMismatch
@@ -235,9 +302,9 @@ function generateRestRoutesImmutableProof(baseRouteName, componentName) {
235
302
  */
236
303
  async function immutableProofCreate(httpRequestContext, componentName, request) {
237
304
  Guards.object(ROUTES_SOURCE, "request", request);
238
- Guards.object(ROUTES_SOURCE, "request.body.proofObject", request.body.proofObject);
305
+ Guards.object(ROUTES_SOURCE, "request.body.document", request.body.document);
239
306
  const component = ComponentFactory.get(componentName);
240
- const result = await component.create(request.body.proofObject);
307
+ const result = await component.create(request.body.document, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
241
308
  return {
242
309
  statusCode: HttpStatusCode.created,
243
310
  headers: {
@@ -277,10 +344,9 @@ async function immutableProofVerify(httpRequestContext, componentName, request)
277
344
  Guards.object(ROUTES_SOURCE, "request", request);
278
345
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
279
346
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
280
- Guards.object(ROUTES_SOURCE, "request.body.proofObject", request.body.proofObject);
281
347
  const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
282
348
  const component = ComponentFactory.get(componentName);
283
- const result = await component.verify(request.pathParams.id, request.body.proofObject);
349
+ const result = await component.verify(request.pathParams.id);
284
350
  return {
285
351
  headers: {
286
352
  [HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
@@ -308,11 +374,6 @@ class ImmutableProofService {
308
374
  * @internal
309
375
  */
310
376
  _config;
311
- /**
312
- * The vault connector.
313
- * @internal
314
- */
315
- _vaultConnector;
316
377
  /**
317
378
  * The identity connector.
318
379
  * @internal
@@ -324,74 +385,89 @@ class ImmutableProofService {
324
385
  */
325
386
  _proofStorage;
326
387
  /**
327
- * The immutable storage for the credentials.
388
+ * The verifiable storage for the credentials.
389
+ * @internal
390
+ */
391
+ _verifiableStorage;
392
+ /**
393
+ * The background task connector.
328
394
  * @internal
329
395
  */
330
- _immutableStorage;
396
+ _backgroundTaskConnector;
331
397
  /**
332
- * The assertion method id to use for the proofs.
398
+ * The event bus component.
333
399
  * @internal
334
400
  */
335
- _assertionMethodId;
401
+ _eventBusComponent;
336
402
  /**
337
- * The proof config key id to use for the proofs.
403
+ * The verification method id to use for the proofs.
338
404
  * @internal
339
405
  */
340
- _proofConfigKeyId;
406
+ _verificationMethodId;
341
407
  /**
342
- * Are we currently processing proofs.
408
+ * The identity connector type.
343
409
  * @internal
344
410
  */
345
- _processing;
411
+ _identityConnectorType;
346
412
  /**
347
413
  * Create a new instance of ImmutableProofService.
348
414
  * @param options The dependencies for the immutable proof connector.
349
- * @param options.config The configuration for the connector.
350
- * @param options.vaultConnectorType The vault connector type, defaults to "vault".
351
- * @param options.immutableProofEntityStorageType The entity storage for proofs, defaults to "immutable-proof".
352
- * @param options.immutableStorageType The immutable storage, defaults to "immutable-storage".
353
- * @param options.identityConnectorType The identity connector type, defaults to "identity".
354
415
  */
355
416
  constructor(options) {
356
- this._vaultConnector = VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
357
417
  this._proofStorage = EntityStorageConnectorFactory.get(options?.immutableProofEntityStorageType ?? StringHelper.kebabCase("ImmutableProof"));
358
- this._immutableStorage = ImmutableStorageConnectorFactory.get(options?.immutableStorageType ?? "immutable-storage");
359
- this._identityConnector = IdentityConnectorFactory.get(options?.identityConnectorType ?? "identity");
418
+ this._verifiableStorage = VerifiableStorageConnectorFactory.get(options?.verifiableStorageType ?? "verifiable-storage");
419
+ this._identityConnectorType = options?.identityConnectorType ?? "identity";
420
+ this._identityConnector = IdentityConnectorFactory.get(this._identityConnectorType);
421
+ this._backgroundTaskConnector = BackgroundTaskConnectorFactory.get(options?.backgroundTaskConnectorType ?? "background-task");
422
+ if (Is.stringValue(options?.eventBusComponentType)) {
423
+ this._eventBusComponent = ComponentFactory.get(options.eventBusComponentType);
424
+ }
360
425
  this._config = options?.config ?? {};
361
- this._assertionMethodId = this._config.assertionMethodId ?? "immutable-proof";
362
- this._proofConfigKeyId = this._config.proofConfigKeyId ?? "immutable-proof";
363
- SchemaOrgDataTypes.registerRedirects();
364
- this._processing = false;
426
+ this._verificationMethodId = this._config.verificationMethodId ?? "immutable-proof-assertion";
427
+ this._backgroundTaskConnector.registerHandler("immutable-proof", "@twin.org/immutable-proof-task", "processProofTask", async (task) => {
428
+ await this.finaliseTask(task);
429
+ });
365
430
  }
366
431
  /**
367
- * Create a new authentication proof.
368
- * @param proofObject The object for the proof as JSON-LD.
432
+ * Create a new proof.
433
+ * @param document The document to create the proof for.
369
434
  * @param userIdentity The identity to create the immutable proof operation with.
370
435
  * @param nodeIdentity The node identity to use for vault operations.
371
- * @returns The id of the new authentication proof.
436
+ * @returns The id of the new proof.
372
437
  */
373
- async create(proofObject, userIdentity, nodeIdentity) {
374
- Guards.object(this.CLASS_NAME, "proofObject", proofObject);
438
+ async create(document, userIdentity, nodeIdentity) {
439
+ Guards.object(this.CLASS_NAME, "document", document);
375
440
  Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
376
441
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
377
442
  try {
378
443
  const validationFailures = [];
379
- await JsonLdHelper.validate(proofObject, validationFailures);
380
- Validation.asValidationError(this.CLASS_NAME, "proofObject", validationFailures);
444
+ await JsonLdHelper.validate(document, validationFailures);
445
+ Validation.asValidationError(this.CLASS_NAME, "document", validationFailures);
381
446
  const id = Converter.bytesToHex(RandomHelper.generate(32), false);
382
447
  const dateCreated = new Date(Date.now()).toISOString();
383
- const proofObjectId = ObjectHelper.extractProperty(proofObject, ["@id", "id"], false);
384
- const hash = this.calculateHash(id, dateCreated, nodeIdentity, userIdentity, proofObject);
448
+ const proofObjectId = ObjectHelper.extractProperty(document, ["@id", "id"], false);
449
+ // We don't want to store the whole document in the immutable proof, as this could be large
450
+ // and also reveal information that should not be stored in the proof so we hash the document
451
+ // and store the hash
452
+ const proofObjectHash = this.calculateDocumentHash(document);
385
453
  const proofEntity = {
386
454
  id,
387
455
  nodeIdentity,
388
456
  userIdentity,
389
457
  dateCreated,
390
458
  proofObjectId,
391
- proofObjectHash: Converter.bytesToBase64(hash)
459
+ proofObjectHash
392
460
  };
393
461
  await this._proofStorage.set(proofEntity);
394
- this.startProcessingProofs();
462
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
463
+ const proofTaskPayload = {
464
+ proofId: id,
465
+ nodeIdentity,
466
+ identityConnectorType: this._identityConnectorType,
467
+ verificationMethodId: this._verificationMethodId,
468
+ document: immutableProof
469
+ };
470
+ await this._backgroundTaskConnector.create("immutable-proof", proofTaskPayload);
395
471
  return new Urn(ImmutableProofService.NAMESPACE, id).toString();
396
472
  }
397
473
  catch (error) {
@@ -399,7 +475,7 @@ class ImmutableProofService {
399
475
  }
400
476
  }
401
477
  /**
402
- * Get an authentication proof.
478
+ * Get a proof.
403
479
  * @param id The id of the proof to get.
404
480
  * @returns The proof.
405
481
  * @throws NotFoundError if the proof is not found.
@@ -414,22 +490,20 @@ class ImmutableProofService {
414
490
  });
415
491
  }
416
492
  try {
417
- const { immutableProof } = await this.internalGet(id);
418
- const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
419
- return compacted;
493
+ const { immutableProof } = await this.internalGet(id, false);
494
+ return JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
420
495
  }
421
496
  catch (error) {
422
497
  throw new GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
423
498
  }
424
499
  }
425
500
  /**
426
- * Verify an authentication proof.
501
+ * Verify a proof.
427
502
  * @param id The id of the proof to verify.
428
- * @param proofObject The object to verify as JSON-LD.
429
503
  * @returns The result of the verification and any failures.
430
504
  * @throws NotFoundError if the proof is not found.
431
505
  */
432
- async verify(id, proofObject) {
506
+ async verify(id) {
433
507
  Guards.stringValue(this.CLASS_NAME, "id", id);
434
508
  const urnParsed = Urn.fromValidString(id);
435
509
  if (urnParsed.namespaceIdentifier() !== ImmutableProofService.NAMESPACE) {
@@ -439,9 +513,9 @@ class ImmutableProofService {
439
513
  });
440
514
  }
441
515
  try {
442
- const { verified, failure } = await this.internalGet(id, proofObject);
516
+ const { verified, failure } = await this.internalGet(id, true);
443
517
  return {
444
- "@context": ImmutableProofTypes.ContextRoot,
518
+ "@context": ImmutableProofContexts.ContextRoot,
445
519
  type: ImmutableProofTypes.ImmutableProofVerification,
446
520
  verified,
447
521
  failure
@@ -452,13 +526,13 @@ class ImmutableProofService {
452
526
  }
453
527
  }
454
528
  /**
455
- * Remove the immutable storage for the proof.
529
+ * Remove the verifiable storage for the proof.
456
530
  * @param id The id of the proof to remove the storage from.
457
531
  * @param nodeIdentity The node identity to use for vault operations.
458
532
  * @returns Nothing.
459
533
  * @throws NotFoundError if the proof is not found.
460
534
  */
461
- async removeImmutable(id, nodeIdentity) {
535
+ async removeVerifiable(id, nodeIdentity) {
462
536
  Guards.stringValue(this.CLASS_NAME, "id", id);
463
537
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
464
538
  const urnParsed = Urn.fromValidString(id);
@@ -474,14 +548,14 @@ class ImmutableProofService {
474
548
  if (Is.empty(streamEntity)) {
475
549
  throw new NotFoundError(this.CLASS_NAME, "proofNotFound", id);
476
550
  }
477
- if (Is.stringValue(streamEntity.immutableStorageId)) {
478
- await this._immutableStorage.remove(nodeIdentity, streamEntity.immutableStorageId);
479
- delete streamEntity.immutableStorageId;
551
+ if (Is.stringValue(streamEntity.verifiableStorageId)) {
552
+ await this._verifiableStorage.remove(nodeIdentity, streamEntity.verifiableStorageId);
553
+ delete streamEntity.verifiableStorageId;
480
554
  await this._proofStorage.set(streamEntity);
481
555
  }
482
556
  }
483
557
  catch (error) {
484
- throw new GeneralError(this.CLASS_NAME, "removeImmutableFailed", undefined, error);
558
+ throw new GeneralError(this.CLASS_NAME, "removeVerifiableFailed", undefined, error);
485
559
  }
486
560
  }
487
561
  /**
@@ -490,14 +564,8 @@ class ImmutableProofService {
490
564
  * @returns The hash.
491
565
  * @internal
492
566
  */
493
- calculateHash(id, dateCreated, nodeIdentity, userIdentity, proofObject) {
494
- const b2b = new Blake2b(Blake2b.SIZE_256);
495
- b2b.update(Converter.utf8ToBytes(id));
496
- b2b.update(Converter.utf8ToBytes(dateCreated));
497
- b2b.update(Converter.utf8ToBytes(nodeIdentity));
498
- b2b.update(Converter.utf8ToBytes(userIdentity));
499
- b2b.update(ObjectHelper.toBytes(proofObject));
500
- return b2b.digest();
567
+ calculateDocumentHash(nodeObject) {
568
+ return `sha256:${Converter.bytesToBase64(Sha256.sum256(ObjectHelper.toBytes(JsonHelper.canonicalize(nodeObject))))}`;
501
569
  }
502
570
  /**
503
571
  * Map the stream entity to a model.
@@ -505,99 +573,84 @@ class ImmutableProofService {
505
573
  * @returns The model.
506
574
  * @internal
507
575
  */
508
- proofEntityToModel(proofEntity) {
509
- const model = {
510
- "@context": [
511
- ImmutableProofTypes.ContextRoot,
512
- SchemaOrgTypes.ContextRoot,
513
- DidContexts.ContextVCDataIntegrity
514
- ],
576
+ proofEntityToJsonLd(proofEntity) {
577
+ const jsonLd = {
578
+ "@context": [ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon],
515
579
  type: ImmutableProofTypes.ImmutableProof,
516
580
  id: proofEntity.id,
581
+ nodeIdentity: proofEntity.nodeIdentity,
517
582
  userIdentity: proofEntity.userIdentity,
518
583
  proofObjectId: proofEntity.proofObjectId,
519
- proofObjectHash: proofEntity.proofObjectHash
584
+ proofObjectHash: proofEntity.proofObjectHash,
585
+ verifiableStorageId: proofEntity.verifiableStorageId
520
586
  };
521
- return model;
587
+ return jsonLd;
522
588
  }
523
589
  /**
524
- * Start processing proofs.
525
- * @returns Nothing.
590
+ * Process a proof.
591
+ * @param proofEntity The proof entity to process.
526
592
  * @internal
527
593
  */
528
- startProcessingProofs() {
529
- if (!this._processing) {
530
- setTimeout(async () => {
531
- await this.processProofs();
532
- }, 0);
533
- }
534
- }
535
- /**
536
- * Process the proofs.
537
- * @internal
538
- */
539
- async processProofs() {
540
- // Get the oldest pending proof, plus one more, we can then determine whether to
541
- // trigger another process after this one
542
- const pendingProofs = await this._proofStorage.query({
543
- property: "immutableStorageId",
544
- comparison: ComparisonOperator.Equals,
545
- value: undefined
546
- }, [
547
- {
548
- property: "dateCreated",
549
- sortDirection: SortDirection.Ascending
594
+ async finaliseTask(task) {
595
+ if (task.status === TaskStatus.Success && Is.object(task.payload) && Is.object(task.result)) {
596
+ const proofEntity = await this._proofStorage.get(task.payload.proofId);
597
+ if (Is.object(proofEntity)) {
598
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
599
+ // As we are adding the proof to the data we update its context
600
+ immutableProof["@context"] = JsonLdProcessor.combineContexts([ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon], task.result.proof["@context"]);
601
+ immutableProof.proof = task.result.proof;
602
+ ObjectHelper.propertyDelete(immutableProof.proof, "@context");
603
+ if (Is.stringValue(immutableProof.proof.created)) {
604
+ proofEntity.dateCreated = immutableProof.proof.created;
605
+ }
606
+ const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
607
+ const verifiableCreateResult = await this._verifiableStorage.create(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
608
+ proofEntity.verifiableStorageId = verifiableCreateResult.id;
609
+ await this._proofStorage.set(proofEntity);
610
+ await this._eventBusComponent?.publish(ImmutableProofTopics.ProofCreated, { id: new Urn(ImmutableProofService.NAMESPACE, task.payload.proofId).toString() });
550
611
  }
551
- ], undefined, undefined, 2);
552
- if (pendingProofs.entities.length > 0) {
553
- const proofEntity = pendingProofs.entities[0];
554
- const immutableProof = this.proofEntityToModel(proofEntity);
555
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
556
- immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
557
- proofEntity.dateCreated = immutableProof.proof.created ?? new Date(Date.now()).toISOString();
558
- const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
559
- proofEntity.immutableStorageId = await this._immutableStorage.store(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
560
- await this._proofStorage.set(proofEntity);
561
- }
562
- // If there are still remaining proofs, start the timer again
563
- this._processing = false;
564
- if (pendingProofs.entities.length > 1) {
565
- this.startProcessingProofs();
566
612
  }
567
613
  }
568
614
  /**
569
- * Verify an authentication proof.
615
+ * Verify a proof.
570
616
  * @param id The id of the proof to verify.
571
- * @param proofObject The object to verify as JSON-LD.
617
+ * @param verify Validate the proof.
572
618
  * @returns The result of the verification and any failures.
573
619
  * @throws NotFoundError if the proof is not found.
574
620
  * @internal
575
621
  */
576
- async internalGet(id, proofObject) {
622
+ async internalGet(id, verify) {
577
623
  const urnParsed = Urn.fromValidString(id);
578
624
  const proofId = urnParsed.namespaceSpecific(0);
579
625
  const proofEntity = await this._proofStorage.get(proofId);
580
626
  if (Is.empty(proofEntity)) {
581
627
  throw new NotFoundError(this.CLASS_NAME, "proofNotFound", id);
582
628
  }
583
- let proofModel = await this.proofEntityToModel(proofEntity);
629
+ let proofJsonLd = this.proofEntityToJsonLd(proofEntity);
584
630
  let verified = false;
585
631
  let failure = ImmutableProofFailure.NotIssued;
586
- if (Is.stringValue(proofEntity.immutableStorageId)) {
632
+ if (Is.stringValue(proofEntity.verifiableStorageId)) {
587
633
  failure = ImmutableProofFailure.ProofMissing;
588
- const immutableData = await this._immutableStorage.get(proofEntity.immutableStorageId);
589
- if (Is.uint8Array(immutableData)) {
590
- proofModel = ObjectHelper.fromBytes(immutableData);
591
- if (Is.object(proofModel.proof) && Is.object(proofObject)) {
592
- if (proofModel.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
634
+ const immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);
635
+ if (Is.uint8Array(immutableResult.data)) {
636
+ proofJsonLd = ObjectHelper.fromBytes(immutableResult.data);
637
+ const unsecureDocument = ObjectHelper.clone(proofJsonLd);
638
+ proofJsonLd.immutableReceipt = immutableResult.receipt;
639
+ proofJsonLd.verifiableStorageId = proofEntity.verifiableStorageId;
640
+ // As we are adding the receipt to the data we update the JSON-LD context
641
+ const receiptContext = immutableResult.receipt["@context"];
642
+ if (!Is.empty(receiptContext)) {
643
+ proofJsonLd["@context"] = JsonLdProcessor.combineContexts(proofJsonLd["@context"], receiptContext);
644
+ }
645
+ if (verify && Is.object(proofJsonLd.proof)) {
646
+ if (proofJsonLd.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
593
647
  failure = ImmutableProofFailure.CryptoSuiteMismatch;
594
648
  }
595
- else if (proofModel.proof.type !== DidTypes.DataIntegrityProof) {
649
+ else if (proofJsonLd.proof.type !== ProofTypes.DataIntegrityProof) {
596
650
  failure = ImmutableProofFailure.ProofTypeMismatch;
597
651
  }
598
652
  else {
599
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, proofModel);
600
- const isVerified = await this._identityConnector.verifyProof(hashData, proofModel.proof);
653
+ const isVerified = await this._identityConnector.verifyProof(unsecureDocument, proofJsonLd.proof);
601
654
  if (isVerified) {
602
655
  verified = true;
603
656
  failure = undefined;
@@ -610,98 +663,13 @@ class ImmutableProofService {
610
663
  }
611
664
  }
612
665
  return {
613
- immutableProof: proofModel,
666
+ immutableProof: proofJsonLd,
614
667
  verified,
615
668
  failure
616
669
  };
617
670
  }
618
- /**
619
- * Generate the hash data for the proof.
620
- * Conforms to https://www.w3.org/TR/vc-di-eddsa/#create-proof-eddsa-jcs-2022
621
- * @param nodeIdentity The node identity to use for vault operations.
622
- * @param immutableProof The immutable proof to generate the hash data for.
623
- * @returns The hash data.
624
- * @internal
625
- */
626
- async generateHashData(nodeIdentity, immutableProof) {
627
- const canonicalDocument = JsonHelper.canonicalize(ObjectHelper.omit(immutableProof, ["proof"]));
628
- const proofConfigKey = await this._vaultConnector.getKey(`${nodeIdentity}/${this._proofConfigKeyId}`);
629
- const proofConfigHash = Sha256.sum256(proofConfigKey.privateKey);
630
- const transformedDocumentHash = Sha256.sum256(Converter.utf8ToBytes(canonicalDocument));
631
- const hashData = new Uint8Array(proofConfigHash.length + transformedDocumentHash.length);
632
- hashData.set(proofConfigHash);
633
- hashData.set(transformedDocumentHash, proofConfigHash.length);
634
- return hashData;
635
- }
636
671
  }
637
672
 
638
- // Copyright 2024 IOTA Stiftung.
639
- // SPDX-License-Identifier: Apache-2.0.
640
- /**
641
- * Class describing the immutable proof.
642
- */
643
- let ImmutableProof = class ImmutableProof {
644
- /**
645
- * The id of the proof.
646
- */
647
- id;
648
- /**
649
- * The identity of the node which controls the proof.
650
- */
651
- nodeIdentity;
652
- /**
653
- * The identity of the user which created the proof.
654
- */
655
- userIdentity;
656
- /**
657
- * The date/time of when the proof was created.
658
- */
659
- dateCreated;
660
- /**
661
- * The associated id for the item.
662
- */
663
- proofObjectId;
664
- /**
665
- * The associated hash for the item.
666
- */
667
- proofObjectHash;
668
- /**
669
- * The immutable storage id.
670
- */
671
- immutableStorageId;
672
- };
673
- __decorate([
674
- property({ type: "string", isPrimary: true }),
675
- __metadata("design:type", String)
676
- ], ImmutableProof.prototype, "id", void 0);
677
- __decorate([
678
- property({ type: "string" }),
679
- __metadata("design:type", String)
680
- ], ImmutableProof.prototype, "nodeIdentity", void 0);
681
- __decorate([
682
- property({ type: "string" }),
683
- __metadata("design:type", String)
684
- ], ImmutableProof.prototype, "userIdentity", void 0);
685
- __decorate([
686
- property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
687
- __metadata("design:type", String)
688
- ], ImmutableProof.prototype, "dateCreated", void 0);
689
- __decorate([
690
- property({ type: "string" }),
691
- __metadata("design:type", String)
692
- ], ImmutableProof.prototype, "proofObjectId", void 0);
693
- __decorate([
694
- property({ type: "string" }),
695
- __metadata("design:type", String)
696
- ], ImmutableProof.prototype, "proofObjectHash", void 0);
697
- __decorate([
698
- property({ type: "string" }),
699
- __metadata("design:type", String)
700
- ], ImmutableProof.prototype, "immutableStorageId", void 0);
701
- ImmutableProof = __decorate([
702
- entity()
703
- ], ImmutableProof);
704
-
705
673
  const restEntryPoints = [
706
674
  {
707
675
  name: "immutable-proof",