@0xpolygonid/js-sdk 1.9.2 → 1.9.4
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/browser/esm/index.js +2989 -1220
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +2956 -1176
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/circuits/comparer.js +6 -1
- package/dist/node/cjs/kms/key-providers/ed25519-provider.js +96 -0
- package/dist/node/cjs/kms/key-providers/index.js +1 -0
- package/dist/node/cjs/kms/store/types.js +1 -0
- package/dist/node/cjs/proof/provers/inputs-generator.js +16 -1
- package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +96 -3
- package/dist/node/cjs/proof/verifiers/query.js +90 -75
- package/dist/node/esm/circuits/comparer.js +4 -0
- package/dist/node/esm/kms/key-providers/ed25519-provider.js +69 -0
- package/dist/node/esm/kms/key-providers/index.js +1 -0
- package/dist/node/esm/kms/store/types.js +1 -0
- package/dist/node/esm/proof/provers/inputs-generator.js +17 -2
- package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +98 -5
- package/dist/node/esm/proof/verifiers/query.js +82 -76
- package/dist/types/circuits/comparer.d.ts +1 -0
- package/dist/types/kms/key-providers/ed25519-provider.d.ts +44 -0
- package/dist/types/kms/key-providers/index.d.ts +1 -0
- package/dist/types/kms/store/types.d.ts +2 -1
- package/dist/types/proof/provers/inputs-generator.d.ts +1 -0
- package/dist/types/proof/verifiers/pub-signals-verifier.d.ts +1 -0
- package/dist/types/proof/verifiers/query.d.ts +13 -1
- package/package.json +5 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Represents the XSD namespace and its corresponding data types.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.factoryComparer = exports.Vector = exports.Scalar = exports.isValidOperation = exports.availableTypesOperators = exports.QueryOperators = exports.Operators = exports.XSDNS = void 0;
|
|
6
|
+
exports.factoryComparer = exports.Vector = exports.Scalar = exports.isValidOperation = exports.availableTypesOperators = exports.getOperatorNameByValue = exports.QueryOperators = exports.Operators = exports.XSDNS = void 0;
|
|
7
7
|
var XSDNS;
|
|
8
8
|
(function (XSDNS) {
|
|
9
9
|
XSDNS["Boolean"] = "http://www.w3.org/2001/XMLSchema#boolean";
|
|
@@ -55,6 +55,11 @@ exports.QueryOperators = {
|
|
|
55
55
|
$sd: Operators.SD,
|
|
56
56
|
$nullify: Operators.NULLIFY
|
|
57
57
|
};
|
|
58
|
+
const getOperatorNameByValue = (operator) => {
|
|
59
|
+
const ops = Object.entries(exports.QueryOperators).find(([, queryOp]) => queryOp === operator);
|
|
60
|
+
return ops ? ops[0] : 'unknown';
|
|
61
|
+
};
|
|
62
|
+
exports.getOperatorNameByValue = getOperatorNameByValue;
|
|
58
63
|
const allOperations = Object.values(exports.QueryOperators);
|
|
59
64
|
exports.availableTypesOperators = new Map([
|
|
60
65
|
[
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Ed25519Provider = void 0;
|
|
27
|
+
const providerHelpers = __importStar(require("../provider-helpers"));
|
|
28
|
+
const ed25519_1 = require("@noble/curves/ed25519");
|
|
29
|
+
const utils_1 = require("../../utils");
|
|
30
|
+
/**
|
|
31
|
+
* Provider for Ed25519 keys
|
|
32
|
+
* @public
|
|
33
|
+
* @class Ed25519Provider
|
|
34
|
+
* @implements IKeyProvider interface
|
|
35
|
+
*/
|
|
36
|
+
class Ed25519Provider {
|
|
37
|
+
/**
|
|
38
|
+
* Creates an instance of Ed25519Provider.
|
|
39
|
+
* @param {KmsKeyType} keyType - kms key type
|
|
40
|
+
* @param {AbstractPrivateKeyStore} keyStore - key store for kms
|
|
41
|
+
*/
|
|
42
|
+
constructor(keyType, _keyStore) {
|
|
43
|
+
this.keyType = keyType;
|
|
44
|
+
this._keyStore = _keyStore;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* generates a ed25519 key from a seed phrase
|
|
48
|
+
* @param {Uint8Array} seed - byte array seed
|
|
49
|
+
* @returns {Promise<KmsKeyId>} kms key identifier
|
|
50
|
+
*/
|
|
51
|
+
async newPrivateKeyFromSeed(seed) {
|
|
52
|
+
if (seed.length !== 32) {
|
|
53
|
+
throw new Error('Seed should be 32 bytes');
|
|
54
|
+
}
|
|
55
|
+
const publicKey = ed25519_1.ed25519.getPublicKey(seed);
|
|
56
|
+
const kmsId = {
|
|
57
|
+
type: this.keyType,
|
|
58
|
+
id: providerHelpers.keyPath(this.keyType, (0, utils_1.bytesToHex)(publicKey))
|
|
59
|
+
};
|
|
60
|
+
await this._keyStore.importKey({
|
|
61
|
+
alias: kmsId.id,
|
|
62
|
+
key: (0, utils_1.bytesToHex)(seed)
|
|
63
|
+
});
|
|
64
|
+
return kmsId;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets public key by kmsKeyId
|
|
68
|
+
* @param {KmsKeyId} keyId - key identifier
|
|
69
|
+
* @returns {Promise<string>} Public key as a hex string
|
|
70
|
+
*/
|
|
71
|
+
async publicKey(keyId) {
|
|
72
|
+
const privateKeyHex = await this.privateKey(keyId);
|
|
73
|
+
const publicKey = ed25519_1.ed25519.getPublicKey(privateKeyHex);
|
|
74
|
+
return (0, utils_1.bytesToHex)(publicKey);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* signs prepared payload of size,
|
|
78
|
+
* with a key id
|
|
79
|
+
* @param {KmsKeyId} keyId - key identifier
|
|
80
|
+
* @param {Uint8Array} data - data to sign (32 bytes)
|
|
81
|
+
* @returns {Promise<Uint8Array>} signature
|
|
82
|
+
*/
|
|
83
|
+
async sign(keyId, data) {
|
|
84
|
+
const privateKeyHex = await this.privateKey(keyId);
|
|
85
|
+
return ed25519_1.ed25519.sign(data, privateKeyHex);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves the private key for a given keyId from the key store.
|
|
89
|
+
* @param {KmsKeyId} keyId - The identifier of the key to retrieve.
|
|
90
|
+
* @returns {Promise<string>} The private key associated with the keyId.
|
|
91
|
+
*/
|
|
92
|
+
async privateKey(keyId) {
|
|
93
|
+
return this._keyStore.get({ alias: keyId.id });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.Ed25519Provider = Ed25519Provider;
|
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./bjj-provider"), exports);
|
|
18
|
+
__exportStar(require("./ed25519-provider"), exports);
|
|
18
19
|
__exportStar(require("./sec256k1-provider"), exports);
|
|
@@ -51,6 +51,7 @@ class InputGenerator {
|
|
|
51
51
|
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
52
52
|
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
53
53
|
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
54
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
54
55
|
return circuitInputs.inputsMarshal();
|
|
55
56
|
};
|
|
56
57
|
this.credentialAtomicQueryMTPV2OnChainPrepareInputs = async ({ preparedCredential, identifier, proofReq, params, circuitQueries }) => {
|
|
@@ -98,6 +99,7 @@ class InputGenerator {
|
|
|
98
99
|
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
99
100
|
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
100
101
|
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
102
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
101
103
|
return circuitInputs.inputsMarshal();
|
|
102
104
|
};
|
|
103
105
|
this.credentialAtomicQuerySigV2PrepareInputs = async ({ preparedCredential, identifier, proofReq, params, circuitQueries }) => {
|
|
@@ -119,6 +121,7 @@ class InputGenerator {
|
|
|
119
121
|
query.operator = this.transformV2QueryOperator(query.operator);
|
|
120
122
|
circuitInputs.query = query;
|
|
121
123
|
circuitInputs.currentTimeStamp = (0, js_iden3_core_1.getUnixTimestamp)(new Date());
|
|
124
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
122
125
|
return circuitInputs.inputsMarshal();
|
|
123
126
|
};
|
|
124
127
|
this.credentialAtomicQuerySigV2OnChainPrepareInputs = async ({ preparedCredential, identifier, proofReq, params, circuitQueries }) => {
|
|
@@ -166,6 +169,7 @@ class InputGenerator {
|
|
|
166
169
|
const signature = await this._identityWallet.signChallenge(params.challenge, authInfo.credential);
|
|
167
170
|
circuitInputs.signature = signature;
|
|
168
171
|
circuitInputs.challenge = params.challenge;
|
|
172
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
169
173
|
return circuitInputs.inputsMarshal();
|
|
170
174
|
};
|
|
171
175
|
this.credentialAtomicQueryV3PrepareInputs = async ({ preparedCredential, identifier, proofReq, params, circuitQueries }) => {
|
|
@@ -215,6 +219,7 @@ class InputGenerator {
|
|
|
215
219
|
circuitInputs.nullifierSessionID = proofReq.params?.nullifierSessionId
|
|
216
220
|
? BigInt(proofReq.params?.nullifierSessionId?.toString())
|
|
217
221
|
: BigInt(0);
|
|
222
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
218
223
|
return circuitInputs.inputsMarshal();
|
|
219
224
|
};
|
|
220
225
|
this.credentialAtomicQueryV3OnChainPrepareInputs = async ({ preparedCredential, identifier, proofReq, params, circuitQueries }) => {
|
|
@@ -293,15 +298,19 @@ class InputGenerator {
|
|
|
293
298
|
circuitInputs.treeState = authClaimData.treeState;
|
|
294
299
|
circuitInputs.signature = signature;
|
|
295
300
|
}
|
|
301
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
296
302
|
return circuitInputs.inputsMarshal();
|
|
297
303
|
};
|
|
298
|
-
this.linkedMultiQuery10PrepareInputs = async ({ preparedCredential, params, circuitQueries }) => {
|
|
304
|
+
this.linkedMultiQuery10PrepareInputs = async ({ preparedCredential, params, proofReq, circuitQueries }) => {
|
|
299
305
|
const circuitClaimData = await this.newCircuitClaimData(preparedCredential);
|
|
300
306
|
circuitClaimData.nonRevProof = (0, common_1.toClaimNonRevStatus)(preparedCredential.revStatus);
|
|
301
307
|
const circuitInputs = new circuits_1.LinkedMultiQueryInputs();
|
|
302
308
|
circuitInputs.linkNonce = params.linkNonce ?? BigInt(0);
|
|
303
309
|
circuitInputs.claim = circuitClaimData.claim;
|
|
304
310
|
circuitInputs.query = circuitQueries;
|
|
311
|
+
circuitQueries.forEach((query) => {
|
|
312
|
+
this.checkOperatorSupport(proofReq.circuitId, query.operator);
|
|
313
|
+
});
|
|
305
314
|
return circuitInputs.inputsMarshal();
|
|
306
315
|
};
|
|
307
316
|
}
|
|
@@ -386,5 +395,11 @@ class InputGenerator {
|
|
|
386
395
|
transformV2QueryOperator(operator) {
|
|
387
396
|
return operator === circuits_1.Operators.SD || operator === circuits_1.Operators.NOOP ? circuits_1.Operators.EQ : operator;
|
|
388
397
|
}
|
|
398
|
+
checkOperatorSupport(circuitId, operator) {
|
|
399
|
+
const supportedOperators = exports.circuitValidator[circuitId].supportedOperations;
|
|
400
|
+
if (!supportedOperators.includes(operator)) {
|
|
401
|
+
throw new Error(`operator ${(0, circuits_1.getOperatorNameByValue)(operator)} is not supported by ${circuitId}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
389
404
|
}
|
|
390
405
|
exports.InputGenerator = InputGenerator;
|
|
@@ -59,7 +59,7 @@ class PubSignalsVerifier {
|
|
|
59
59
|
valueArraySize: mtpv2PubSignals.getValueArrSize(),
|
|
60
60
|
isRevocationChecked: mtpv2PubSignals.isRevocationChecked
|
|
61
61
|
};
|
|
62
|
-
await
|
|
62
|
+
await this.checkQueryV2Circuits(models_1.CircuitId.AtomicQueryMTPV2, query, outs, opts, verifiablePresentation);
|
|
63
63
|
// verify state
|
|
64
64
|
await this.checkStateExistenceForId(mtpv2PubSignals.issuerID, mtpv2PubSignals.issuerClaimIdenState);
|
|
65
65
|
if (mtpv2PubSignals.isRevocationChecked !== 0) {
|
|
@@ -88,7 +88,7 @@ class PubSignalsVerifier {
|
|
|
88
88
|
valueArraySize: sigV2PubSignals.getValueArrSize(),
|
|
89
89
|
isRevocationChecked: sigV2PubSignals.isRevocationChecked
|
|
90
90
|
};
|
|
91
|
-
await
|
|
91
|
+
await this.checkQueryV2Circuits(models_1.CircuitId.AtomicQuerySigV2, query, outs, opts, verifiablePresentation);
|
|
92
92
|
// verify state
|
|
93
93
|
await this.checkStateExistenceForId(sigV2PubSignals.issuerID, sigV2PubSignals.issuerAuthState);
|
|
94
94
|
if (sigV2PubSignals.isRevocationChecked !== 0) {
|
|
@@ -114,9 +114,55 @@ class PubSignalsVerifier {
|
|
|
114
114
|
merklized: v3PubSignals.merklized,
|
|
115
115
|
claimPathKey: v3PubSignals.claimPathKey,
|
|
116
116
|
valueArraySize: v3PubSignals.getValueArrSize(),
|
|
117
|
+
operatorOutput: v3PubSignals.operatorOutput,
|
|
117
118
|
isRevocationChecked: v3PubSignals.isRevocationChecked
|
|
118
119
|
};
|
|
119
|
-
|
|
120
|
+
if (!query.type) {
|
|
121
|
+
throw new Error(`proof query type is undefined`);
|
|
122
|
+
}
|
|
123
|
+
const loader = this._documentLoader ?? (0, js_jsonld_merklization_1.getDocumentLoader)();
|
|
124
|
+
// validate schema
|
|
125
|
+
let context;
|
|
126
|
+
try {
|
|
127
|
+
context = (await loader(query.context ?? '')).document;
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
throw new Error(`can't load schema for request query`);
|
|
131
|
+
}
|
|
132
|
+
const queriesMetadata = await (0, common_2.parseQueriesMetadata)(query.type, JSON.stringify(context), query.credentialSubject, {
|
|
133
|
+
documentLoader: loader
|
|
134
|
+
});
|
|
135
|
+
const circuitId = models_1.CircuitId.AtomicQueryV3;
|
|
136
|
+
await (0, query_1.checkQueryRequest)(query, queriesMetadata, context, outs, circuitId, this._documentLoader, opts);
|
|
137
|
+
const queryMetadata = queriesMetadata[0]; // only one query is supported
|
|
138
|
+
(0, query_1.checkCircuitOperator)(circuitId, outs.operator);
|
|
139
|
+
// validate selective disclosure
|
|
140
|
+
if (queryMetadata.operator === circuits_1.Operators.SD) {
|
|
141
|
+
try {
|
|
142
|
+
await (0, query_1.validateDisclosureNativeSDSupport)(queryMetadata, outs, verifiablePresentation, loader);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
throw new Error(`failed to validate selective disclosure: ${e.message}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (!queryMetadata.fieldName && queryMetadata.operator == circuits_1.Operators.NOOP) {
|
|
149
|
+
try {
|
|
150
|
+
await (0, query_1.validateEmptyCredentialSubjectNoopNativeSupport)(outs);
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
try {
|
|
158
|
+
await (0, query_1.validateOperators)(queryMetadata, outs);
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// verify field inclusion / non-inclusion
|
|
165
|
+
(0, query_1.verifyFieldValueInclusionNativeExistsSupport)(outs, queryMetadata);
|
|
120
166
|
const { proofType, verifierID, nullifier, nullifierSessionID, linkID } = v3PubSignals;
|
|
121
167
|
switch (query.proofType) {
|
|
122
168
|
case verifiable_1.ProofType.BJJSignature:
|
|
@@ -291,6 +337,53 @@ class PubSignalsVerifier {
|
|
|
291
337
|
}
|
|
292
338
|
return fn(ctx);
|
|
293
339
|
}
|
|
340
|
+
async checkQueryV2Circuits(circuitId, query, outs, opts, verifiablePresentation) {
|
|
341
|
+
if (!query.type) {
|
|
342
|
+
throw new Error(`proof query type is undefined`);
|
|
343
|
+
}
|
|
344
|
+
const loader = this._documentLoader ?? (0, js_jsonld_merklization_1.getDocumentLoader)();
|
|
345
|
+
// validate schema
|
|
346
|
+
let context;
|
|
347
|
+
try {
|
|
348
|
+
context = (await loader(query.context ?? '')).document;
|
|
349
|
+
}
|
|
350
|
+
catch (e) {
|
|
351
|
+
throw new Error(`can't load schema for request query`);
|
|
352
|
+
}
|
|
353
|
+
const queriesMetadata = await (0, common_2.parseQueriesMetadata)(query.type, JSON.stringify(context), query.credentialSubject, {
|
|
354
|
+
documentLoader: loader
|
|
355
|
+
});
|
|
356
|
+
await (0, query_1.checkQueryRequest)(query, queriesMetadata, context, outs, circuitId, this._documentLoader, opts);
|
|
357
|
+
const queryMetadata = queriesMetadata[0]; // only one query is supported
|
|
358
|
+
(0, query_1.checkCircuitOperator)(circuitId, outs.operator);
|
|
359
|
+
// validate selective disclosure
|
|
360
|
+
if (queryMetadata.operator === circuits_1.Operators.SD) {
|
|
361
|
+
try {
|
|
362
|
+
await (0, query_1.validateDisclosureV2Circuit)(queryMetadata, outs, verifiablePresentation, loader);
|
|
363
|
+
}
|
|
364
|
+
catch (e) {
|
|
365
|
+
throw new Error(`failed to validate selective disclosure: ${e.message}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
else if (!queryMetadata.fieldName && queryMetadata.operator == circuits_1.Operators.NOOP) {
|
|
369
|
+
try {
|
|
370
|
+
await (0, query_1.validateEmptyCredentialSubjectV2Circuit)(queryMetadata, outs);
|
|
371
|
+
}
|
|
372
|
+
catch (e) {
|
|
373
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
try {
|
|
378
|
+
await (0, query_1.validateOperators)(queryMetadata, outs);
|
|
379
|
+
}
|
|
380
|
+
catch (e) {
|
|
381
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// verify field inclusion
|
|
385
|
+
(0, query_1.verifyFieldValueInclusionV2)(outs, queryMetadata);
|
|
386
|
+
}
|
|
294
387
|
async resolve(id, state) {
|
|
295
388
|
const idBigInt = id.bigInt();
|
|
296
389
|
const did = js_iden3_core_1.DID.parseFromId(id);
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fieldValueFromVerifiablePresentation = exports.checkQueryRequest = void 0;
|
|
3
|
+
exports.fieldValueFromVerifiablePresentation = exports.validateEmptyCredentialSubjectNoopNativeSupport = exports.validateDisclosureNativeSDSupport = exports.validateDisclosureV2Circuit = exports.validateOperators = exports.validateEmptyCredentialSubjectV2Circuit = exports.verifyFieldValueInclusionNativeExistsSupport = exports.verifyFieldValueInclusionV2 = exports.checkCircuitOperator = exports.checkCircuitQueriesLength = exports.checkQueryRequest = void 0;
|
|
4
4
|
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
5
5
|
const js_jsonld_merklization_1 = require("@iden3/js-jsonld-merklization");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const comparer_1 = require("../../circuits/comparer");
|
|
8
8
|
const verifiable_1 = require("../../verifiable");
|
|
9
|
-
const common_1 = require("../common");
|
|
10
9
|
const provers_1 = require("../provers");
|
|
11
10
|
const defaultProofGenerationDelayOpts = 24 * 60 * 60 * 1000; // 24 hours
|
|
12
|
-
async function checkQueryRequest(query, outputs, circuitId, schemaLoader,
|
|
11
|
+
async function checkQueryRequest(query, queriesMetadata, ldContext, outputs, circuitId, schemaLoader, opts) {
|
|
13
12
|
// validate issuer
|
|
14
13
|
const userDID = js_iden3_core_1.DID.parseFromId(outputs.issuerId);
|
|
15
14
|
const issuerAllowed = !query.allowedIssuers ||
|
|
@@ -17,19 +16,10 @@ async function checkQueryRequest(query, outputs, circuitId, schemaLoader, verifi
|
|
|
17
16
|
if (!issuerAllowed) {
|
|
18
17
|
throw new Error('issuer is not in allowed list');
|
|
19
18
|
}
|
|
20
|
-
// validate schema
|
|
21
|
-
let schema;
|
|
22
|
-
try {
|
|
23
|
-
const loader = schemaLoader ?? (0, js_jsonld_merklization_1.getDocumentLoader)();
|
|
24
|
-
schema = (await loader(query.context ?? '')).document;
|
|
25
|
-
}
|
|
26
|
-
catch (e) {
|
|
27
|
-
throw new Error(`can't load schema for request query`);
|
|
28
|
-
}
|
|
29
19
|
if (!query.type) {
|
|
30
|
-
throw new Error(
|
|
20
|
+
throw new Error('query type is missing');
|
|
31
21
|
}
|
|
32
|
-
const schemaId = await js_jsonld_merklization_1.Path.getTypeIDFromContext(JSON.stringify(
|
|
22
|
+
const schemaId = await js_jsonld_merklization_1.Path.getTypeIDFromContext(JSON.stringify(ldContext), query.type, {
|
|
33
23
|
documentLoader: schemaLoader
|
|
34
24
|
});
|
|
35
25
|
const schemaHash = (0, verifiable_1.calculateCoreSchemaHash)(utils_1.byteEncoder.encode(schemaId));
|
|
@@ -39,76 +29,72 @@ async function checkQueryRequest(query, outputs, circuitId, schemaLoader, verifi
|
|
|
39
29
|
if (!query.skipClaimRevocationCheck && outputs.isRevocationChecked === 0) {
|
|
40
30
|
throw new Error(`check revocation is required`);
|
|
41
31
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
checkCircuitQueriesLength(circuitId, queriesMetadata);
|
|
33
|
+
// verify timestamp
|
|
34
|
+
let acceptedProofGenerationDelay = defaultProofGenerationDelayOpts;
|
|
35
|
+
if (opts?.acceptedProofGenerationDelay) {
|
|
36
|
+
acceptedProofGenerationDelay = opts.acceptedProofGenerationDelay;
|
|
37
|
+
}
|
|
38
|
+
const timeDiff = Date.now() - (0, js_iden3_core_1.getDateFromUnixTimestamp)(Number(outputs.timestamp)).getTime();
|
|
39
|
+
if (timeDiff > acceptedProofGenerationDelay) {
|
|
40
|
+
throw new Error('generated proof is outdated');
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
exports.checkQueryRequest = checkQueryRequest;
|
|
45
|
+
function checkCircuitQueriesLength(circuitId, queriesMetadata) {
|
|
45
46
|
const circuitValidationData = provers_1.circuitValidator[circuitId];
|
|
46
47
|
if (queriesMetadata.length > circuitValidationData.maxQueriesCount) {
|
|
47
48
|
throw new Error(`circuit ${circuitId} supports only ${provers_1.circuitValidator[circuitId].maxQueriesCount} queries`);
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
}
|
|
51
|
+
exports.checkCircuitQueriesLength = checkCircuitQueriesLength;
|
|
52
|
+
function checkCircuitOperator(circuitId, operator) {
|
|
53
|
+
const circuitValidationData = provers_1.circuitValidator[circuitId];
|
|
54
|
+
if (!circuitValidationData.supportedOperations.includes(operator)) {
|
|
55
|
+
throw new Error(`circuit ${circuitId} not support ${(0, comparer_1.getOperatorNameByValue)(operator)} operator`);
|
|
52
56
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
throw new Error(`failed to validate selective disclosure: ${e.message}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
else if (!metadata.fieldName && metadata.operator == comparer_1.Operators.NOOP) {
|
|
68
|
-
try {
|
|
69
|
-
await validateEmptyCredentialSubject(metadata, outputs);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
throw new Error(`failed to validate operators: ${e.message}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
try {
|
|
78
|
-
await validateOperators(metadata, outputs);
|
|
79
|
-
}
|
|
80
|
-
catch (e) {
|
|
81
|
-
throw new Error(`failed to validate operators: ${e.message}`);
|
|
82
|
-
}
|
|
57
|
+
}
|
|
58
|
+
exports.checkCircuitOperator = checkCircuitOperator;
|
|
59
|
+
function verifyFieldValueInclusionV2(outputs, metadata) {
|
|
60
|
+
if (outputs.operator == comparer_1.QueryOperators.$noop) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (outputs.merklized === 1) {
|
|
64
|
+
if (outputs.claimPathNotExists === 1) {
|
|
65
|
+
throw new Error(`proof doesn't contains target query key`);
|
|
83
66
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (outputs.claimPathNotExists === 1) {
|
|
87
|
-
throw new Error(`proof doesn't contains target query key`);
|
|
88
|
-
}
|
|
89
|
-
if (outputs.claimPathKey !== metadata.claimPathKey) {
|
|
90
|
-
throw new Error(`proof was generated for another path`);
|
|
91
|
-
}
|
|
67
|
+
if (outputs.claimPathKey !== metadata.claimPathKey) {
|
|
68
|
+
throw new Error(`proof was generated for another path`);
|
|
92
69
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (outputs.slotIndex !== metadata.slotIndex) {
|
|
73
|
+
throw new Error(`wrong claim slot was used in claim`);
|
|
97
74
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.verifyFieldValueInclusionV2 = verifyFieldValueInclusionV2;
|
|
78
|
+
function verifyFieldValueInclusionNativeExistsSupport(outputs, metadata) {
|
|
79
|
+
if (outputs.operator == comparer_1.Operators.NOOP) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (outputs.operator === comparer_1.Operators.EXISTS && !outputs.merklized) {
|
|
83
|
+
throw new Error('$exists operator is not supported for non-merklized credential');
|
|
84
|
+
}
|
|
85
|
+
if (outputs.merklized === 1) {
|
|
86
|
+
if (outputs.claimPathKey !== metadata.claimPathKey) {
|
|
87
|
+
throw new Error(`proof was generated for another path`);
|
|
102
88
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
if (outputs.slotIndex !== metadata.slotIndex) {
|
|
92
|
+
throw new Error(`wrong claim slot was used in claim`);
|
|
106
93
|
}
|
|
107
94
|
}
|
|
108
|
-
return;
|
|
109
95
|
}
|
|
110
|
-
exports.
|
|
111
|
-
async function
|
|
96
|
+
exports.verifyFieldValueInclusionNativeExistsSupport = verifyFieldValueInclusionNativeExistsSupport;
|
|
97
|
+
async function validateEmptyCredentialSubjectV2Circuit(cq, outputs) {
|
|
112
98
|
if (outputs.operator !== comparer_1.Operators.EQ) {
|
|
113
99
|
throw new Error('empty credentialSubject request available only for equal operation');
|
|
114
100
|
}
|
|
@@ -124,6 +110,7 @@ async function validateEmptyCredentialSubject(cq, outputs) {
|
|
|
124
110
|
}
|
|
125
111
|
return;
|
|
126
112
|
}
|
|
113
|
+
exports.validateEmptyCredentialSubjectV2Circuit = validateEmptyCredentialSubjectV2Circuit;
|
|
127
114
|
async function validateOperators(cq, outputs) {
|
|
128
115
|
if (outputs.operator !== cq.operator) {
|
|
129
116
|
throw new Error(`operator that was used is not equal to request`);
|
|
@@ -141,7 +128,12 @@ async function validateOperators(cq, outputs) {
|
|
|
141
128
|
}
|
|
142
129
|
}
|
|
143
130
|
}
|
|
144
|
-
|
|
131
|
+
exports.validateOperators = validateOperators;
|
|
132
|
+
async function validateDisclosureV2Circuit(cq, outputs, verifiablePresentation, ldLoader) {
|
|
133
|
+
const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader);
|
|
134
|
+
if (bi !== outputs.value[0]) {
|
|
135
|
+
throw new Error(`value that was used is not equal to requested in query`);
|
|
136
|
+
}
|
|
145
137
|
if (outputs.operator !== comparer_1.Operators.EQ) {
|
|
146
138
|
throw new Error(`operator for selective disclosure must be $eq`);
|
|
147
139
|
}
|
|
@@ -150,11 +142,34 @@ async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader)
|
|
|
150
142
|
throw new Error(`selective disclosure not available for array of values`);
|
|
151
143
|
}
|
|
152
144
|
}
|
|
145
|
+
}
|
|
146
|
+
exports.validateDisclosureV2Circuit = validateDisclosureV2Circuit;
|
|
147
|
+
async function validateDisclosureNativeSDSupport(cq, outputs, verifiablePresentation, ldLoader) {
|
|
153
148
|
const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader);
|
|
154
|
-
if (bi !== outputs.
|
|
155
|
-
throw new Error(`
|
|
149
|
+
if (bi !== outputs.operatorOutput) {
|
|
150
|
+
throw new Error(`operator output should be equal to disclosed value`);
|
|
151
|
+
}
|
|
152
|
+
if (outputs.operator !== comparer_1.Operators.SD) {
|
|
153
|
+
throw new Error(`operator for selective disclosure must be $sd`);
|
|
154
|
+
}
|
|
155
|
+
for (let index = 0; index < outputs.value.length; index++) {
|
|
156
|
+
if (outputs.value[index] !== 0n) {
|
|
157
|
+
throw new Error(`public signal values must be zero`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.validateDisclosureNativeSDSupport = validateDisclosureNativeSDSupport;
|
|
162
|
+
async function validateEmptyCredentialSubjectNoopNativeSupport(outputs) {
|
|
163
|
+
if (outputs.operator !== comparer_1.Operators.NOOP) {
|
|
164
|
+
throw new Error('empty credentialSubject request available only for $noop operation');
|
|
165
|
+
}
|
|
166
|
+
for (let index = 1; index < outputs.value.length; index++) {
|
|
167
|
+
if (outputs.value[index] !== 0n) {
|
|
168
|
+
throw new Error(`empty credentialSubject request not available for array of values`);
|
|
169
|
+
}
|
|
156
170
|
}
|
|
157
171
|
}
|
|
172
|
+
exports.validateEmptyCredentialSubjectNoopNativeSupport = validateEmptyCredentialSubjectNoopNativeSupport;
|
|
158
173
|
const fieldValueFromVerifiablePresentation = async (fieldName, verifiablePresentation, ldLoader) => {
|
|
159
174
|
if (!verifiablePresentation) {
|
|
160
175
|
throw new Error(`verifiablePresentation is required for selective disclosure request`);
|
|
@@ -52,6 +52,10 @@ export const QueryOperators = {
|
|
|
52
52
|
$sd: Operators.SD,
|
|
53
53
|
$nullify: Operators.NULLIFY
|
|
54
54
|
};
|
|
55
|
+
export const getOperatorNameByValue = (operator) => {
|
|
56
|
+
const ops = Object.entries(QueryOperators).find(([, queryOp]) => queryOp === operator);
|
|
57
|
+
return ops ? ops[0] : 'unknown';
|
|
58
|
+
};
|
|
55
59
|
const allOperations = Object.values(QueryOperators);
|
|
56
60
|
export const availableTypesOperators = new Map([
|
|
57
61
|
[
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as providerHelpers from '../provider-helpers';
|
|
2
|
+
import { ed25519 } from '@noble/curves/ed25519';
|
|
3
|
+
import { bytesToHex } from '../../utils';
|
|
4
|
+
/**
|
|
5
|
+
* Provider for Ed25519 keys
|
|
6
|
+
* @public
|
|
7
|
+
* @class Ed25519Provider
|
|
8
|
+
* @implements IKeyProvider interface
|
|
9
|
+
*/
|
|
10
|
+
export class Ed25519Provider {
|
|
11
|
+
/**
|
|
12
|
+
* Creates an instance of Ed25519Provider.
|
|
13
|
+
* @param {KmsKeyType} keyType - kms key type
|
|
14
|
+
* @param {AbstractPrivateKeyStore} keyStore - key store for kms
|
|
15
|
+
*/
|
|
16
|
+
constructor(keyType, _keyStore) {
|
|
17
|
+
this.keyType = keyType;
|
|
18
|
+
this._keyStore = _keyStore;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* generates a ed25519 key from a seed phrase
|
|
22
|
+
* @param {Uint8Array} seed - byte array seed
|
|
23
|
+
* @returns {Promise<KmsKeyId>} kms key identifier
|
|
24
|
+
*/
|
|
25
|
+
async newPrivateKeyFromSeed(seed) {
|
|
26
|
+
if (seed.length !== 32) {
|
|
27
|
+
throw new Error('Seed should be 32 bytes');
|
|
28
|
+
}
|
|
29
|
+
const publicKey = ed25519.getPublicKey(seed);
|
|
30
|
+
const kmsId = {
|
|
31
|
+
type: this.keyType,
|
|
32
|
+
id: providerHelpers.keyPath(this.keyType, bytesToHex(publicKey))
|
|
33
|
+
};
|
|
34
|
+
await this._keyStore.importKey({
|
|
35
|
+
alias: kmsId.id,
|
|
36
|
+
key: bytesToHex(seed)
|
|
37
|
+
});
|
|
38
|
+
return kmsId;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gets public key by kmsKeyId
|
|
42
|
+
* @param {KmsKeyId} keyId - key identifier
|
|
43
|
+
* @returns {Promise<string>} Public key as a hex string
|
|
44
|
+
*/
|
|
45
|
+
async publicKey(keyId) {
|
|
46
|
+
const privateKeyHex = await this.privateKey(keyId);
|
|
47
|
+
const publicKey = ed25519.getPublicKey(privateKeyHex);
|
|
48
|
+
return bytesToHex(publicKey);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* signs prepared payload of size,
|
|
52
|
+
* with a key id
|
|
53
|
+
* @param {KmsKeyId} keyId - key identifier
|
|
54
|
+
* @param {Uint8Array} data - data to sign (32 bytes)
|
|
55
|
+
* @returns {Promise<Uint8Array>} signature
|
|
56
|
+
*/
|
|
57
|
+
async sign(keyId, data) {
|
|
58
|
+
const privateKeyHex = await this.privateKey(keyId);
|
|
59
|
+
return ed25519.sign(data, privateKeyHex);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Retrieves the private key for a given keyId from the key store.
|
|
63
|
+
* @param {KmsKeyId} keyId - The identifier of the key to retrieve.
|
|
64
|
+
* @returns {Promise<string>} The private key associated with the keyId.
|
|
65
|
+
*/
|
|
66
|
+
async privateKey(keyId) {
|
|
67
|
+
return this._keyStore.get({ alias: keyId.id });
|
|
68
|
+
}
|
|
69
|
+
}
|