@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.
- package/dist/cjs/index.cjs +202 -216
- package/dist/esm/index.mjs +207 -221
- package/dist/types/entities/immutableProof.d.ts +2 -2
- package/dist/types/immutableProofService.d.ts +11 -29
- 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 +115 -1
- package/docs/open-api/spec.json +711 -732
- package/docs/reference/classes/ImmutableProof.md +6 -6
- package/docs/reference/classes/ImmutableProofService.md +38 -58
- 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 +8 -8
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
|
|
@@ -299,8 +365,9 @@ async function immutableProofVerify(httpRequestContext, componentName, request)
|
|
|
299
365
|
class ImmutableProofService {
|
|
300
366
|
/**
|
|
301
367
|
* The namespace for the service.
|
|
368
|
+
* @internal
|
|
302
369
|
*/
|
|
303
|
-
static
|
|
370
|
+
static _NAMESPACE = "immutable-proof";
|
|
304
371
|
/**
|
|
305
372
|
* Runtime name for the class.
|
|
306
373
|
*/
|
|
@@ -310,11 +377,6 @@ class ImmutableProofService {
|
|
|
310
377
|
* @internal
|
|
311
378
|
*/
|
|
312
379
|
_config;
|
|
313
|
-
/**
|
|
314
|
-
* The vault connector.
|
|
315
|
-
* @internal
|
|
316
|
-
*/
|
|
317
|
-
_vaultConnector;
|
|
318
380
|
/**
|
|
319
381
|
* The identity connector.
|
|
320
382
|
* @internal
|
|
@@ -326,83 +388,97 @@ class ImmutableProofService {
|
|
|
326
388
|
*/
|
|
327
389
|
_proofStorage;
|
|
328
390
|
/**
|
|
329
|
-
* The
|
|
391
|
+
* The verifiable storage for the credentials.
|
|
330
392
|
* @internal
|
|
331
393
|
*/
|
|
332
|
-
|
|
394
|
+
_verifiableStorage;
|
|
333
395
|
/**
|
|
334
396
|
* The background task connector.
|
|
335
397
|
* @internal
|
|
336
398
|
*/
|
|
337
399
|
_backgroundTaskConnector;
|
|
338
400
|
/**
|
|
339
|
-
* The
|
|
401
|
+
* The event bus component.
|
|
340
402
|
* @internal
|
|
341
403
|
*/
|
|
342
|
-
|
|
404
|
+
_eventBusComponent;
|
|
343
405
|
/**
|
|
344
|
-
* The
|
|
406
|
+
* The verification method id to use for the proofs.
|
|
345
407
|
* @internal
|
|
346
408
|
*/
|
|
347
|
-
|
|
409
|
+
_verificationMethodId;
|
|
410
|
+
/**
|
|
411
|
+
* The identity connector type.
|
|
412
|
+
* @internal
|
|
413
|
+
*/
|
|
414
|
+
_identityConnectorType;
|
|
348
415
|
/**
|
|
349
416
|
* Create a new instance of ImmutableProofService.
|
|
350
417
|
* @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
418
|
*/
|
|
358
419
|
constructor(options) {
|
|
359
|
-
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
|
|
360
420
|
this._proofStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.immutableProofEntityStorageType ?? core.StringHelper.kebabCase("ImmutableProof"));
|
|
361
|
-
this.
|
|
362
|
-
this.
|
|
421
|
+
this._verifiableStorage = verifiableStorageModels.VerifiableStorageConnectorFactory.get(options?.verifiableStorageType ?? "verifiable-storage");
|
|
422
|
+
this._identityConnectorType = options?.identityConnectorType ?? "identity";
|
|
423
|
+
this._identityConnector = identityModels.IdentityConnectorFactory.get(this._identityConnectorType);
|
|
363
424
|
this._backgroundTaskConnector = backgroundTaskModels.BackgroundTaskConnectorFactory.get(options?.backgroundTaskConnectorType ?? "background-task");
|
|
425
|
+
if (core.Is.stringValue(options?.eventBusComponentType)) {
|
|
426
|
+
this._eventBusComponent = core.ComponentFactory.get(options.eventBusComponentType);
|
|
427
|
+
}
|
|
364
428
|
this._config = options?.config ?? {};
|
|
365
|
-
this.
|
|
366
|
-
this.
|
|
367
|
-
|
|
429
|
+
this._verificationMethodId = this._config.verificationMethodId ?? "immutable-proof-assertion";
|
|
430
|
+
this._backgroundTaskConnector.registerHandler("immutable-proof", "@twin.org/immutable-proof-task", "processProofTask", async (task) => {
|
|
431
|
+
await this.finaliseTask(task);
|
|
432
|
+
});
|
|
368
433
|
}
|
|
369
434
|
/**
|
|
370
|
-
* Create a new
|
|
371
|
-
* @param
|
|
435
|
+
* Create a new proof.
|
|
436
|
+
* @param document The document to create the proof for.
|
|
372
437
|
* @param userIdentity The identity to create the immutable proof operation with.
|
|
373
438
|
* @param nodeIdentity The node identity to use for vault operations.
|
|
374
|
-
* @returns The id of the new
|
|
439
|
+
* @returns The id of the new proof.
|
|
375
440
|
*/
|
|
376
|
-
async create(
|
|
377
|
-
core.Guards.object(this.CLASS_NAME, "
|
|
441
|
+
async create(document, userIdentity, nodeIdentity) {
|
|
442
|
+
core.Guards.object(this.CLASS_NAME, "document", document);
|
|
378
443
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
379
444
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
380
445
|
try {
|
|
381
446
|
const validationFailures = [];
|
|
382
|
-
await dataJsonLd.JsonLdHelper.validate(
|
|
383
|
-
core.Validation.asValidationError(this.CLASS_NAME, "
|
|
447
|
+
await dataJsonLd.JsonLdHelper.validate(document, validationFailures);
|
|
448
|
+
core.Validation.asValidationError(this.CLASS_NAME, "document", validationFailures);
|
|
384
449
|
const id = core.Converter.bytesToHex(core.RandomHelper.generate(32), false);
|
|
385
450
|
const dateCreated = new Date(Date.now()).toISOString();
|
|
386
|
-
const proofObjectId = core.ObjectHelper.extractProperty(
|
|
387
|
-
|
|
451
|
+
const proofObjectId = core.ObjectHelper.extractProperty(document, ["@id", "id"], false);
|
|
452
|
+
// We don't want to store the whole document in the immutable proof, as this could be large
|
|
453
|
+
// and also reveal information that should not be stored in the proof so we hash the document
|
|
454
|
+
// and store the hash
|
|
455
|
+
const proofObjectHash = this.calculateDocumentHash(document);
|
|
388
456
|
const proofEntity = {
|
|
389
457
|
id,
|
|
390
458
|
nodeIdentity,
|
|
391
459
|
userIdentity,
|
|
392
460
|
dateCreated,
|
|
393
461
|
proofObjectId,
|
|
394
|
-
proofObjectHash
|
|
462
|
+
proofObjectHash
|
|
395
463
|
};
|
|
396
464
|
await this._proofStorage.set(proofEntity);
|
|
397
|
-
|
|
398
|
-
|
|
465
|
+
const immutableProof = this.proofEntityToJsonLd(proofEntity);
|
|
466
|
+
const proofTaskPayload = {
|
|
467
|
+
proofId: id,
|
|
468
|
+
nodeIdentity,
|
|
469
|
+
identityConnectorType: this._identityConnectorType,
|
|
470
|
+
verificationMethodId: this._verificationMethodId,
|
|
471
|
+
document: immutableProof
|
|
472
|
+
};
|
|
473
|
+
await this._backgroundTaskConnector.create("immutable-proof", proofTaskPayload);
|
|
474
|
+
return new core.Urn(ImmutableProofService._NAMESPACE, id).toString();
|
|
399
475
|
}
|
|
400
476
|
catch (error) {
|
|
401
477
|
throw new core.GeneralError(this.CLASS_NAME, "createFailed", undefined, error);
|
|
402
478
|
}
|
|
403
479
|
}
|
|
404
480
|
/**
|
|
405
|
-
* Get
|
|
481
|
+
* Get a proof.
|
|
406
482
|
* @param id The id of the proof to get.
|
|
407
483
|
* @returns The proof.
|
|
408
484
|
* @throws NotFoundError if the proof is not found.
|
|
@@ -410,41 +486,39 @@ class ImmutableProofService {
|
|
|
410
486
|
async get(id) {
|
|
411
487
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
412
488
|
const urnParsed = core.Urn.fromValidString(id);
|
|
413
|
-
if (urnParsed.namespaceIdentifier() !== ImmutableProofService.
|
|
489
|
+
if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
|
|
414
490
|
throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
415
|
-
namespace: ImmutableProofService.
|
|
491
|
+
namespace: ImmutableProofService._NAMESPACE,
|
|
416
492
|
id
|
|
417
493
|
});
|
|
418
494
|
}
|
|
419
495
|
try {
|
|
420
|
-
const { immutableProof } = await this.internalGet(id);
|
|
421
|
-
|
|
422
|
-
return compacted;
|
|
496
|
+
const { immutableProof } = await this.internalGet(id, false);
|
|
497
|
+
return dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
|
|
423
498
|
}
|
|
424
499
|
catch (error) {
|
|
425
500
|
throw new core.GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
|
|
426
501
|
}
|
|
427
502
|
}
|
|
428
503
|
/**
|
|
429
|
-
* Verify
|
|
504
|
+
* Verify a proof.
|
|
430
505
|
* @param id The id of the proof to verify.
|
|
431
|
-
* @param proofObject The object to verify as JSON-LD.
|
|
432
506
|
* @returns The result of the verification and any failures.
|
|
433
507
|
* @throws NotFoundError if the proof is not found.
|
|
434
508
|
*/
|
|
435
|
-
async verify(id
|
|
509
|
+
async verify(id) {
|
|
436
510
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
437
511
|
const urnParsed = core.Urn.fromValidString(id);
|
|
438
|
-
if (urnParsed.namespaceIdentifier() !== ImmutableProofService.
|
|
512
|
+
if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
|
|
439
513
|
throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
440
|
-
namespace: ImmutableProofService.
|
|
514
|
+
namespace: ImmutableProofService._NAMESPACE,
|
|
441
515
|
id
|
|
442
516
|
});
|
|
443
517
|
}
|
|
444
518
|
try {
|
|
445
|
-
const { verified, failure } = await this.internalGet(id,
|
|
519
|
+
const { verified, failure } = await this.internalGet(id, true);
|
|
446
520
|
return {
|
|
447
|
-
"@context": immutableProofModels.
|
|
521
|
+
"@context": immutableProofModels.ImmutableProofContexts.ContextRoot,
|
|
448
522
|
type: immutableProofModels.ImmutableProofTypes.ImmutableProofVerification,
|
|
449
523
|
verified,
|
|
450
524
|
failure
|
|
@@ -455,19 +529,19 @@ class ImmutableProofService {
|
|
|
455
529
|
}
|
|
456
530
|
}
|
|
457
531
|
/**
|
|
458
|
-
* Remove the
|
|
532
|
+
* Remove the verifiable storage for the proof.
|
|
459
533
|
* @param id The id of the proof to remove the storage from.
|
|
460
534
|
* @param nodeIdentity The node identity to use for vault operations.
|
|
461
535
|
* @returns Nothing.
|
|
462
536
|
* @throws NotFoundError if the proof is not found.
|
|
463
537
|
*/
|
|
464
|
-
async
|
|
538
|
+
async removeVerifiable(id, nodeIdentity) {
|
|
465
539
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
466
540
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
467
541
|
const urnParsed = core.Urn.fromValidString(id);
|
|
468
|
-
if (urnParsed.namespaceIdentifier() !== ImmutableProofService.
|
|
542
|
+
if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
|
|
469
543
|
throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
470
|
-
namespace: ImmutableProofService.
|
|
544
|
+
namespace: ImmutableProofService._NAMESPACE,
|
|
471
545
|
id
|
|
472
546
|
});
|
|
473
547
|
}
|
|
@@ -477,14 +551,14 @@ class ImmutableProofService {
|
|
|
477
551
|
if (core.Is.empty(streamEntity)) {
|
|
478
552
|
throw new core.NotFoundError(this.CLASS_NAME, "proofNotFound", id);
|
|
479
553
|
}
|
|
480
|
-
if (core.Is.stringValue(streamEntity.
|
|
481
|
-
await this.
|
|
482
|
-
delete streamEntity.
|
|
554
|
+
if (core.Is.stringValue(streamEntity.verifiableStorageId)) {
|
|
555
|
+
await this._verifiableStorage.remove(nodeIdentity, streamEntity.verifiableStorageId);
|
|
556
|
+
delete streamEntity.verifiableStorageId;
|
|
483
557
|
await this._proofStorage.set(streamEntity);
|
|
484
558
|
}
|
|
485
559
|
}
|
|
486
560
|
catch (error) {
|
|
487
|
-
throw new core.GeneralError(this.CLASS_NAME, "
|
|
561
|
+
throw new core.GeneralError(this.CLASS_NAME, "removeVerifiableFailed", undefined, error);
|
|
488
562
|
}
|
|
489
563
|
}
|
|
490
564
|
/**
|
|
@@ -493,14 +567,8 @@ class ImmutableProofService {
|
|
|
493
567
|
* @returns The hash.
|
|
494
568
|
* @internal
|
|
495
569
|
*/
|
|
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();
|
|
570
|
+
calculateDocumentHash(nodeObject) {
|
|
571
|
+
return `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(core.ObjectHelper.toBytes(core.JsonHelper.canonicalize(nodeObject))))}`;
|
|
504
572
|
}
|
|
505
573
|
/**
|
|
506
574
|
* Map the stream entity to a model.
|
|
@@ -509,76 +577,83 @@ class ImmutableProofService {
|
|
|
509
577
|
* @internal
|
|
510
578
|
*/
|
|
511
579
|
proofEntityToJsonLd(proofEntity) {
|
|
512
|
-
const
|
|
513
|
-
"@context": immutableProofModels.
|
|
580
|
+
const jsonLd = {
|
|
581
|
+
"@context": [immutableProofModels.ImmutableProofContexts.ContextRoot, immutableProofModels.ImmutableProofContexts.ContextRootCommon],
|
|
514
582
|
type: immutableProofModels.ImmutableProofTypes.ImmutableProof,
|
|
515
583
|
id: proofEntity.id,
|
|
584
|
+
nodeIdentity: proofEntity.nodeIdentity,
|
|
516
585
|
userIdentity: proofEntity.userIdentity,
|
|
517
586
|
proofObjectId: proofEntity.proofObjectId,
|
|
518
|
-
proofObjectHash: proofEntity.proofObjectHash
|
|
587
|
+
proofObjectHash: proofEntity.proofObjectHash,
|
|
588
|
+
verifiableStorageId: proofEntity.verifiableStorageId
|
|
519
589
|
};
|
|
520
|
-
return
|
|
590
|
+
return jsonLd;
|
|
521
591
|
}
|
|
522
592
|
/**
|
|
523
593
|
* Process a proof.
|
|
524
594
|
* @param proofEntity The proof entity to process.
|
|
525
595
|
* @internal
|
|
526
596
|
*/
|
|
527
|
-
async
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
597
|
+
async finaliseTask(task) {
|
|
598
|
+
if (task.status === backgroundTaskModels.TaskStatus.Success && core.Is.object(task.payload) && core.Is.object(task.result)) {
|
|
599
|
+
const proofEntity = await this._proofStorage.get(task.payload.proofId);
|
|
600
|
+
if (core.Is.object(proofEntity)) {
|
|
601
|
+
const immutableProof = this.proofEntityToJsonLd(proofEntity);
|
|
602
|
+
// As we are adding the proof to the data we update its context
|
|
603
|
+
immutableProof["@context"] = dataJsonLd.JsonLdProcessor.combineContexts([immutableProofModels.ImmutableProofContexts.ContextRoot, immutableProofModels.ImmutableProofContexts.ContextRootCommon], task.result.proof["@context"]);
|
|
604
|
+
immutableProof.proof = task.result.proof;
|
|
605
|
+
core.ObjectHelper.propertyDelete(immutableProof.proof, "@context");
|
|
606
|
+
if (core.Is.stringValue(immutableProof.proof.created)) {
|
|
607
|
+
proofEntity.dateCreated = immutableProof.proof.created;
|
|
608
|
+
}
|
|
609
|
+
const compacted = await dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
|
|
610
|
+
const verifiableCreateResult = await this._verifiableStorage.create(proofEntity.nodeIdentity, core.ObjectHelper.toBytes(compacted));
|
|
611
|
+
proofEntity.verifiableStorageId = verifiableCreateResult.id;
|
|
612
|
+
await this._proofStorage.set(proofEntity);
|
|
613
|
+
await this._eventBusComponent?.publish(immutableProofModels.ImmutableProofTopics.ProofCreated, { id: new core.Urn(ImmutableProofService._NAMESPACE, task.payload.proofId).toString() });
|
|
614
|
+
}
|
|
538
615
|
}
|
|
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
616
|
}
|
|
544
617
|
/**
|
|
545
|
-
* Verify
|
|
618
|
+
* Verify a proof.
|
|
546
619
|
* @param id The id of the proof to verify.
|
|
547
|
-
* @param
|
|
620
|
+
* @param verify Validate the proof.
|
|
548
621
|
* @returns The result of the verification and any failures.
|
|
549
622
|
* @throws NotFoundError if the proof is not found.
|
|
550
623
|
* @internal
|
|
551
624
|
*/
|
|
552
|
-
async internalGet(id,
|
|
625
|
+
async internalGet(id, verify) {
|
|
553
626
|
const urnParsed = core.Urn.fromValidString(id);
|
|
554
627
|
const proofId = urnParsed.namespaceSpecific(0);
|
|
555
628
|
const proofEntity = await this._proofStorage.get(proofId);
|
|
556
629
|
if (core.Is.empty(proofEntity)) {
|
|
557
630
|
throw new core.NotFoundError(this.CLASS_NAME, "proofNotFound", id);
|
|
558
631
|
}
|
|
559
|
-
let
|
|
632
|
+
let proofJsonLd = this.proofEntityToJsonLd(proofEntity);
|
|
560
633
|
let verified = false;
|
|
561
634
|
let failure = immutableProofModels.ImmutableProofFailure.NotIssued;
|
|
562
|
-
if (core.Is.stringValue(proofEntity.
|
|
635
|
+
if (core.Is.stringValue(proofEntity.verifiableStorageId)) {
|
|
563
636
|
failure = immutableProofModels.ImmutableProofFailure.ProofMissing;
|
|
564
|
-
const immutableResult = await this.
|
|
637
|
+
const immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);
|
|
565
638
|
if (core.Is.uint8Array(immutableResult.data)) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
639
|
+
proofJsonLd = core.ObjectHelper.fromBytes(immutableResult.data);
|
|
640
|
+
const unsecureDocument = core.ObjectHelper.clone(proofJsonLd);
|
|
641
|
+
proofJsonLd.immutableReceipt = immutableResult.receipt;
|
|
642
|
+
proofJsonLd.verifiableStorageId = proofEntity.verifiableStorageId;
|
|
643
|
+
// As we are adding the receipt to the data we update the JSON-LD context
|
|
644
|
+
const receiptContext = immutableResult.receipt["@context"];
|
|
645
|
+
if (!core.Is.empty(receiptContext)) {
|
|
646
|
+
proofJsonLd["@context"] = dataJsonLd.JsonLdProcessor.combineContexts(proofJsonLd["@context"], receiptContext);
|
|
571
647
|
}
|
|
572
|
-
if (
|
|
573
|
-
if (
|
|
648
|
+
if (verify && core.Is.object(proofJsonLd.proof)) {
|
|
649
|
+
if (proofJsonLd.proof.cryptosuite !== standardsW3cDid.DidCryptoSuites.EdDSAJcs2022) {
|
|
574
650
|
failure = immutableProofModels.ImmutableProofFailure.CryptoSuiteMismatch;
|
|
575
651
|
}
|
|
576
|
-
else if (
|
|
652
|
+
else if (proofJsonLd.proof.type !== standardsW3cDid.ProofTypes.DataIntegrityProof) {
|
|
577
653
|
failure = immutableProofModels.ImmutableProofFailure.ProofTypeMismatch;
|
|
578
654
|
}
|
|
579
655
|
else {
|
|
580
|
-
const
|
|
581
|
-
const isVerified = await this._identityConnector.verifyProof(hashData, proofModel.proof);
|
|
656
|
+
const isVerified = await this._identityConnector.verifyProof(unsecureDocument, proofJsonLd.proof);
|
|
582
657
|
if (isVerified) {
|
|
583
658
|
verified = true;
|
|
584
659
|
failure = undefined;
|
|
@@ -591,102 +666,13 @@ class ImmutableProofService {
|
|
|
591
666
|
}
|
|
592
667
|
}
|
|
593
668
|
return {
|
|
594
|
-
immutableProof:
|
|
669
|
+
immutableProof: proofJsonLd,
|
|
595
670
|
verified,
|
|
596
671
|
failure
|
|
597
672
|
};
|
|
598
673
|
}
|
|
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
674
|
}
|
|
622
675
|
|
|
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
676
|
const restEntryPoints = [
|
|
691
677
|
{
|
|
692
678
|
name: "immutable-proof",
|