@0xpolygonid/js-sdk 1.9.1 → 1.9.3
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 +2991 -1225
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +2956 -1181
- 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/common.js +11 -3
- package/dist/node/cjs/proof/proof-service.js +1 -4
- package/dist/node/cjs/proof/provers/inputs-generator.js +16 -1
- package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +93 -3
- package/dist/node/cjs/proof/verifiers/query.js +80 -72
- package/dist/node/cjs/storage/filters/jsonQuery.js +1 -1
- 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/common.js +12 -4
- package/dist/node/esm/proof/proof-service.js +1 -4
- package/dist/node/esm/proof/provers/inputs-generator.js +17 -2
- package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +95 -5
- package/dist/node/esm/proof/verifiers/query.js +74 -73
- package/dist/node/esm/storage/filters/jsonQuery.js +1 -1
- 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 +11 -1
- package/package.json +2 -1
|
@@ -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);
|
|
@@ -125,12 +125,14 @@ const parseQueryMetadata = async (propertyQuery, ldContextJSON, credentialType,
|
|
|
125
125
|
throw new Error(`field does not exist in the schema ${e.message}`);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
if (propertyQuery.operatorValue) {
|
|
128
|
+
if (propertyQuery.operatorValue !== undefined) {
|
|
129
129
|
if (!(0, circuits_1.isValidOperation)(query.datatype, propertyQuery.operator)) {
|
|
130
130
|
throw new Error(`operator ${propertyQuery.operator} is not supported for datatype ${query.datatype}`);
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
query.values =
|
|
133
|
+
propertyQuery.operator === circuits_1.Operators.EXISTS
|
|
134
|
+
? transformExistsValue(propertyQuery.operatorValue)
|
|
135
|
+
: await (0, exports.transformQueryValueToBigInts)(propertyQuery.operatorValue, query.datatype);
|
|
134
136
|
}
|
|
135
137
|
return query;
|
|
136
138
|
};
|
|
@@ -153,3 +155,9 @@ const transformQueryValueToBigInts = async (value, ldType) => {
|
|
|
153
155
|
return values;
|
|
154
156
|
};
|
|
155
157
|
exports.transformQueryValueToBigInts = transformQueryValueToBigInts;
|
|
158
|
+
const transformExistsValue = (value) => {
|
|
159
|
+
if (typeof value == 'boolean') {
|
|
160
|
+
return [BigInt(value)];
|
|
161
|
+
}
|
|
162
|
+
throw new Error('exists operator value must be true or false');
|
|
163
|
+
};
|
|
@@ -191,10 +191,7 @@ class ProofService {
|
|
|
191
191
|
query.valueProof = new circuits_1.ValueProof();
|
|
192
192
|
query.valueProof.mtp = proof;
|
|
193
193
|
query.valueProof.path = queryMetadata.claimPathKey;
|
|
194
|
-
const mtEntry = await mtValue?.mtEntry();
|
|
195
|
-
if (!mtEntry) {
|
|
196
|
-
throw new Error(`can't merklize credential: no merkle tree entry found`);
|
|
197
|
-
}
|
|
194
|
+
const mtEntry = (await mtValue?.mtEntry()) ?? 0n;
|
|
198
195
|
query.valueProof.value = mtEntry;
|
|
199
196
|
if (!queryMetadata.fieldName) {
|
|
200
197
|
query.values = [mtEntry];
|
|
@@ -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,53 @@ 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
|
+
await (0, query_1.checkQueryRequest)(query, queriesMetadata, context, outs, models_1.CircuitId.AtomicQueryV3, this._documentLoader, opts);
|
|
136
|
+
const queryMetadata = queriesMetadata[0]; // only one query is supported
|
|
137
|
+
// validate selective disclosure
|
|
138
|
+
if (queryMetadata.operator === circuits_1.Operators.SD) {
|
|
139
|
+
try {
|
|
140
|
+
await (0, query_1.validateDisclosureNativeSDSupport)(queryMetadata, outs, verifiablePresentation, loader);
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
throw new Error(`failed to validate selective disclosure: ${e.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else if (!queryMetadata.fieldName && queryMetadata.operator == circuits_1.Operators.NOOP) {
|
|
147
|
+
try {
|
|
148
|
+
await (0, query_1.validateEmptyCredentialSubjectNoopNativeSupport)(outs);
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
try {
|
|
156
|
+
await (0, query_1.validateOperators)(queryMetadata, outs);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// verify field inclusion / non-inclusion
|
|
163
|
+
(0, query_1.verifyFieldValueInclusionNativeExistsSupport)(outs, queryMetadata);
|
|
120
164
|
const { proofType, verifierID, nullifier, nullifierSessionID, linkID } = v3PubSignals;
|
|
121
165
|
switch (query.proofType) {
|
|
122
166
|
case verifiable_1.ProofType.BJJSignature:
|
|
@@ -291,6 +335,52 @@ class PubSignalsVerifier {
|
|
|
291
335
|
}
|
|
292
336
|
return fn(ctx);
|
|
293
337
|
}
|
|
338
|
+
async checkQueryV2Circuits(circuitId, query, outs, opts, verifiablePresentation) {
|
|
339
|
+
if (!query.type) {
|
|
340
|
+
throw new Error(`proof query type is undefined`);
|
|
341
|
+
}
|
|
342
|
+
const loader = this._documentLoader ?? (0, js_jsonld_merklization_1.getDocumentLoader)();
|
|
343
|
+
// validate schema
|
|
344
|
+
let context;
|
|
345
|
+
try {
|
|
346
|
+
context = (await loader(query.context ?? '')).document;
|
|
347
|
+
}
|
|
348
|
+
catch (e) {
|
|
349
|
+
throw new Error(`can't load schema for request query`);
|
|
350
|
+
}
|
|
351
|
+
const queriesMetadata = await (0, common_2.parseQueriesMetadata)(query.type, JSON.stringify(context), query.credentialSubject, {
|
|
352
|
+
documentLoader: loader
|
|
353
|
+
});
|
|
354
|
+
await (0, query_1.checkQueryRequest)(query, queriesMetadata, context, outs, circuitId, this._documentLoader, opts);
|
|
355
|
+
const queryMetadata = queriesMetadata[0]; // only one query is supported
|
|
356
|
+
// validate selective disclosure
|
|
357
|
+
if (queryMetadata.operator === circuits_1.Operators.SD) {
|
|
358
|
+
try {
|
|
359
|
+
await (0, query_1.validateDisclosureV2Circuit)(queryMetadata, outs, verifiablePresentation, loader);
|
|
360
|
+
}
|
|
361
|
+
catch (e) {
|
|
362
|
+
throw new Error(`failed to validate selective disclosure: ${e.message}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (!queryMetadata.fieldName && queryMetadata.operator == circuits_1.Operators.NOOP) {
|
|
366
|
+
try {
|
|
367
|
+
await (0, query_1.validateEmptyCredentialSubjectV2Circuit)(queryMetadata, outs);
|
|
368
|
+
}
|
|
369
|
+
catch (e) {
|
|
370
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
try {
|
|
375
|
+
await (0, query_1.validateOperators)(queryMetadata, outs);
|
|
376
|
+
}
|
|
377
|
+
catch (e) {
|
|
378
|
+
throw new Error(`failed to validate operators: ${e.message}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// verify field inclusion
|
|
382
|
+
(0, query_1.verifyFieldValueInclusionV2)(outs, queryMetadata);
|
|
383
|
+
}
|
|
294
384
|
async resolve(id, state) {
|
|
295
385
|
const idBigInt = id.bigInt();
|
|
296
386
|
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.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,9 +29,6 @@ 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
|
-
const queriesMetadata = await (0, common_1.parseQueriesMetadata)(query.type, JSON.stringify(schema), query.credentialSubject, {
|
|
43
|
-
documentLoader: schemaLoader
|
|
44
|
-
});
|
|
45
32
|
const circuitValidationData = provers_1.circuitValidator[circuitId];
|
|
46
33
|
if (queriesMetadata.length > circuitValidationData.maxQueriesCount) {
|
|
47
34
|
throw new Error(`circuit ${circuitId} supports only ${provers_1.circuitValidator[circuitId].maxQueriesCount} queries`);
|
|
@@ -50,65 +37,57 @@ async function checkQueryRequest(query, outputs, circuitId, schemaLoader, verifi
|
|
|
50
37
|
if (notSupportedOpIndx > -1) {
|
|
51
38
|
throw new Error(`circuit ${circuitId} not support ${queriesMetadata[notSupportedOpIndx].operator} operator`);
|
|
52
39
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
}
|
|
40
|
+
// verify timestamp
|
|
41
|
+
let acceptedProofGenerationDelay = defaultProofGenerationDelayOpts;
|
|
42
|
+
if (opts?.acceptedProofGenerationDelay) {
|
|
43
|
+
acceptedProofGenerationDelay = opts.acceptedProofGenerationDelay;
|
|
44
|
+
}
|
|
45
|
+
const timeDiff = Date.now() - (0, js_iden3_core_1.getDateFromUnixTimestamp)(Number(outputs.timestamp)).getTime();
|
|
46
|
+
if (timeDiff > acceptedProofGenerationDelay) {
|
|
47
|
+
throw new Error('generated proof is outdated');
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
exports.checkQueryRequest = checkQueryRequest;
|
|
52
|
+
function verifyFieldValueInclusionV2(outputs, metadata) {
|
|
53
|
+
if (outputs.operator == comparer_1.QueryOperators.$noop) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (outputs.merklized === 1) {
|
|
57
|
+
if (outputs.claimPathNotExists === 1) {
|
|
58
|
+
throw new Error(`proof doesn't contains target query key`);
|
|
83
59
|
}
|
|
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
|
-
}
|
|
60
|
+
if (outputs.claimPathKey !== metadata.claimPathKey) {
|
|
61
|
+
throw new Error(`proof was generated for another path`);
|
|
92
62
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (outputs.slotIndex !== metadata.slotIndex) {
|
|
66
|
+
throw new Error(`wrong claim slot was used in claim`);
|
|
97
67
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.verifyFieldValueInclusionV2 = verifyFieldValueInclusionV2;
|
|
71
|
+
function verifyFieldValueInclusionNativeExistsSupport(outputs, metadata) {
|
|
72
|
+
if (outputs.operator == comparer_1.Operators.NOOP) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (outputs.operator === comparer_1.Operators.EXISTS && !outputs.merklized) {
|
|
76
|
+
throw new Error('$exists operator is not supported for non-merklized credential');
|
|
77
|
+
}
|
|
78
|
+
if (outputs.merklized === 1) {
|
|
79
|
+
if (outputs.claimPathKey !== metadata.claimPathKey) {
|
|
80
|
+
throw new Error(`proof was generated for another path`);
|
|
102
81
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
if (outputs.slotIndex !== metadata.slotIndex) {
|
|
85
|
+
throw new Error(`wrong claim slot was used in claim`);
|
|
106
86
|
}
|
|
107
87
|
}
|
|
108
|
-
return;
|
|
109
88
|
}
|
|
110
|
-
exports.
|
|
111
|
-
async function
|
|
89
|
+
exports.verifyFieldValueInclusionNativeExistsSupport = verifyFieldValueInclusionNativeExistsSupport;
|
|
90
|
+
async function validateEmptyCredentialSubjectV2Circuit(cq, outputs) {
|
|
112
91
|
if (outputs.operator !== comparer_1.Operators.EQ) {
|
|
113
92
|
throw new Error('empty credentialSubject request available only for equal operation');
|
|
114
93
|
}
|
|
@@ -124,6 +103,7 @@ async function validateEmptyCredentialSubject(cq, outputs) {
|
|
|
124
103
|
}
|
|
125
104
|
return;
|
|
126
105
|
}
|
|
106
|
+
exports.validateEmptyCredentialSubjectV2Circuit = validateEmptyCredentialSubjectV2Circuit;
|
|
127
107
|
async function validateOperators(cq, outputs) {
|
|
128
108
|
if (outputs.operator !== cq.operator) {
|
|
129
109
|
throw new Error(`operator that was used is not equal to request`);
|
|
@@ -141,7 +121,12 @@ async function validateOperators(cq, outputs) {
|
|
|
141
121
|
}
|
|
142
122
|
}
|
|
143
123
|
}
|
|
144
|
-
|
|
124
|
+
exports.validateOperators = validateOperators;
|
|
125
|
+
async function validateDisclosureV2Circuit(cq, outputs, verifiablePresentation, ldLoader) {
|
|
126
|
+
const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader);
|
|
127
|
+
if (bi !== outputs.value[0]) {
|
|
128
|
+
throw new Error(`value that was used is not equal to requested in query`);
|
|
129
|
+
}
|
|
145
130
|
if (outputs.operator !== comparer_1.Operators.EQ) {
|
|
146
131
|
throw new Error(`operator for selective disclosure must be $eq`);
|
|
147
132
|
}
|
|
@@ -150,11 +135,34 @@ async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader)
|
|
|
150
135
|
throw new Error(`selective disclosure not available for array of values`);
|
|
151
136
|
}
|
|
152
137
|
}
|
|
138
|
+
}
|
|
139
|
+
exports.validateDisclosureV2Circuit = validateDisclosureV2Circuit;
|
|
140
|
+
async function validateDisclosureNativeSDSupport(cq, outputs, verifiablePresentation, ldLoader) {
|
|
153
141
|
const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader);
|
|
154
|
-
if (bi !== outputs.
|
|
155
|
-
throw new Error(`
|
|
142
|
+
if (bi !== outputs.operatorOutput) {
|
|
143
|
+
throw new Error(`operator output should be equal to disclosed value`);
|
|
144
|
+
}
|
|
145
|
+
if (outputs.operator !== comparer_1.Operators.SD) {
|
|
146
|
+
throw new Error(`operator for selective disclosure must be $sd`);
|
|
147
|
+
}
|
|
148
|
+
for (let index = 0; index < outputs.value.length; index++) {
|
|
149
|
+
if (outputs.value[index] !== 0n) {
|
|
150
|
+
throw new Error(`public signal values must be zero`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.validateDisclosureNativeSDSupport = validateDisclosureNativeSDSupport;
|
|
155
|
+
async function validateEmptyCredentialSubjectNoopNativeSupport(outputs) {
|
|
156
|
+
if (outputs.operator !== comparer_1.Operators.NOOP) {
|
|
157
|
+
throw new Error('empty credentialSubject request available only for $noop operation');
|
|
158
|
+
}
|
|
159
|
+
for (let index = 1; index < outputs.value.length; index++) {
|
|
160
|
+
if (outputs.value[index] !== 0n) {
|
|
161
|
+
throw new Error(`empty credentialSubject request not available for array of values`);
|
|
162
|
+
}
|
|
156
163
|
}
|
|
157
164
|
}
|
|
165
|
+
exports.validateEmptyCredentialSubjectNoopNativeSupport = validateEmptyCredentialSubjectNoopNativeSupport;
|
|
158
166
|
const fieldValueFromVerifiablePresentation = async (fieldName, verifiablePresentation, ldLoader) => {
|
|
159
167
|
if (!verifiablePresentation) {
|
|
160
168
|
throw new Error(`verifiablePresentation is required for selective disclosure request`);
|
|
@@ -166,7 +166,7 @@ class FilterQuery {
|
|
|
166
166
|
}
|
|
167
167
|
const credentialPathValue = (0, exports.resolvePath)(credential, this.path);
|
|
168
168
|
if ((credentialPathValue === null || credentialPathValue === undefined) &&
|
|
169
|
-
this.operatorFunc !==
|
|
169
|
+
this.operatorFunc !== exports.comparatorOptions.$exists) {
|
|
170
170
|
return false;
|
|
171
171
|
}
|
|
172
172
|
if (this.isReverseParams) {
|
|
@@ -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
|
[
|