@twin.org/immutable-proof-service 0.0.1-next.9 → 0.0.2-next.1

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 { BackgroundTaskConnectorFactory } from '@twin.org/background-task-models';
6
- import { Blake2b, Sha256 } from '@twin.org/crypto';
6
+ import { BackgroundTaskConnectorFactory, TaskStatus } from '@twin.org/background-task-models';
7
+ import { Sha256 } from '@twin.org/crypto';
7
8
  import { JsonLdHelper, JsonLdProcessor } from '@twin.org/data-json-ld';
8
9
  import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
9
10
  import { IdentityConnectorFactory } from '@twin.org/identity-models';
10
- import { ImmutableStorageConnectorFactory, ImmutableStorageTypes } from '@twin.org/immutable-storage-models';
11
- import { VaultConnectorFactory } from '@twin.org/vault-models';
12
- import { property, SortDirection, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
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
@@ -297,8 +363,9 @@ async function immutableProofVerify(httpRequestContext, componentName, request)
297
363
  class ImmutableProofService {
298
364
  /**
299
365
  * The namespace for the service.
366
+ * @internal
300
367
  */
301
- static NAMESPACE = "immutable-proof";
368
+ static _NAMESPACE = "immutable-proof";
302
369
  /**
303
370
  * Runtime name for the class.
304
371
  */
@@ -308,11 +375,6 @@ class ImmutableProofService {
308
375
  * @internal
309
376
  */
310
377
  _config;
311
- /**
312
- * The vault connector.
313
- * @internal
314
- */
315
- _vaultConnector;
316
378
  /**
317
379
  * The identity connector.
318
380
  * @internal
@@ -324,83 +386,97 @@ class ImmutableProofService {
324
386
  */
325
387
  _proofStorage;
326
388
  /**
327
- * The immutable storage for the credentials.
389
+ * The verifiable storage for the credentials.
328
390
  * @internal
329
391
  */
330
- _immutableStorage;
392
+ _verifiableStorage;
331
393
  /**
332
394
  * The background task connector.
333
395
  * @internal
334
396
  */
335
397
  _backgroundTaskConnector;
336
398
  /**
337
- * The assertion method id to use for the proofs.
399
+ * The event bus component.
338
400
  * @internal
339
401
  */
340
- _assertionMethodId;
402
+ _eventBusComponent;
341
403
  /**
342
- * The proof hash key id to use for the proofs.
404
+ * The verification method id to use for the proofs.
343
405
  * @internal
344
406
  */
345
- _proofHashKeyId;
407
+ _verificationMethodId;
408
+ /**
409
+ * The identity connector type.
410
+ * @internal
411
+ */
412
+ _identityConnectorType;
346
413
  /**
347
414
  * Create a new instance of ImmutableProofService.
348
415
  * @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
- * @param options.backgroundTaskConnectorType The background task connector type, defaults to "background-task".
355
416
  */
356
417
  constructor(options) {
357
- this._vaultConnector = VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
358
418
  this._proofStorage = EntityStorageConnectorFactory.get(options?.immutableProofEntityStorageType ?? StringHelper.kebabCase("ImmutableProof"));
359
- this._immutableStorage = ImmutableStorageConnectorFactory.get(options?.immutableStorageType ?? "immutable-storage");
360
- this._identityConnector = IdentityConnectorFactory.get(options?.identityConnectorType ?? "identity");
419
+ this._verifiableStorage = VerifiableStorageConnectorFactory.get(options?.verifiableStorageType ?? "verifiable-storage");
420
+ this._identityConnectorType = options?.identityConnectorType ?? "identity";
421
+ this._identityConnector = IdentityConnectorFactory.get(this._identityConnectorType);
361
422
  this._backgroundTaskConnector = BackgroundTaskConnectorFactory.get(options?.backgroundTaskConnectorType ?? "background-task");
423
+ if (Is.stringValue(options?.eventBusComponentType)) {
424
+ this._eventBusComponent = ComponentFactory.get(options.eventBusComponentType);
425
+ }
362
426
  this._config = options?.config ?? {};
363
- this._assertionMethodId = this._config.assertionMethodId ?? "immutable-proof-assertion";
364
- this._proofHashKeyId = this._config.proofHashKeyId ?? "immutable-proof-hash";
365
- this._backgroundTaskConnector.registerHandler("immutable-proof", async (proof) => this.processProof(proof));
427
+ this._verificationMethodId = this._config.verificationMethodId ?? "immutable-proof-assertion";
428
+ this._backgroundTaskConnector.registerHandler("immutable-proof", "@twin.org/immutable-proof-task", "processProofTask", async (task) => {
429
+ await this.finaliseTask(task);
430
+ });
366
431
  }
367
432
  /**
368
- * Create a new authentication proof.
369
- * @param proofObject The object for the proof as JSON-LD.
433
+ * Create a new proof.
434
+ * @param document The document to create the proof for.
370
435
  * @param userIdentity The identity to create the immutable proof operation with.
371
436
  * @param nodeIdentity The node identity to use for vault operations.
372
- * @returns The id of the new authentication proof.
437
+ * @returns The id of the new proof.
373
438
  */
374
- async create(proofObject, userIdentity, nodeIdentity) {
375
- Guards.object(this.CLASS_NAME, "proofObject", proofObject);
439
+ async create(document, userIdentity, nodeIdentity) {
440
+ Guards.object(this.CLASS_NAME, "document", document);
376
441
  Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
377
442
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
378
443
  try {
379
444
  const validationFailures = [];
380
- await JsonLdHelper.validate(proofObject, validationFailures);
381
- Validation.asValidationError(this.CLASS_NAME, "proofObject", validationFailures);
445
+ await JsonLdHelper.validate(document, validationFailures);
446
+ Validation.asValidationError(this.CLASS_NAME, "document", validationFailures);
382
447
  const id = Converter.bytesToHex(RandomHelper.generate(32), false);
383
448
  const dateCreated = new Date(Date.now()).toISOString();
384
- const proofObjectId = ObjectHelper.extractProperty(proofObject, ["@id", "id"], false);
385
- const hash = this.calculateHash(id, dateCreated, nodeIdentity, userIdentity, proofObject);
449
+ const proofObjectId = ObjectHelper.extractProperty(document, ["@id", "id"], false);
450
+ // We don't want to store the whole document in the immutable proof, as this could be large
451
+ // and also reveal information that should not be stored in the proof so we hash the document
452
+ // and store the hash
453
+ const proofObjectHash = this.calculateDocumentHash(document);
386
454
  const proofEntity = {
387
455
  id,
388
456
  nodeIdentity,
389
457
  userIdentity,
390
458
  dateCreated,
391
459
  proofObjectId,
392
- proofObjectHash: Converter.bytesToBase64(hash)
460
+ proofObjectHash
393
461
  };
394
462
  await this._proofStorage.set(proofEntity);
395
- await this._backgroundTaskConnector.create("immutable-proof", proofEntity);
396
- return new Urn(ImmutableProofService.NAMESPACE, id).toString();
463
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
464
+ const proofTaskPayload = {
465
+ proofId: id,
466
+ nodeIdentity,
467
+ identityConnectorType: this._identityConnectorType,
468
+ verificationMethodId: this._verificationMethodId,
469
+ document: immutableProof
470
+ };
471
+ await this._backgroundTaskConnector.create("immutable-proof", proofTaskPayload);
472
+ return new Urn(ImmutableProofService._NAMESPACE, id).toString();
397
473
  }
398
474
  catch (error) {
399
475
  throw new GeneralError(this.CLASS_NAME, "createFailed", undefined, error);
400
476
  }
401
477
  }
402
478
  /**
403
- * Get an authentication proof.
479
+ * Get a proof.
404
480
  * @param id The id of the proof to get.
405
481
  * @returns The proof.
406
482
  * @throws NotFoundError if the proof is not found.
@@ -408,41 +484,39 @@ class ImmutableProofService {
408
484
  async get(id) {
409
485
  Guards.stringValue(this.CLASS_NAME, "id", id);
410
486
  const urnParsed = Urn.fromValidString(id);
411
- if (urnParsed.namespaceIdentifier() !== ImmutableProofService.NAMESPACE) {
487
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
412
488
  throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
413
- namespace: ImmutableProofService.NAMESPACE,
489
+ namespace: ImmutableProofService._NAMESPACE,
414
490
  id
415
491
  });
416
492
  }
417
493
  try {
418
- const { immutableProof } = await this.internalGet(id);
419
- const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
420
- return compacted;
494
+ const { immutableProof } = await this.internalGet(id, false);
495
+ return JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
421
496
  }
422
497
  catch (error) {
423
498
  throw new GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
424
499
  }
425
500
  }
426
501
  /**
427
- * Verify an authentication proof.
502
+ * Verify a proof.
428
503
  * @param id The id of the proof to verify.
429
- * @param proofObject The object to verify as JSON-LD.
430
504
  * @returns The result of the verification and any failures.
431
505
  * @throws NotFoundError if the proof is not found.
432
506
  */
433
- async verify(id, proofObject) {
507
+ async verify(id) {
434
508
  Guards.stringValue(this.CLASS_NAME, "id", id);
435
509
  const urnParsed = Urn.fromValidString(id);
436
- if (urnParsed.namespaceIdentifier() !== ImmutableProofService.NAMESPACE) {
510
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
437
511
  throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
438
- namespace: ImmutableProofService.NAMESPACE,
512
+ namespace: ImmutableProofService._NAMESPACE,
439
513
  id
440
514
  });
441
515
  }
442
516
  try {
443
- const { verified, failure } = await this.internalGet(id, proofObject);
517
+ const { verified, failure } = await this.internalGet(id, true);
444
518
  return {
445
- "@context": ImmutableProofTypes.ContextRoot,
519
+ "@context": ImmutableProofContexts.ContextRoot,
446
520
  type: ImmutableProofTypes.ImmutableProofVerification,
447
521
  verified,
448
522
  failure
@@ -453,19 +527,19 @@ class ImmutableProofService {
453
527
  }
454
528
  }
455
529
  /**
456
- * Remove the immutable storage for the proof.
530
+ * Remove the verifiable storage for the proof.
457
531
  * @param id The id of the proof to remove the storage from.
458
532
  * @param nodeIdentity The node identity to use for vault operations.
459
533
  * @returns Nothing.
460
534
  * @throws NotFoundError if the proof is not found.
461
535
  */
462
- async removeImmutable(id, nodeIdentity) {
536
+ async removeVerifiable(id, nodeIdentity) {
463
537
  Guards.stringValue(this.CLASS_NAME, "id", id);
464
538
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
465
539
  const urnParsed = Urn.fromValidString(id);
466
- if (urnParsed.namespaceIdentifier() !== ImmutableProofService.NAMESPACE) {
540
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
467
541
  throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
468
- namespace: ImmutableProofService.NAMESPACE,
542
+ namespace: ImmutableProofService._NAMESPACE,
469
543
  id
470
544
  });
471
545
  }
@@ -475,14 +549,14 @@ class ImmutableProofService {
475
549
  if (Is.empty(streamEntity)) {
476
550
  throw new NotFoundError(this.CLASS_NAME, "proofNotFound", id);
477
551
  }
478
- if (Is.stringValue(streamEntity.immutableStorageId)) {
479
- await this._immutableStorage.remove(nodeIdentity, streamEntity.immutableStorageId);
480
- delete streamEntity.immutableStorageId;
552
+ if (Is.stringValue(streamEntity.verifiableStorageId)) {
553
+ await this._verifiableStorage.remove(nodeIdentity, streamEntity.verifiableStorageId);
554
+ delete streamEntity.verifiableStorageId;
481
555
  await this._proofStorage.set(streamEntity);
482
556
  }
483
557
  }
484
558
  catch (error) {
485
- throw new GeneralError(this.CLASS_NAME, "removeImmutableFailed", undefined, error);
559
+ throw new GeneralError(this.CLASS_NAME, "removeVerifiableFailed", undefined, error);
486
560
  }
487
561
  }
488
562
  /**
@@ -491,14 +565,8 @@ class ImmutableProofService {
491
565
  * @returns The hash.
492
566
  * @internal
493
567
  */
494
- calculateHash(id, dateCreated, nodeIdentity, userIdentity, proofObject) {
495
- const b2b = new Blake2b(Blake2b.SIZE_256);
496
- b2b.update(Converter.utf8ToBytes(id));
497
- b2b.update(Converter.utf8ToBytes(dateCreated));
498
- b2b.update(Converter.utf8ToBytes(nodeIdentity));
499
- b2b.update(Converter.utf8ToBytes(userIdentity));
500
- b2b.update(ObjectHelper.toBytes(proofObject));
501
- return b2b.digest();
568
+ calculateDocumentHash(nodeObject) {
569
+ return `sha256:${Converter.bytesToBase64(Sha256.sum256(ObjectHelper.toBytes(JsonHelper.canonicalize(nodeObject))))}`;
502
570
  }
503
571
  /**
504
572
  * Map the stream entity to a model.
@@ -507,76 +575,83 @@ class ImmutableProofService {
507
575
  * @internal
508
576
  */
509
577
  proofEntityToJsonLd(proofEntity) {
510
- const model = {
511
- "@context": ImmutableProofTypes.ContextRoot,
578
+ const jsonLd = {
579
+ "@context": [ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon],
512
580
  type: ImmutableProofTypes.ImmutableProof,
513
581
  id: proofEntity.id,
582
+ nodeIdentity: proofEntity.nodeIdentity,
514
583
  userIdentity: proofEntity.userIdentity,
515
584
  proofObjectId: proofEntity.proofObjectId,
516
- proofObjectHash: proofEntity.proofObjectHash
585
+ proofObjectHash: proofEntity.proofObjectHash,
586
+ verifiableStorageId: proofEntity.verifiableStorageId
517
587
  };
518
- return model;
588
+ return jsonLd;
519
589
  }
520
590
  /**
521
591
  * Process a proof.
522
592
  * @param proofEntity The proof entity to process.
523
593
  * @internal
524
594
  */
525
- async processProof(proofEntity) {
526
- const immutableProof = this.proofEntityToJsonLd(proofEntity);
527
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
528
- // As we are adding the proof to the data we update its context
529
- immutableProof["@context"] = [
530
- ImmutableProofTypes.ContextRoot,
531
- DidContexts.ContextVCDataIntegrity
532
- ];
533
- immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
534
- if (Is.stringValue(immutableProof.proof.created)) {
535
- proofEntity.dateCreated = immutableProof.proof.created;
595
+ async finaliseTask(task) {
596
+ if (task.status === TaskStatus.Success && Is.object(task.payload) && Is.object(task.result)) {
597
+ const proofEntity = await this._proofStorage.get(task.payload.proofId);
598
+ if (Is.object(proofEntity)) {
599
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
600
+ // As we are adding the proof to the data we update its context
601
+ immutableProof["@context"] = JsonLdProcessor.combineContexts([ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon], task.result.proof["@context"]);
602
+ immutableProof.proof = task.result.proof;
603
+ ObjectHelper.propertyDelete(immutableProof.proof, "@context");
604
+ if (Is.stringValue(immutableProof.proof.created)) {
605
+ proofEntity.dateCreated = immutableProof.proof.created;
606
+ }
607
+ const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
608
+ const verifiableCreateResult = await this._verifiableStorage.create(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
609
+ proofEntity.verifiableStorageId = verifiableCreateResult.id;
610
+ await this._proofStorage.set(proofEntity);
611
+ await this._eventBusComponent?.publish(ImmutableProofTopics.ProofCreated, { id: new Urn(ImmutableProofService._NAMESPACE, task.payload.proofId).toString() });
612
+ }
536
613
  }
537
- const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
538
- const immutableStoreResult = await this._immutableStorage.store(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
539
- proofEntity.immutableStorageId = immutableStoreResult.id;
540
- await this._proofStorage.set(proofEntity);
541
614
  }
542
615
  /**
543
- * Verify an authentication proof.
616
+ * Verify a proof.
544
617
  * @param id The id of the proof to verify.
545
- * @param proofObject The object to verify as JSON-LD.
618
+ * @param verify Validate the proof.
546
619
  * @returns The result of the verification and any failures.
547
620
  * @throws NotFoundError if the proof is not found.
548
621
  * @internal
549
622
  */
550
- async internalGet(id, proofObject) {
623
+ async internalGet(id, verify) {
551
624
  const urnParsed = Urn.fromValidString(id);
552
625
  const proofId = urnParsed.namespaceSpecific(0);
553
626
  const proofEntity = await this._proofStorage.get(proofId);
554
627
  if (Is.empty(proofEntity)) {
555
628
  throw new NotFoundError(this.CLASS_NAME, "proofNotFound", id);
556
629
  }
557
- let proofModel = await this.proofEntityToJsonLd(proofEntity);
630
+ let proofJsonLd = this.proofEntityToJsonLd(proofEntity);
558
631
  let verified = false;
559
632
  let failure = ImmutableProofFailure.NotIssued;
560
- if (Is.stringValue(proofEntity.immutableStorageId)) {
633
+ if (Is.stringValue(proofEntity.verifiableStorageId)) {
561
634
  failure = ImmutableProofFailure.ProofMissing;
562
- const immutableResult = await this._immutableStorage.get(proofEntity.immutableStorageId);
635
+ const immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);
563
636
  if (Is.uint8Array(immutableResult.data)) {
564
- proofModel = ObjectHelper.fromBytes(immutableResult.data);
565
- proofModel.immutableReceipt = immutableResult.receipt;
566
- // As we are adding the receipt to the data we update its context
567
- if (Is.array(proofModel["@context"])) {
568
- proofModel["@context"].push(ImmutableStorageTypes.ContextRoot);
637
+ proofJsonLd = ObjectHelper.fromBytes(immutableResult.data);
638
+ const unsecureDocument = ObjectHelper.clone(proofJsonLd);
639
+ proofJsonLd.immutableReceipt = immutableResult.receipt;
640
+ proofJsonLd.verifiableStorageId = proofEntity.verifiableStorageId;
641
+ // As we are adding the receipt to the data we update the JSON-LD context
642
+ const receiptContext = immutableResult.receipt["@context"];
643
+ if (!Is.empty(receiptContext)) {
644
+ proofJsonLd["@context"] = JsonLdProcessor.combineContexts(proofJsonLd["@context"], receiptContext);
569
645
  }
570
- if (Is.object(proofModel.proof) && Is.object(proofObject)) {
571
- if (proofModel.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
646
+ if (verify && Is.object(proofJsonLd.proof)) {
647
+ if (proofJsonLd.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
572
648
  failure = ImmutableProofFailure.CryptoSuiteMismatch;
573
649
  }
574
- else if (proofModel.proof.type !== DidTypes.DataIntegrityProof) {
650
+ else if (proofJsonLd.proof.type !== ProofTypes.DataIntegrityProof) {
575
651
  failure = ImmutableProofFailure.ProofTypeMismatch;
576
652
  }
577
653
  else {
578
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, proofModel);
579
- const isVerified = await this._identityConnector.verifyProof(hashData, proofModel.proof);
654
+ const isVerified = await this._identityConnector.verifyProof(unsecureDocument, proofJsonLd.proof);
580
655
  if (isVerified) {
581
656
  verified = true;
582
657
  failure = undefined;
@@ -589,102 +664,13 @@ class ImmutableProofService {
589
664
  }
590
665
  }
591
666
  return {
592
- immutableProof: proofModel,
667
+ immutableProof: proofJsonLd,
593
668
  verified,
594
669
  failure
595
670
  };
596
671
  }
597
- /**
598
- * Generate the hash data for the proof.
599
- * Conforms to https://www.w3.org/TR/vc-di-eddsa/#create-proof-eddsa-jcs-2022
600
- * @param nodeIdentity The node identity to use for vault operations.
601
- * @param immutableProof The immutable proof to generate the hash data for.
602
- * @returns The hash data.
603
- * @internal
604
- */
605
- async generateHashData(nodeIdentity, immutableProof) {
606
- // We hash the data for the proof without the the proof or immutable receipt for the proof
607
- // without these objects we can simplify the context
608
- const object = ObjectHelper.omit(immutableProof, ["proof", "immutableReceipt"]);
609
- object["@context"] = ImmutableProofTypes.ContextRoot;
610
- const canonicalDocument = JsonHelper.canonicalize(object);
611
- const proofKey = await this._vaultConnector.getKey(`${nodeIdentity}/${this._proofHashKeyId}`);
612
- const proofHash = Sha256.sum256(proofKey.privateKey);
613
- const transformedDocumentHash = Sha256.sum256(Converter.utf8ToBytes(canonicalDocument));
614
- const hashData = new Uint8Array(proofHash.length + transformedDocumentHash.length);
615
- hashData.set(proofHash);
616
- hashData.set(transformedDocumentHash, proofHash.length);
617
- return hashData;
618
- }
619
672
  }
620
673
 
621
- // Copyright 2024 IOTA Stiftung.
622
- // SPDX-License-Identifier: Apache-2.0.
623
- /**
624
- * Class describing the immutable proof.
625
- */
626
- let ImmutableProof = class ImmutableProof {
627
- /**
628
- * The id of the proof.
629
- */
630
- id;
631
- /**
632
- * The identity of the node which controls the proof.
633
- */
634
- nodeIdentity;
635
- /**
636
- * The identity of the user which created the proof.
637
- */
638
- userIdentity;
639
- /**
640
- * The date/time of when the proof was created.
641
- */
642
- dateCreated;
643
- /**
644
- * The associated id for the item.
645
- */
646
- proofObjectId;
647
- /**
648
- * The associated hash for the item.
649
- */
650
- proofObjectHash;
651
- /**
652
- * The immutable storage id.
653
- */
654
- immutableStorageId;
655
- };
656
- __decorate([
657
- property({ type: "string", isPrimary: true }),
658
- __metadata("design:type", String)
659
- ], ImmutableProof.prototype, "id", void 0);
660
- __decorate([
661
- property({ type: "string" }),
662
- __metadata("design:type", String)
663
- ], ImmutableProof.prototype, "nodeIdentity", void 0);
664
- __decorate([
665
- property({ type: "string" }),
666
- __metadata("design:type", String)
667
- ], ImmutableProof.prototype, "userIdentity", void 0);
668
- __decorate([
669
- property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
670
- __metadata("design:type", String)
671
- ], ImmutableProof.prototype, "dateCreated", void 0);
672
- __decorate([
673
- property({ type: "string" }),
674
- __metadata("design:type", String)
675
- ], ImmutableProof.prototype, "proofObjectId", void 0);
676
- __decorate([
677
- property({ type: "string" }),
678
- __metadata("design:type", String)
679
- ], ImmutableProof.prototype, "proofObjectHash", void 0);
680
- __decorate([
681
- property({ type: "string" }),
682
- __metadata("design:type", String)
683
- ], ImmutableProof.prototype, "immutableStorageId", void 0);
684
- ImmutableProof = __decorate([
685
- entity()
686
- ], ImmutableProof);
687
-
688
674
  const restEntryPoints = [
689
675
  {
690
676
  name: "immutable-proof",