@twin.org/immutable-proof-service 0.0.1-next.3 → 0.0.1-next.30
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 +201 -233
- package/dist/esm/index.mjs +205 -237
- package/dist/types/entities/immutableProof.d.ts +2 -2
- package/dist/types/immutableProofService.d.ts +12 -24
- package/dist/types/index.d.ts +2 -1
- package/dist/types/models/IImmutableProofServiceConfig.d.ts +3 -8
- package/dist/types/models/IImmutableProofServiceConstructorOptions.d.ts +34 -0
- package/docs/changelog.md +1 -1
- package/docs/open-api/spec.json +705 -732
- package/docs/reference/classes/ImmutableProof.md +3 -3
- package/docs/reference/classes/ImmutableProofService.md +35 -43
- 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 +4 -18
- package/docs/reference/interfaces/IImmutableProofServiceConstructorOptions.md +75 -0
- package/locales/en.json +1 -1
- package/package.json +10 -8
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,17 +1,83 @@
|
|
|
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');
|
|
6
7
|
var web = require('@twin.org/web');
|
|
8
|
+
var backgroundTaskModels = require('@twin.org/background-task-models');
|
|
7
9
|
var crypto = require('@twin.org/crypto');
|
|
8
10
|
var dataJsonLd = require('@twin.org/data-json-ld');
|
|
9
|
-
var dataSchemaOrg = require('@twin.org/data-schema-org');
|
|
10
|
-
var entity = require('@twin.org/entity');
|
|
11
11
|
var entityStorageModels = require('@twin.org/entity-storage-models');
|
|
12
12
|
var identityModels = require('@twin.org/identity-models');
|
|
13
|
-
var
|
|
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,74 +387,89 @@ class ImmutableProofService {
|
|
|
326
387
|
*/
|
|
327
388
|
_proofStorage;
|
|
328
389
|
/**
|
|
329
|
-
* The
|
|
390
|
+
* The verifiable storage for the credentials.
|
|
391
|
+
* @internal
|
|
392
|
+
*/
|
|
393
|
+
_verifiableStorage;
|
|
394
|
+
/**
|
|
395
|
+
* The background task connector.
|
|
330
396
|
* @internal
|
|
331
397
|
*/
|
|
332
|
-
|
|
398
|
+
_backgroundTaskConnector;
|
|
333
399
|
/**
|
|
334
|
-
* The
|
|
400
|
+
* The event bus component.
|
|
335
401
|
* @internal
|
|
336
402
|
*/
|
|
337
|
-
|
|
403
|
+
_eventBusComponent;
|
|
338
404
|
/**
|
|
339
|
-
* The
|
|
405
|
+
* The verification method id to use for the proofs.
|
|
340
406
|
* @internal
|
|
341
407
|
*/
|
|
342
|
-
|
|
408
|
+
_verificationMethodId;
|
|
343
409
|
/**
|
|
344
|
-
*
|
|
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
417
|
*/
|
|
357
418
|
constructor(options) {
|
|
358
|
-
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
|
|
359
419
|
this._proofStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.immutableProofEntityStorageType ?? core.StringHelper.kebabCase("ImmutableProof"));
|
|
360
|
-
this.
|
|
361
|
-
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);
|
|
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
|
+
}
|
|
362
427
|
this._config = options?.config ?? {};
|
|
363
|
-
this.
|
|
364
|
-
this.
|
|
365
|
-
|
|
366
|
-
|
|
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
|
+
});
|
|
367
432
|
}
|
|
368
433
|
/**
|
|
369
|
-
* Create a new
|
|
370
|
-
* @param
|
|
434
|
+
* Create a new proof.
|
|
435
|
+
* @param document The document to create the proof for.
|
|
371
436
|
* @param userIdentity The identity to create the immutable proof operation with.
|
|
372
437
|
* @param nodeIdentity The node identity to use for vault operations.
|
|
373
|
-
* @returns The id of the new
|
|
438
|
+
* @returns The id of the new proof.
|
|
374
439
|
*/
|
|
375
|
-
async create(
|
|
376
|
-
core.Guards.object(this.CLASS_NAME, "
|
|
440
|
+
async create(document, userIdentity, nodeIdentity) {
|
|
441
|
+
core.Guards.object(this.CLASS_NAME, "document", document);
|
|
377
442
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
378
443
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
379
444
|
try {
|
|
380
445
|
const validationFailures = [];
|
|
381
|
-
await dataJsonLd.JsonLdHelper.validate(
|
|
382
|
-
core.Validation.asValidationError(this.CLASS_NAME, "
|
|
446
|
+
await dataJsonLd.JsonLdHelper.validate(document, validationFailures);
|
|
447
|
+
core.Validation.asValidationError(this.CLASS_NAME, "document", validationFailures);
|
|
383
448
|
const id = core.Converter.bytesToHex(core.RandomHelper.generate(32), false);
|
|
384
449
|
const dateCreated = new Date(Date.now()).toISOString();
|
|
385
|
-
const proofObjectId = core.ObjectHelper.extractProperty(
|
|
386
|
-
|
|
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);
|
|
387
455
|
const proofEntity = {
|
|
388
456
|
id,
|
|
389
457
|
nodeIdentity,
|
|
390
458
|
userIdentity,
|
|
391
459
|
dateCreated,
|
|
392
460
|
proofObjectId,
|
|
393
|
-
proofObjectHash
|
|
461
|
+
proofObjectHash
|
|
394
462
|
};
|
|
395
463
|
await this._proofStorage.set(proofEntity);
|
|
396
|
-
this.
|
|
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);
|
|
397
473
|
return new core.Urn(ImmutableProofService.NAMESPACE, id).toString();
|
|
398
474
|
}
|
|
399
475
|
catch (error) {
|
|
@@ -401,7 +477,7 @@ class ImmutableProofService {
|
|
|
401
477
|
}
|
|
402
478
|
}
|
|
403
479
|
/**
|
|
404
|
-
* Get
|
|
480
|
+
* Get a proof.
|
|
405
481
|
* @param id The id of the proof to get.
|
|
406
482
|
* @returns The proof.
|
|
407
483
|
* @throws NotFoundError if the proof is not found.
|
|
@@ -416,22 +492,20 @@ class ImmutableProofService {
|
|
|
416
492
|
});
|
|
417
493
|
}
|
|
418
494
|
try {
|
|
419
|
-
const { immutableProof } = await this.internalGet(id);
|
|
420
|
-
|
|
421
|
-
return compacted;
|
|
495
|
+
const { immutableProof } = await this.internalGet(id, false);
|
|
496
|
+
return dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
|
|
422
497
|
}
|
|
423
498
|
catch (error) {
|
|
424
499
|
throw new core.GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
|
|
425
500
|
}
|
|
426
501
|
}
|
|
427
502
|
/**
|
|
428
|
-
* Verify
|
|
503
|
+
* Verify a proof.
|
|
429
504
|
* @param id The id of the proof to verify.
|
|
430
|
-
* @param proofObject The object to verify as JSON-LD.
|
|
431
505
|
* @returns The result of the verification and any failures.
|
|
432
506
|
* @throws NotFoundError if the proof is not found.
|
|
433
507
|
*/
|
|
434
|
-
async verify(id
|
|
508
|
+
async verify(id) {
|
|
435
509
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
436
510
|
const urnParsed = core.Urn.fromValidString(id);
|
|
437
511
|
if (urnParsed.namespaceIdentifier() !== ImmutableProofService.NAMESPACE) {
|
|
@@ -441,9 +515,9 @@ class ImmutableProofService {
|
|
|
441
515
|
});
|
|
442
516
|
}
|
|
443
517
|
try {
|
|
444
|
-
const { verified, failure } = await this.internalGet(id,
|
|
518
|
+
const { verified, failure } = await this.internalGet(id, true);
|
|
445
519
|
return {
|
|
446
|
-
"@context": immutableProofModels.
|
|
520
|
+
"@context": immutableProofModels.ImmutableProofContexts.ContextRoot,
|
|
447
521
|
type: immutableProofModels.ImmutableProofTypes.ImmutableProofVerification,
|
|
448
522
|
verified,
|
|
449
523
|
failure
|
|
@@ -454,13 +528,13 @@ class ImmutableProofService {
|
|
|
454
528
|
}
|
|
455
529
|
}
|
|
456
530
|
/**
|
|
457
|
-
* Remove the
|
|
531
|
+
* Remove the verifiable storage for the proof.
|
|
458
532
|
* @param id The id of the proof to remove the storage from.
|
|
459
533
|
* @param nodeIdentity The node identity to use for vault operations.
|
|
460
534
|
* @returns Nothing.
|
|
461
535
|
* @throws NotFoundError if the proof is not found.
|
|
462
536
|
*/
|
|
463
|
-
async
|
|
537
|
+
async removeVerifiable(id, nodeIdentity) {
|
|
464
538
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
465
539
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
466
540
|
const urnParsed = core.Urn.fromValidString(id);
|
|
@@ -476,14 +550,14 @@ class ImmutableProofService {
|
|
|
476
550
|
if (core.Is.empty(streamEntity)) {
|
|
477
551
|
throw new core.NotFoundError(this.CLASS_NAME, "proofNotFound", id);
|
|
478
552
|
}
|
|
479
|
-
if (core.Is.stringValue(streamEntity.
|
|
480
|
-
await this.
|
|
481
|
-
delete streamEntity.
|
|
553
|
+
if (core.Is.stringValue(streamEntity.verifiableStorageId)) {
|
|
554
|
+
await this._verifiableStorage.remove(nodeIdentity, streamEntity.verifiableStorageId);
|
|
555
|
+
delete streamEntity.verifiableStorageId;
|
|
482
556
|
await this._proofStorage.set(streamEntity);
|
|
483
557
|
}
|
|
484
558
|
}
|
|
485
559
|
catch (error) {
|
|
486
|
-
throw new core.GeneralError(this.CLASS_NAME, "
|
|
560
|
+
throw new core.GeneralError(this.CLASS_NAME, "removeVerifiableFailed", undefined, error);
|
|
487
561
|
}
|
|
488
562
|
}
|
|
489
563
|
/**
|
|
@@ -492,14 +566,8 @@ class ImmutableProofService {
|
|
|
492
566
|
* @returns The hash.
|
|
493
567
|
* @internal
|
|
494
568
|
*/
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
b2b.update(core.Converter.utf8ToBytes(id));
|
|
498
|
-
b2b.update(core.Converter.utf8ToBytes(dateCreated));
|
|
499
|
-
b2b.update(core.Converter.utf8ToBytes(nodeIdentity));
|
|
500
|
-
b2b.update(core.Converter.utf8ToBytes(userIdentity));
|
|
501
|
-
b2b.update(core.ObjectHelper.toBytes(proofObject));
|
|
502
|
-
return b2b.digest();
|
|
569
|
+
calculateDocumentHash(nodeObject) {
|
|
570
|
+
return `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(core.ObjectHelper.toBytes(core.JsonHelper.canonicalize(nodeObject))))}`;
|
|
503
571
|
}
|
|
504
572
|
/**
|
|
505
573
|
* Map the stream entity to a model.
|
|
@@ -507,99 +575,84 @@ class ImmutableProofService {
|
|
|
507
575
|
* @returns The model.
|
|
508
576
|
* @internal
|
|
509
577
|
*/
|
|
510
|
-
|
|
511
|
-
const
|
|
512
|
-
"@context": [
|
|
513
|
-
immutableProofModels.ImmutableProofTypes.ContextRoot,
|
|
514
|
-
dataSchemaOrg.SchemaOrgTypes.ContextRoot,
|
|
515
|
-
standardsW3cDid.DidContexts.ContextVCDataIntegrity
|
|
516
|
-
],
|
|
578
|
+
proofEntityToJsonLd(proofEntity) {
|
|
579
|
+
const jsonLd = {
|
|
580
|
+
"@context": [immutableProofModels.ImmutableProofContexts.ContextRoot, immutableProofModels.ImmutableProofContexts.ContextRootCommon],
|
|
517
581
|
type: immutableProofModels.ImmutableProofTypes.ImmutableProof,
|
|
518
582
|
id: proofEntity.id,
|
|
583
|
+
nodeIdentity: proofEntity.nodeIdentity,
|
|
519
584
|
userIdentity: proofEntity.userIdentity,
|
|
520
585
|
proofObjectId: proofEntity.proofObjectId,
|
|
521
|
-
proofObjectHash: proofEntity.proofObjectHash
|
|
586
|
+
proofObjectHash: proofEntity.proofObjectHash,
|
|
587
|
+
verifiableStorageId: proofEntity.verifiableStorageId
|
|
522
588
|
};
|
|
523
|
-
return
|
|
589
|
+
return jsonLd;
|
|
524
590
|
}
|
|
525
591
|
/**
|
|
526
|
-
*
|
|
527
|
-
* @
|
|
528
|
-
* @internal
|
|
529
|
-
*/
|
|
530
|
-
startProcessingProofs() {
|
|
531
|
-
if (!this._processing) {
|
|
532
|
-
setTimeout(async () => {
|
|
533
|
-
await this.processProofs();
|
|
534
|
-
}, 0);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Process the proofs.
|
|
592
|
+
* Process a proof.
|
|
593
|
+
* @param proofEntity The proof entity to process.
|
|
539
594
|
* @internal
|
|
540
595
|
*/
|
|
541
|
-
async
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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() });
|
|
552
613
|
}
|
|
553
|
-
], undefined, undefined, 2);
|
|
554
|
-
if (pendingProofs.entities.length > 0) {
|
|
555
|
-
const proofEntity = pendingProofs.entities[0];
|
|
556
|
-
const immutableProof = this.proofEntityToModel(proofEntity);
|
|
557
|
-
const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
|
|
558
|
-
immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
|
|
559
|
-
proofEntity.dateCreated = immutableProof.proof.created ?? new Date(Date.now()).toISOString();
|
|
560
|
-
const compacted = await dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
|
|
561
|
-
proofEntity.immutableStorageId = await this._immutableStorage.store(proofEntity.nodeIdentity, core.ObjectHelper.toBytes(compacted));
|
|
562
|
-
await this._proofStorage.set(proofEntity);
|
|
563
|
-
}
|
|
564
|
-
// If there are still remaining proofs, start the timer again
|
|
565
|
-
this._processing = false;
|
|
566
|
-
if (pendingProofs.entities.length > 1) {
|
|
567
|
-
this.startProcessingProofs();
|
|
568
614
|
}
|
|
569
615
|
}
|
|
570
616
|
/**
|
|
571
|
-
* Verify
|
|
617
|
+
* Verify a proof.
|
|
572
618
|
* @param id The id of the proof to verify.
|
|
573
|
-
* @param
|
|
619
|
+
* @param verify Validate the proof.
|
|
574
620
|
* @returns The result of the verification and any failures.
|
|
575
621
|
* @throws NotFoundError if the proof is not found.
|
|
576
622
|
* @internal
|
|
577
623
|
*/
|
|
578
|
-
async internalGet(id,
|
|
624
|
+
async internalGet(id, verify) {
|
|
579
625
|
const urnParsed = core.Urn.fromValidString(id);
|
|
580
626
|
const proofId = urnParsed.namespaceSpecific(0);
|
|
581
627
|
const proofEntity = await this._proofStorage.get(proofId);
|
|
582
628
|
if (core.Is.empty(proofEntity)) {
|
|
583
629
|
throw new core.NotFoundError(this.CLASS_NAME, "proofNotFound", id);
|
|
584
630
|
}
|
|
585
|
-
let
|
|
631
|
+
let proofJsonLd = this.proofEntityToJsonLd(proofEntity);
|
|
586
632
|
let verified = false;
|
|
587
633
|
let failure = immutableProofModels.ImmutableProofFailure.NotIssued;
|
|
588
|
-
if (core.Is.stringValue(proofEntity.
|
|
634
|
+
if (core.Is.stringValue(proofEntity.verifiableStorageId)) {
|
|
589
635
|
failure = immutableProofModels.ImmutableProofFailure.ProofMissing;
|
|
590
|
-
const
|
|
591
|
-
if (core.Is.uint8Array(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
636
|
+
const immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);
|
|
637
|
+
if (core.Is.uint8Array(immutableResult.data)) {
|
|
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);
|
|
646
|
+
}
|
|
647
|
+
if (verify && core.Is.object(proofJsonLd.proof)) {
|
|
648
|
+
if (proofJsonLd.proof.cryptosuite !== standardsW3cDid.DidCryptoSuites.EdDSAJcs2022) {
|
|
595
649
|
failure = immutableProofModels.ImmutableProofFailure.CryptoSuiteMismatch;
|
|
596
650
|
}
|
|
597
|
-
else if (
|
|
651
|
+
else if (proofJsonLd.proof.type !== standardsW3cDid.ProofTypes.DataIntegrityProof) {
|
|
598
652
|
failure = immutableProofModels.ImmutableProofFailure.ProofTypeMismatch;
|
|
599
653
|
}
|
|
600
654
|
else {
|
|
601
|
-
const
|
|
602
|
-
const isVerified = await this._identityConnector.verifyProof(hashData, proofModel.proof);
|
|
655
|
+
const isVerified = await this._identityConnector.verifyProof(unsecureDocument, proofJsonLd.proof);
|
|
603
656
|
if (isVerified) {
|
|
604
657
|
verified = true;
|
|
605
658
|
failure = undefined;
|
|
@@ -612,98 +665,13 @@ class ImmutableProofService {
|
|
|
612
665
|
}
|
|
613
666
|
}
|
|
614
667
|
return {
|
|
615
|
-
immutableProof:
|
|
668
|
+
immutableProof: proofJsonLd,
|
|
616
669
|
verified,
|
|
617
670
|
failure
|
|
618
671
|
};
|
|
619
672
|
}
|
|
620
|
-
/**
|
|
621
|
-
* Generate the hash data for the proof.
|
|
622
|
-
* Conforms to https://www.w3.org/TR/vc-di-eddsa/#create-proof-eddsa-jcs-2022
|
|
623
|
-
* @param nodeIdentity The node identity to use for vault operations.
|
|
624
|
-
* @param immutableProof The immutable proof to generate the hash data for.
|
|
625
|
-
* @returns The hash data.
|
|
626
|
-
* @internal
|
|
627
|
-
*/
|
|
628
|
-
async generateHashData(nodeIdentity, immutableProof) {
|
|
629
|
-
const canonicalDocument = core.JsonHelper.canonicalize(core.ObjectHelper.omit(immutableProof, ["proof"]));
|
|
630
|
-
const proofConfigKey = await this._vaultConnector.getKey(`${nodeIdentity}/${this._proofConfigKeyId}`);
|
|
631
|
-
const proofConfigHash = crypto.Sha256.sum256(proofConfigKey.privateKey);
|
|
632
|
-
const transformedDocumentHash = crypto.Sha256.sum256(core.Converter.utf8ToBytes(canonicalDocument));
|
|
633
|
-
const hashData = new Uint8Array(proofConfigHash.length + transformedDocumentHash.length);
|
|
634
|
-
hashData.set(proofConfigHash);
|
|
635
|
-
hashData.set(transformedDocumentHash, proofConfigHash.length);
|
|
636
|
-
return hashData;
|
|
637
|
-
}
|
|
638
673
|
}
|
|
639
674
|
|
|
640
|
-
// Copyright 2024 IOTA Stiftung.
|
|
641
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
642
|
-
/**
|
|
643
|
-
* Class describing the immutable proof.
|
|
644
|
-
*/
|
|
645
|
-
exports.ImmutableProof = class ImmutableProof {
|
|
646
|
-
/**
|
|
647
|
-
* The id of the proof.
|
|
648
|
-
*/
|
|
649
|
-
id;
|
|
650
|
-
/**
|
|
651
|
-
* The identity of the node which controls the proof.
|
|
652
|
-
*/
|
|
653
|
-
nodeIdentity;
|
|
654
|
-
/**
|
|
655
|
-
* The identity of the user which created the proof.
|
|
656
|
-
*/
|
|
657
|
-
userIdentity;
|
|
658
|
-
/**
|
|
659
|
-
* The date/time of when the proof was created.
|
|
660
|
-
*/
|
|
661
|
-
dateCreated;
|
|
662
|
-
/**
|
|
663
|
-
* The associated id for the item.
|
|
664
|
-
*/
|
|
665
|
-
proofObjectId;
|
|
666
|
-
/**
|
|
667
|
-
* The associated hash for the item.
|
|
668
|
-
*/
|
|
669
|
-
proofObjectHash;
|
|
670
|
-
/**
|
|
671
|
-
* The immutable storage id.
|
|
672
|
-
*/
|
|
673
|
-
immutableStorageId;
|
|
674
|
-
};
|
|
675
|
-
__decorate([
|
|
676
|
-
entity.property({ type: "string", isPrimary: true }),
|
|
677
|
-
__metadata("design:type", String)
|
|
678
|
-
], exports.ImmutableProof.prototype, "id", void 0);
|
|
679
|
-
__decorate([
|
|
680
|
-
entity.property({ type: "string" }),
|
|
681
|
-
__metadata("design:type", String)
|
|
682
|
-
], exports.ImmutableProof.prototype, "nodeIdentity", void 0);
|
|
683
|
-
__decorate([
|
|
684
|
-
entity.property({ type: "string" }),
|
|
685
|
-
__metadata("design:type", String)
|
|
686
|
-
], exports.ImmutableProof.prototype, "userIdentity", void 0);
|
|
687
|
-
__decorate([
|
|
688
|
-
entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
|
|
689
|
-
__metadata("design:type", String)
|
|
690
|
-
], exports.ImmutableProof.prototype, "dateCreated", void 0);
|
|
691
|
-
__decorate([
|
|
692
|
-
entity.property({ type: "string" }),
|
|
693
|
-
__metadata("design:type", String)
|
|
694
|
-
], exports.ImmutableProof.prototype, "proofObjectId", void 0);
|
|
695
|
-
__decorate([
|
|
696
|
-
entity.property({ type: "string" }),
|
|
697
|
-
__metadata("design:type", String)
|
|
698
|
-
], exports.ImmutableProof.prototype, "proofObjectHash", void 0);
|
|
699
|
-
__decorate([
|
|
700
|
-
entity.property({ type: "string" }),
|
|
701
|
-
__metadata("design:type", String)
|
|
702
|
-
], exports.ImmutableProof.prototype, "immutableStorageId", void 0);
|
|
703
|
-
exports.ImmutableProof = __decorate([
|
|
704
|
-
entity.entity()
|
|
705
|
-
], exports.ImmutableProof);
|
|
706
|
-
|
|
707
675
|
const restEntryPoints = [
|
|
708
676
|
{
|
|
709
677
|
name: "immutable-proof",
|