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