@zkpassport/sdk 0.5.6 → 0.5.7-beta.10

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.js DELETED
@@ -1,2345 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ZKPassport = exports.MERCOSUR_COUNTRIES = exports.ASEAN_COUNTRIES = exports.SCHENGEN_COUNTRIES = exports.EEA_COUNTRIES = exports.EU_COUNTRIES = exports.SANCTIONED_COUNTRIES = void 0;
4
- const tslib_1 = require("tslib");
5
- const i18n_iso_countries_1 = require("i18n-iso-countries");
6
- const utils_1 = require("@zkpassport/utils");
7
- const utils_2 = require("@noble/ciphers/utils");
8
- const logger_1 = require("./logger");
9
- const en_json_1 = tslib_1.__importDefault(require("i18n-iso-countries/langs/en.json"));
10
- const buffer_1 = require("buffer/");
11
- const sha2_1 = require("@noble/hashes/sha2");
12
- const utils_3 = require("@noble/hashes/utils");
13
- const ZKPassportVerifier_json_1 = tslib_1.__importDefault(require("./assets/abi/ZKPassportVerifier.json"));
14
- const registry_1 = require("@zkpassport/registry");
15
- const bridge_1 = require("@obsidion/bridge");
16
- const VERSION = "0.5.5";
17
- const DEFAULT_DATE_VALUE = new Date(1111, 10, 11);
18
- // If Buffer is not defined, then we use the Buffer from the buffer package
19
- if (typeof globalThis.Buffer === "undefined") {
20
- globalThis.Buffer = buffer_1.Buffer;
21
- if (typeof window !== "undefined") {
22
- window.Buffer = buffer_1.Buffer;
23
- }
24
- }
25
- function getChainIdFromEVMChain(chain) {
26
- if (chain === "ethereum_sepolia") {
27
- return 11155111;
28
- }
29
- else if (chain === "local_anvil") {
30
- return 31337;
31
- }
32
- throw new Error(`Unsupported chain: ${chain}`);
33
- }
34
- function getEVMChainFromChainId(chainId) {
35
- if (chainId === 11155111) {
36
- return "ethereum_sepolia";
37
- }
38
- else if (chainId === 31337) {
39
- return "local_anvil";
40
- }
41
- throw new Error(`Unsupported chain ID: ${chainId}`);
42
- }
43
- (0, i18n_iso_countries_1.registerLocale)(en_json_1.default);
44
- function hasRequestedAccessToField(credentialsRequest, field) {
45
- const fieldValue = credentialsRequest[field];
46
- const isDefined = fieldValue !== undefined && fieldValue !== null;
47
- if (!isDefined) {
48
- return false;
49
- }
50
- for (const key in fieldValue) {
51
- if (fieldValue[key] !== undefined &&
52
- fieldValue[key] !== null) {
53
- return true;
54
- }
55
- }
56
- return false;
57
- }
58
- function normalizeCountry(country) {
59
- if (country === "Zero Knowledge Republic") {
60
- return "ZKR";
61
- }
62
- let normalizedCountry;
63
- const alpha3 = (0, i18n_iso_countries_1.getAlpha3Code)(country, "en");
64
- normalizedCountry = alpha3 || country || "ZKR";
65
- return normalizedCountry;
66
- }
67
- function numericalCompare(fnName, key, value, requestId, requestIdToConfig) {
68
- requestIdToConfig[requestId][key] = {
69
- ...requestIdToConfig[requestId][key],
70
- [fnName]: value,
71
- };
72
- }
73
- function rangeCompare(key, value, requestId, requestIdToConfig) {
74
- requestIdToConfig[requestId][key] = {
75
- ...requestIdToConfig[requestId][key],
76
- range: value,
77
- };
78
- }
79
- function generalCompare(fnName, key, value, requestId, requestIdToConfig) {
80
- requestIdToConfig[requestId][key] = {
81
- ...requestIdToConfig[requestId][key],
82
- [fnName]: value,
83
- };
84
- }
85
- var utils_4 = require("@zkpassport/utils");
86
- Object.defineProperty(exports, "SANCTIONED_COUNTRIES", { enumerable: true, get: function () { return utils_4.SANCTIONED_COUNTRIES; } });
87
- Object.defineProperty(exports, "EU_COUNTRIES", { enumerable: true, get: function () { return utils_4.EU_COUNTRIES; } });
88
- Object.defineProperty(exports, "EEA_COUNTRIES", { enumerable: true, get: function () { return utils_4.EEA_COUNTRIES; } });
89
- Object.defineProperty(exports, "SCHENGEN_COUNTRIES", { enumerable: true, get: function () { return utils_4.SCHENGEN_COUNTRIES; } });
90
- Object.defineProperty(exports, "ASEAN_COUNTRIES", { enumerable: true, get: function () { return utils_4.ASEAN_COUNTRIES; } });
91
- Object.defineProperty(exports, "MERCOSUR_COUNTRIES", { enumerable: true, get: function () { return utils_4.MERCOSUR_COUNTRIES; } });
92
- class ZKPassport {
93
- //private wasmVerifierInit: boolean = false
94
- constructor(_domain) {
95
- this.topicToConfig = {};
96
- this.topicToLocalConfig = {};
97
- this.topicToPublicKey = {};
98
- this.topicToBridge = {};
99
- this.topicToRequestReceived = {};
100
- this.topicToService = {};
101
- this.topicToProofs = {};
102
- this.topicToExpectedProofCount = {};
103
- this.topicToFailedProofCount = {};
104
- this.topicToResults = {};
105
- this.onRequestReceivedCallbacks = {};
106
- this.onGeneratingProofCallbacks = {};
107
- this.onBridgeConnectCallbacks = {};
108
- this.onProofGeneratedCallbacks = {};
109
- this.onResultCallbacks = {};
110
- this.onRejectCallbacks = {};
111
- this.onErrorCallbacks = {};
112
- if (!_domain && typeof window === "undefined") {
113
- throw new Error("Domain argument is required in Node.js environment");
114
- }
115
- this.domain = _domain || window.location.hostname;
116
- }
117
- async handleResult(topic) {
118
- const result = this.topicToResults[topic];
119
- // Clear the results straight away to avoid concurrency issues
120
- delete this.topicToResults[topic];
121
- // Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
122
- const { uniqueIdentifier, verified, queryResultErrors } = await this.verify({
123
- proofs: this.topicToProofs[topic],
124
- queryResult: result,
125
- validity: this.topicToLocalConfig[topic]?.validity,
126
- scope: this.topicToService[topic]?.scope,
127
- evmChain: this.topicToService[topic]?.chainId
128
- ? getEVMChainFromChainId(this.topicToService[topic]?.chainId)
129
- : undefined,
130
- devMode: this.topicToLocalConfig[topic]?.devMode,
131
- });
132
- delete this.topicToProofs[topic];
133
- const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
134
- await Promise.all(this.onResultCallbacks[topic].map((callback) => callback({
135
- // If there are failed proofs, we don't return the unique identifier
136
- // and we set the verified result to false
137
- uniqueIdentifier: hasFailedProofs ? undefined : uniqueIdentifier,
138
- verified: hasFailedProofs ? false : verified,
139
- result,
140
- queryResultErrors,
141
- })));
142
- // Clear the expected proof count and failed proof count
143
- delete this.topicToExpectedProofCount[topic];
144
- delete this.topicToFailedProofCount[topic];
145
- }
146
- setExpectedProofCount(topic) {
147
- // If the mode is not fast, we'll receive only 1 compressed proof
148
- if (this.topicToLocalConfig[topic].mode !== "fast") {
149
- this.topicToExpectedProofCount[topic] = 1;
150
- return;
151
- }
152
- const fields = Object.keys(this.topicToConfig[topic]).filter((key) => hasRequestedAccessToField(this.topicToConfig[topic], key));
153
- const neededCircuits = [];
154
- // Determine which circuits are needed based on the requested fields
155
- for (const field of fields) {
156
- for (const key in this.topicToConfig[topic][field]) {
157
- switch (key) {
158
- case "eq":
159
- case "disclose":
160
- if (field !== "age" && !neededCircuits.includes("disclose_bytes")) {
161
- neededCircuits.push("disclose_bytes");
162
- }
163
- else if (field === "age" && !neededCircuits.includes("compare_age")) {
164
- neededCircuits.push("compare_age");
165
- }
166
- break;
167
- case "gte":
168
- case "gt":
169
- case "lte":
170
- case "lt":
171
- case "range":
172
- if (field === "age" && !neededCircuits.includes("compare_age")) {
173
- neededCircuits.push("compare_age");
174
- }
175
- else if (field === "expiry_date" && !neededCircuits.includes("compare_expiry")) {
176
- neededCircuits.push("compare_expiry");
177
- }
178
- else if (field === "birthdate" && !neededCircuits.includes("compare_birthdate")) {
179
- neededCircuits.push("compare_birthdate");
180
- }
181
- break;
182
- case "in":
183
- if (field === "nationality" &&
184
- !neededCircuits.includes("inclusion_check_nationality")) {
185
- neededCircuits.push("inclusion_check_nationality");
186
- }
187
- else if (field === "issuing_country" &&
188
- !neededCircuits.includes("inclusion_check_issuing_country")) {
189
- neededCircuits.push("inclusion_check_issuing_country");
190
- }
191
- break;
192
- case "out":
193
- if (field === "nationality" &&
194
- !neededCircuits.includes("exclusion_check_nationality")) {
195
- neededCircuits.push("exclusion_check_nationality");
196
- }
197
- else if (field === "issuing_country" &&
198
- !neededCircuits.includes("exclusion_check_issuing_country")) {
199
- neededCircuits.push("exclusion_check_issuing_country");
200
- }
201
- break;
202
- }
203
- }
204
- }
205
- if (this.topicToConfig[topic].bind) {
206
- neededCircuits.push("bind");
207
- }
208
- // From the circuits needed, determine the expected proof count
209
- // There are at least 4 proofs, 3 base proofs and 1 disclosure proof minimum
210
- // Each separate needed circuit adds 1 disclosure proof
211
- this.topicToExpectedProofCount[topic] =
212
- neededCircuits.length === 0 ? 4 : 3 + neededCircuits.length;
213
- this.topicToFailedProofCount[topic] = 0;
214
- }
215
- /**
216
- * @notice Handle an encrypted message.
217
- * @param request The request.
218
- * @param outerRequest The outer request.
219
- */
220
- async handleEncryptedMessage(topic, request) {
221
- logger_1.noLogger.debug("Received encrypted message:", request);
222
- if (request.method === "accept") {
223
- logger_1.noLogger.debug(`User accepted the request and is generating a proof`);
224
- await Promise.all(this.onGeneratingProofCallbacks[topic].map((callback) => callback(topic)));
225
- }
226
- else if (request.method === "reject") {
227
- logger_1.noLogger.debug(`User rejected the request`);
228
- await Promise.all(this.onRejectCallbacks[topic].map((callback) => callback()));
229
- }
230
- else if (request.method === "proof") {
231
- logger_1.noLogger.debug(`User generated proof`);
232
- this.topicToProofs[topic].push(request.params);
233
- await Promise.all(this.onProofGeneratedCallbacks[topic].map((callback) => callback(request.params)));
234
- // If the results were received before all the proofs were generated,
235
- // we can handle the result now
236
- if (this.topicToResults[topic] &&
237
- this.topicToExpectedProofCount[topic] === this.topicToProofs[topic].length) {
238
- await this.handleResult(topic);
239
- }
240
- }
241
- else if (request.method === "done") {
242
- logger_1.noLogger.debug(`User sent the query result`);
243
- const formattedResult = request.params;
244
- // Make sure to reconvert the dates to Date objects
245
- if (formattedResult.birthdate && formattedResult.birthdate.disclose) {
246
- formattedResult.birthdate.disclose.result = new Date(formattedResult.birthdate.disclose.result);
247
- }
248
- if (formattedResult.expiry_date && formattedResult.expiry_date.disclose) {
249
- formattedResult.expiry_date.disclose.result = new Date(formattedResult.expiry_date.disclose.result);
250
- }
251
- this.topicToResults[topic] = formattedResult;
252
- // Make sure all the proofs have been received, otherwise we'll handle the result later
253
- // once the proofs have all been received
254
- if (this.topicToExpectedProofCount[topic] === this.topicToProofs[topic].length) {
255
- await this.handleResult(topic);
256
- }
257
- }
258
- else if (request.method === "error") {
259
- const error = request.params.error;
260
- if (error && error === "This ID is not supported yet") {
261
- // This means the user has an ID that is not supported yet
262
- // So we won't receive any proofs and we can handle the result now
263
- this.topicToExpectedProofCount[topic] = 0;
264
- this.topicToFailedProofCount[topic] += this.topicToExpectedProofCount[topic];
265
- if (this.topicToResults[topic]) {
266
- await this.handleResult(topic);
267
- }
268
- }
269
- else if (error && error.startsWith("Cannot generate proof")) {
270
- // This means one of the disclosure proofs failed to be generated
271
- // So we need to remove one from the expected proof count
272
- this.topicToExpectedProofCount[topic] -= 1;
273
- this.topicToFailedProofCount[topic] += 1;
274
- // If the expected proof count is now equal to the number of proofs received
275
- // and the results were received, we can handle the result now
276
- if (this.topicToResults[topic] &&
277
- this.topicToExpectedProofCount[topic] === this.topicToProofs[topic].length) {
278
- await this.handleResult(topic);
279
- }
280
- }
281
- await Promise.all(this.onErrorCallbacks[topic].map((callback) => callback(error)));
282
- }
283
- }
284
- getZkPassportRequest(topic) {
285
- return {
286
- eq: (key, value) => {
287
- if (key === "issuing_country" || key === "nationality") {
288
- value = normalizeCountry(value);
289
- }
290
- generalCompare("eq", key, value, topic, this.topicToConfig);
291
- return this.getZkPassportRequest(topic);
292
- },
293
- gte: (key, value) => {
294
- numericalCompare("gte", key, value, topic, this.topicToConfig);
295
- if (key === "age" && (value < 1 || value >= 100)) {
296
- throw new Error("Age must be between 1 and 99 (inclusive)");
297
- }
298
- return this.getZkPassportRequest(topic);
299
- },
300
- /*gt: <T extends NumericalIDCredential>(key: T, value: IDCredentialValue<T>) => {
301
- numericalCompare('gt', key, value, topic, this.topicToConfig)
302
- return this.getZkPassportRequest(topic)
303
- },*/
304
- lte: (key, value) => {
305
- numericalCompare("lte", key, value, topic, this.topicToConfig);
306
- return this.getZkPassportRequest(topic);
307
- },
308
- lt: (key, value) => {
309
- numericalCompare("lt", key, value, topic, this.topicToConfig);
310
- return this.getZkPassportRequest(topic);
311
- },
312
- range: (key, start, end) => {
313
- rangeCompare(key, [start, end], topic, this.topicToConfig);
314
- return this.getZkPassportRequest(topic);
315
- },
316
- in: (key, value) => {
317
- value = value.map((v) => normalizeCountry(v));
318
- generalCompare("in", key, value, topic, this.topicToConfig);
319
- return this.getZkPassportRequest(topic);
320
- },
321
- out: (key, value) => {
322
- value = value.map((v) => normalizeCountry(v));
323
- generalCompare("out", key, value, topic, this.topicToConfig);
324
- return this.getZkPassportRequest(topic);
325
- },
326
- disclose: (key) => {
327
- this.topicToConfig[topic][key] = {
328
- ...this.topicToConfig[topic][key],
329
- disclose: true,
330
- };
331
- return this.getZkPassportRequest(topic);
332
- },
333
- bind: (key, value) => {
334
- this.topicToConfig[topic].bind = {
335
- ...this.topicToConfig[topic].bind,
336
- [key]: value,
337
- };
338
- return this.getZkPassportRequest(topic);
339
- },
340
- done: () => {
341
- this.setExpectedProofCount(topic);
342
- return {
343
- url: this._getUrl(topic),
344
- requestId: topic,
345
- onRequestReceived: (callback) => this.onRequestReceivedCallbacks[topic].push(callback),
346
- onGeneratingProof: (callback) => this.onGeneratingProofCallbacks[topic].push(callback),
347
- onBridgeConnect: (callback) => this.onBridgeConnectCallbacks[topic].push(callback),
348
- onProofGenerated: (callback) => this.onProofGeneratedCallbacks[topic].push(callback),
349
- onResult: (callback) => this.onResultCallbacks[topic].push(callback),
350
- onReject: (callback) => this.onRejectCallbacks[topic].push(callback),
351
- onError: (callback) => this.onErrorCallbacks[topic].push(callback),
352
- isBridgeConnected: () => this.topicToBridge[topic].isBridgeConnected(),
353
- requestReceived: () => this.topicToRequestReceived[topic] === true,
354
- };
355
- },
356
- };
357
- }
358
- /**
359
- * @notice Create a new request
360
- * @param name Your service name
361
- * @param logo The logo of your service
362
- * @param purpose To explain what you want to do with the user's data
363
- * @param scope Scope this request to a specific use case
364
- * @param validity How many days ago should have the ID been last scanned by the user?
365
- * @param devMode Whether to enable dev mode. This will allow you to verify mock proofs (i.e. from ZKR)
366
- * @param evmChain The EVM chain to use for the request (if using the proof onchain)
367
- * @returns The query builder object.
368
- */
369
- async request({ name, logo, purpose, scope, mode, evmChain, validity, devMode, topicOverride, keyPairOverride, cloudProverUrl, bridgeUrl, }) {
370
- const bridge = await bridge_1.Bridge.create({
371
- keyPair: keyPairOverride,
372
- bridgeId: topicOverride,
373
- bridgeUrl,
374
- });
375
- const topic = bridge.connection.getBridgeId();
376
- this.topicToConfig[topic] = {};
377
- this.topicToService[topic] = {
378
- name,
379
- logo,
380
- purpose,
381
- scope,
382
- chainId: evmChain ? getChainIdFromEVMChain(evmChain) : undefined,
383
- cloudProverUrl,
384
- bridgeUrl,
385
- };
386
- this.topicToProofs[topic] = [];
387
- this.topicToExpectedProofCount[topic] = 0;
388
- this.topicToLocalConfig[topic] = {
389
- // Default to 6 months
390
- validity: validity || 6 * 30,
391
- mode: mode || "fast",
392
- devMode: devMode || false,
393
- };
394
- this.onRequestReceivedCallbacks[topic] = [];
395
- this.onGeneratingProofCallbacks[topic] = [];
396
- this.onBridgeConnectCallbacks[topic] = [];
397
- this.onProofGeneratedCallbacks[topic] = [];
398
- this.onResultCallbacks[topic] = [];
399
- this.onRejectCallbacks[topic] = [];
400
- this.onErrorCallbacks[topic] = [];
401
- this.topicToPublicKey[topic] = bridge.getPublicKey();
402
- this.topicToBridge[topic] = bridge;
403
- bridge.onConnect(async (reconnection) => {
404
- logger_1.noLogger.debug("Bridge connected");
405
- logger_1.noLogger.debug("Is reconnection:", reconnection);
406
- await Promise.all(this.onBridgeConnectCallbacks[topic].map((callback) => callback()));
407
- });
408
- bridge.onSecureChannelEstablished(async () => {
409
- logger_1.noLogger.debug("Secure channel established");
410
- await Promise.all(this.onRequestReceivedCallbacks[topic].map((callback) => callback()));
411
- });
412
- bridge.onSecureMessage(async (message) => {
413
- logger_1.noLogger.debug("Received message:", message);
414
- this.handleEncryptedMessage(topic, message);
415
- });
416
- return this.getZkPassportRequest(topic);
417
- }
418
- checkDiscloseBytesPublicInputs(proof, queryResult) {
419
- const queryResultErrors = {
420
- sig_check_dsc: {},
421
- sig_check_id_data: {},
422
- data_check_integrity: {},
423
- disclose: {},
424
- age: {},
425
- birthdate: {},
426
- expiry_date: {},
427
- document_type: {},
428
- issuing_country: {},
429
- gender: {},
430
- nationality: {},
431
- firstname: {},
432
- lastname: {},
433
- fullname: {},
434
- document_number: {},
435
- outer: {},
436
- bind: {},
437
- };
438
- let isCorrect = true;
439
- // We can't be certain that the disclosed data is for a passport or an ID card
440
- // so we need to check both (unless the document type is revealed)
441
- const disclosedDataPassport = utils_1.DisclosedData.fromDisclosedBytes((proof.committedInputs?.disclose_bytes).disclosedBytes, "passport");
442
- const disclosedDataIDCard = utils_1.DisclosedData.fromDisclosedBytes((proof.committedInputs?.disclose_bytes).disclosedBytes, "id_card");
443
- if (queryResult.document_type) {
444
- // Document type is always at the same index in the disclosed data
445
- if (queryResult.document_type.eq &&
446
- queryResult.document_type.eq.result &&
447
- queryResult.document_type.eq.expected !== disclosedDataPassport.documentType) {
448
- console.warn("Document type does not match the expected document type");
449
- isCorrect = false;
450
- queryResultErrors.document_type.eq = {
451
- expected: `${queryResult.document_type.eq.expected}`,
452
- received: `${disclosedDataPassport.documentType ?? disclosedDataIDCard.documentType}`,
453
- message: "Document type does not match the expected document type",
454
- };
455
- }
456
- if (queryResult.document_type.disclose?.result !== disclosedDataIDCard.documentType) {
457
- console.warn("Document type does not match the disclosed document type in query result");
458
- isCorrect = false;
459
- queryResultErrors.document_type.disclose = {
460
- expected: `${queryResult.document_type.disclose?.result}`,
461
- received: `${disclosedDataIDCard.documentType ?? disclosedDataPassport.documentType}`,
462
- message: "Document type does not match the disclosed document type in query result",
463
- };
464
- }
465
- }
466
- if (queryResult.birthdate) {
467
- const birthdatePassport = disclosedDataPassport.dateOfBirth;
468
- const birthdateIDCard = disclosedDataIDCard.dateOfBirth;
469
- if (queryResult.birthdate.eq &&
470
- queryResult.birthdate.eq.result &&
471
- queryResult.birthdate.eq.expected.getTime() !== birthdatePassport.getTime() &&
472
- queryResult.birthdate.eq.expected.getTime() !== birthdateIDCard.getTime()) {
473
- console.warn("Birthdate does not match the expected birthdate");
474
- isCorrect = false;
475
- queryResultErrors.birthdate.eq = {
476
- expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
477
- received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
478
- message: "Birthdate does not match the expected birthdate",
479
- };
480
- }
481
- if (queryResult.birthdate.disclose &&
482
- queryResult.birthdate.disclose.result.getTime() !== birthdatePassport.getTime() &&
483
- queryResult.birthdate.disclose.result.getTime() !== birthdateIDCard.getTime()) {
484
- console.warn("Birthdate does not match the disclosed birthdate in query result");
485
- isCorrect = false;
486
- queryResultErrors.birthdate.disclose = {
487
- expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
488
- received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
489
- message: "Birthdate does not match the disclosed birthdate in query result",
490
- };
491
- }
492
- }
493
- if (queryResult.expiry_date) {
494
- const expiryDatePassport = disclosedDataPassport.dateOfExpiry;
495
- const expiryDateIDCard = disclosedDataIDCard.dateOfExpiry;
496
- if (queryResult.expiry_date.eq &&
497
- queryResult.expiry_date.eq.result &&
498
- queryResult.expiry_date.eq.expected.getTime() !== expiryDatePassport.getTime() &&
499
- queryResult.expiry_date.eq.expected.getTime() !== expiryDateIDCard.getTime()) {
500
- console.warn("Expiry date does not match the expected expiry date");
501
- isCorrect = false;
502
- queryResultErrors.expiry_date.eq = {
503
- expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
504
- received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
505
- message: "Expiry date does not match the expected expiry date",
506
- };
507
- }
508
- if (queryResult.expiry_date.disclose &&
509
- queryResult.expiry_date.disclose.result.getTime() !== expiryDatePassport.getTime() &&
510
- queryResult.expiry_date.disclose.result.getTime() !== expiryDateIDCard.getTime()) {
511
- console.warn("Expiry date does not match the disclosed expiry date in query result");
512
- isCorrect = false;
513
- queryResultErrors.expiry_date.disclose = {
514
- expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
515
- received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
516
- message: "Expiry date does not match the disclosed expiry date in query result",
517
- };
518
- }
519
- }
520
- if (queryResult.nationality) {
521
- const nationalityPassport = disclosedDataPassport.nationality;
522
- const nationalityIDCard = disclosedDataIDCard.nationality;
523
- if (queryResult.nationality.eq &&
524
- queryResult.nationality.eq.result &&
525
- queryResult.nationality.eq.expected !== nationalityPassport &&
526
- queryResult.nationality.eq.expected !== nationalityIDCard) {
527
- console.warn("Nationality does not match the expected nationality");
528
- isCorrect = false;
529
- queryResultErrors.nationality.eq = {
530
- expected: `${queryResult.nationality.eq.expected}`,
531
- received: `${nationalityPassport ?? nationalityIDCard}`,
532
- message: "Nationality does not match the expected nationality",
533
- };
534
- }
535
- if (queryResult.nationality.disclose &&
536
- queryResult.nationality.disclose.result !== nationalityPassport &&
537
- queryResult.nationality.disclose.result !== nationalityIDCard) {
538
- console.warn("Nationality does not match the disclosed nationality in query result");
539
- isCorrect = false;
540
- queryResultErrors.nationality.disclose = {
541
- expected: `${queryResult.nationality.disclose.result}`,
542
- received: `${nationalityPassport ?? nationalityIDCard}`,
543
- message: "Nationality does not match the disclosed nationality in query result",
544
- };
545
- }
546
- }
547
- if (queryResult.document_number) {
548
- const documentNumberPassport = disclosedDataPassport.documentNumber;
549
- const documentNumberIDCard = disclosedDataIDCard.documentNumber;
550
- if (queryResult.document_number.eq &&
551
- queryResult.document_number.eq.result &&
552
- queryResult.document_number.eq.expected !== documentNumberPassport &&
553
- queryResult.document_number.eq.expected !== documentNumberIDCard) {
554
- console.warn("Document number does not match the expected document number");
555
- isCorrect = false;
556
- queryResultErrors.document_number.eq = {
557
- expected: `${queryResult.document_number.eq.expected}`,
558
- received: `${documentNumberPassport ?? documentNumberIDCard}`,
559
- message: "Document number does not match the expected document number",
560
- };
561
- }
562
- if (queryResult.document_number.disclose &&
563
- queryResult.document_number.disclose.result !== documentNumberPassport &&
564
- queryResult.document_number.disclose.result !== documentNumberIDCard) {
565
- console.warn("Document number does not match the disclosed document number in query result");
566
- isCorrect = false;
567
- queryResultErrors.document_number.disclose = {
568
- expected: `${queryResult.document_number.disclose.result}`,
569
- received: `${documentNumberPassport ?? documentNumberIDCard}`,
570
- message: "Document number does not match the disclosed document number in query result",
571
- };
572
- }
573
- }
574
- if (queryResult.gender) {
575
- const genderPassport = disclosedDataPassport.gender;
576
- const genderIDCard = disclosedDataIDCard.gender;
577
- if (queryResult.gender.eq &&
578
- queryResult.gender.eq.result &&
579
- queryResult.gender.eq.expected !== genderPassport &&
580
- queryResult.gender.eq.expected !== genderIDCard) {
581
- console.warn("Gender does not match the expected gender");
582
- isCorrect = false;
583
- queryResultErrors.gender.eq = {
584
- expected: `${queryResult.gender.eq.expected}`,
585
- received: `${genderPassport ?? genderIDCard}`,
586
- message: "Gender does not match the expected gender",
587
- };
588
- }
589
- if (queryResult.gender.disclose &&
590
- queryResult.gender.disclose.result !== genderPassport &&
591
- queryResult.gender.disclose.result !== genderIDCard) {
592
- console.warn("Gender does not match the disclosed gender in query result");
593
- isCorrect = false;
594
- queryResultErrors.gender.disclose = {
595
- expected: `${queryResult.gender.disclose.result}`,
596
- received: `${genderPassport ?? genderIDCard}`,
597
- message: "Gender does not match the disclosed gender in query result",
598
- };
599
- }
600
- }
601
- if (queryResult.issuing_country) {
602
- const issuingCountryPassport = disclosedDataPassport.issuingCountry;
603
- const issuingCountryIDCard = disclosedDataIDCard.issuingCountry;
604
- if (queryResult.issuing_country.eq &&
605
- queryResult.issuing_country.eq.result &&
606
- queryResult.issuing_country.eq.expected !== issuingCountryPassport &&
607
- queryResult.issuing_country.eq.expected !== issuingCountryIDCard) {
608
- console.warn("Issuing country does not match the expected issuing country");
609
- isCorrect = false;
610
- queryResultErrors.issuing_country.eq = {
611
- expected: `${queryResult.issuing_country.eq.expected}`,
612
- received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
613
- message: "Issuing country does not match the expected issuing country",
614
- };
615
- }
616
- if (queryResult.issuing_country.disclose &&
617
- queryResult.issuing_country.disclose.result !== issuingCountryPassport &&
618
- queryResult.issuing_country.disclose.result !== issuingCountryIDCard) {
619
- console.warn("Issuing country does not match the disclosed issuing country in query result");
620
- isCorrect = false;
621
- queryResultErrors.issuing_country.disclose = {
622
- expected: `${queryResult.issuing_country.disclose.result}`,
623
- received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
624
- message: "Issuing country does not match the disclosed issuing country in query result",
625
- };
626
- }
627
- }
628
- if (queryResult.fullname) {
629
- const fullnamePassport = disclosedDataPassport.name;
630
- const fullnameIDCard = disclosedDataIDCard.name;
631
- if (queryResult.fullname.eq &&
632
- queryResult.fullname.eq.result &&
633
- (0, utils_1.formatName)(queryResult.fullname.eq.expected).toLowerCase() !==
634
- fullnamePassport.toLowerCase() &&
635
- (0, utils_1.formatName)(queryResult.fullname.eq.expected).toLowerCase() !== fullnameIDCard.toLowerCase()) {
636
- console.warn("Fullname does not match the expected fullname");
637
- isCorrect = false;
638
- queryResultErrors.fullname.eq = {
639
- expected: `${queryResult.fullname.eq.expected}`,
640
- received: `${fullnamePassport ?? fullnameIDCard}`,
641
- message: "Fullname does not match the expected fullname",
642
- };
643
- }
644
- if (queryResult.fullname.disclose &&
645
- (0, utils_1.formatName)(queryResult.fullname.disclose.result).toLowerCase() !==
646
- fullnamePassport.toLowerCase() &&
647
- (0, utils_1.formatName)(queryResult.fullname.disclose.result).toLowerCase() !==
648
- fullnameIDCard.toLowerCase()) {
649
- console.warn("Fullname does not match the disclosed fullname in query result");
650
- isCorrect = false;
651
- queryResultErrors.fullname.disclose = {
652
- expected: `${queryResult.fullname.disclose.result}`,
653
- received: `${fullnamePassport ?? fullnameIDCard}`,
654
- message: "Fullname does not match the disclosed fullname in query result",
655
- };
656
- }
657
- }
658
- if (queryResult.firstname) {
659
- // If fullname was not revealed, then the name could be either the first name or last name
660
- const firstnamePassport = disclosedDataPassport.firstName && disclosedDataPassport.firstName.length > 0
661
- ? disclosedDataPassport.firstName
662
- : disclosedDataPassport.name;
663
- const firstnameIDCard = disclosedDataIDCard.firstName && disclosedDataIDCard.firstName.length > 0
664
- ? disclosedDataIDCard.firstName
665
- : disclosedDataIDCard.name;
666
- if (queryResult.firstname.eq &&
667
- queryResult.firstname.eq.result &&
668
- (0, utils_1.formatName)(queryResult.firstname.eq.expected).toLowerCase() !==
669
- firstnamePassport.toLowerCase() &&
670
- (0, utils_1.formatName)(queryResult.firstname.eq.expected).toLowerCase() !==
671
- firstnameIDCard.toLowerCase()) {
672
- console.warn("Firstname does not match the expected firstname");
673
- isCorrect = false;
674
- queryResultErrors.firstname.eq = {
675
- expected: `${queryResult.firstname.eq.expected}`,
676
- received: `${firstnamePassport ?? firstnameIDCard}`,
677
- message: "Firstname does not match the expected firstname",
678
- };
679
- }
680
- if (queryResult.firstname.disclose &&
681
- (0, utils_1.formatName)(queryResult.firstname.disclose.result).toLowerCase() !==
682
- firstnamePassport.toLowerCase() &&
683
- (0, utils_1.formatName)(queryResult.firstname.disclose.result).toLowerCase() !==
684
- firstnameIDCard.toLowerCase()) {
685
- console.warn("Firstname does not match the disclosed firstname in query result");
686
- isCorrect = false;
687
- queryResultErrors.firstname.disclose = {
688
- expected: `${queryResult.firstname.disclose.result}`,
689
- received: `${firstnamePassport ?? firstnameIDCard}`,
690
- message: "Firstname does not match the disclosed firstname in query result",
691
- };
692
- }
693
- }
694
- if (queryResult.lastname) {
695
- // If fullname was not revealed, then the name could be either the first name or last name
696
- const lastnamePassport = disclosedDataPassport.lastName && disclosedDataPassport.lastName.length > 0
697
- ? disclosedDataPassport.lastName
698
- : disclosedDataPassport.name;
699
- const lastnameIDCard = disclosedDataIDCard.lastName && disclosedDataIDCard.lastName.length > 0
700
- ? disclosedDataIDCard.lastName
701
- : disclosedDataIDCard.name;
702
- if (queryResult.lastname.eq &&
703
- queryResult.lastname.eq.result &&
704
- (0, utils_1.formatName)(queryResult.lastname.eq.expected).toLowerCase() !==
705
- lastnamePassport.toLowerCase() &&
706
- (0, utils_1.formatName)(queryResult.lastname.eq.expected).toLowerCase() !== lastnameIDCard.toLowerCase()) {
707
- console.warn("Lastname does not match the expected lastname");
708
- isCorrect = false;
709
- queryResultErrors.lastname.eq = {
710
- expected: `${queryResult.lastname.eq.expected}`,
711
- received: `${lastnamePassport ?? lastnameIDCard}`,
712
- message: "Lastname does not match the expected lastname",
713
- };
714
- }
715
- if (queryResult.lastname.disclose &&
716
- (0, utils_1.formatName)(queryResult.lastname.disclose.result).toLowerCase() !==
717
- lastnamePassport.toLowerCase() &&
718
- (0, utils_1.formatName)(queryResult.lastname.disclose.result).toLowerCase() !==
719
- lastnameIDCard.toLowerCase()) {
720
- console.warn("Lastname does not match the disclosed lastname in query result");
721
- isCorrect = false;
722
- queryResultErrors.lastname.disclose = {
723
- expected: `${queryResult.lastname.disclose.result}`,
724
- received: `${lastnamePassport ?? lastnameIDCard}`,
725
- message: "Lastname does not match the disclosed lastname in query result",
726
- };
727
- }
728
- }
729
- return { isCorrect, queryResultErrors };
730
- }
731
- checkAgePublicInputs(proof, queryResult) {
732
- const queryResultErrors = {
733
- sig_check_dsc: {},
734
- sig_check_id_data: {},
735
- data_check_integrity: {},
736
- disclose: {},
737
- age: {},
738
- birthdate: {},
739
- expiry_date: {},
740
- document_type: {},
741
- issuing_country: {},
742
- gender: {},
743
- nationality: {},
744
- firstname: {},
745
- lastname: {},
746
- fullname: {},
747
- document_number: {},
748
- outer: {},
749
- bind: {},
750
- };
751
- let isCorrect = true;
752
- const currentTime = new Date();
753
- const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0, 0);
754
- const minAge = (0, utils_1.getMinAgeFromCommittedInputs)(proof.committedInputs?.compare_age);
755
- const maxAge = (0, utils_1.getMaxAgeFromCommittedInputs)(proof.committedInputs?.compare_age);
756
- if (queryResult.age) {
757
- if (queryResult.age.gte &&
758
- queryResult.age.gte.result &&
759
- minAge !== queryResult.age.gte.expected) {
760
- console.warn("Age is not greater than or equal to the expected age");
761
- isCorrect = false;
762
- queryResultErrors.age.gte = {
763
- expected: queryResult.age.gte.expected,
764
- received: minAge,
765
- message: "Age is not greater than or equal to the expected age",
766
- };
767
- }
768
- if (queryResult.age.lt &&
769
- queryResult.age.lt.result &&
770
- maxAge !== queryResult.age.lt.expected) {
771
- console.warn("Age is not less than the expected age");
772
- isCorrect = false;
773
- queryResultErrors.age.lt = {
774
- expected: queryResult.age.lt.expected,
775
- received: maxAge,
776
- message: "Age is not less than the expected age",
777
- };
778
- }
779
- if (queryResult.age.range) {
780
- if (queryResult.age.range.result &&
781
- (minAge !== queryResult.age.range.expected[0] ||
782
- maxAge !== queryResult.age.range.expected[1])) {
783
- console.warn("Age is not in the expected range");
784
- isCorrect = false;
785
- queryResultErrors.age.range = {
786
- expected: queryResult.age.range.expected,
787
- received: [minAge, maxAge],
788
- message: "Age is not in the expected range",
789
- };
790
- }
791
- }
792
- if (!queryResult.age.lt && !queryResult.age.range && maxAge != 0) {
793
- console.warn("Maximum age should be equal to 0");
794
- isCorrect = false;
795
- queryResultErrors.age.disclose = {
796
- expected: 0,
797
- received: maxAge,
798
- message: "Maximum age should be equal to 0",
799
- };
800
- }
801
- if (!queryResult.age.gte && !queryResult.age.range && minAge != 0) {
802
- console.warn("Minimum age should be equal to 0");
803
- isCorrect = false;
804
- queryResultErrors.age.disclose = {
805
- expected: 0,
806
- received: minAge,
807
- message: "Minimum age should be equal to 0",
808
- };
809
- }
810
- if (queryResult.age.disclose &&
811
- (queryResult.age.disclose.result !== minAge || queryResult.age.disclose.result !== maxAge)) {
812
- console.warn("Age does not match the disclosed age in query result");
813
- isCorrect = false;
814
- queryResultErrors.age.disclose = {
815
- expected: `${minAge}`,
816
- received: `${queryResult.age.disclose.result}`,
817
- message: "Age does not match the disclosed age in query result",
818
- };
819
- }
820
- }
821
- else {
822
- console.warn("Age is not set in the query result");
823
- isCorrect = false;
824
- queryResultErrors.age.disclose = {
825
- message: "Age is not set in the query result",
826
- };
827
- }
828
- const currentDate = (0, utils_1.getCurrentDateFromCommittedInputs)(proof.committedInputs?.compare_age);
829
- if (currentDate.getTime() !== today.getTime() &&
830
- currentDate.getTime() !== today.getTime() - 86400000) {
831
- console.warn("Current date in the proof is too old");
832
- isCorrect = false;
833
- queryResultErrors.age.disclose = {
834
- expected: `${today.toISOString()}`,
835
- received: `${currentDate.toISOString()}`,
836
- message: "Current date in the proof is too old",
837
- };
838
- }
839
- return { isCorrect, queryResultErrors };
840
- }
841
- checkBirthdatePublicInputs(proof, queryResult) {
842
- const queryResultErrors = {
843
- sig_check_dsc: {},
844
- sig_check_id_data: {},
845
- data_check_integrity: {},
846
- disclose: {},
847
- age: {},
848
- birthdate: {},
849
- expiry_date: {},
850
- document_type: {},
851
- issuing_country: {},
852
- gender: {},
853
- nationality: {},
854
- firstname: {},
855
- lastname: {},
856
- fullname: {},
857
- document_number: {},
858
- outer: {},
859
- bind: {},
860
- };
861
- let isCorrect = true;
862
- const currentTime = new Date();
863
- const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0);
864
- const minDate = (0, utils_1.getMinDateFromCommittedInputs)(proof.committedInputs?.compare_birthdate);
865
- const maxDate = (0, utils_1.getMaxDateFromCommittedInputs)(proof.committedInputs?.compare_birthdate);
866
- const currentDate = (0, utils_1.getCurrentDateFromCommittedInputs)(proof.committedInputs?.compare_birthdate);
867
- if (queryResult.birthdate) {
868
- if (queryResult.birthdate.gte &&
869
- queryResult.birthdate.gte.result &&
870
- minDate !== queryResult.birthdate.gte.expected) {
871
- console.warn("Birthdate is not greater than or equal to the expected birthdate");
872
- isCorrect = false;
873
- queryResultErrors.birthdate.gte = {
874
- expected: queryResult.birthdate.gte.expected,
875
- received: minDate,
876
- message: "Birthdate is not greater than or equal to the expected birthdate",
877
- };
878
- }
879
- if (queryResult.birthdate.lte &&
880
- queryResult.birthdate.lte.result &&
881
- maxDate !== queryResult.birthdate.lte.expected) {
882
- console.warn("Birthdate is not less than the expected birthdate");
883
- isCorrect = false;
884
- queryResultErrors.birthdate.lte = {
885
- expected: queryResult.birthdate.lte.expected,
886
- received: maxDate,
887
- message: "Birthdate is not less than the expected birthdate",
888
- };
889
- }
890
- if (queryResult.birthdate.range) {
891
- if (queryResult.birthdate.range.result &&
892
- (minDate !== queryResult.birthdate.range.expected[0] ||
893
- maxDate !== queryResult.birthdate.range.expected[1])) {
894
- console.warn("Birthdate is not in the expected range");
895
- isCorrect = false;
896
- queryResultErrors.birthdate.range = {
897
- expected: queryResult.birthdate.range.expected,
898
- received: [minDate, maxDate],
899
- message: "Birthdate is not in the expected range",
900
- };
901
- }
902
- }
903
- if (!queryResult.birthdate.lte &&
904
- !queryResult.birthdate.range &&
905
- maxDate.getTime() != DEFAULT_DATE_VALUE.getTime()) {
906
- console.warn("Maximum birthdate should be equal to default date value");
907
- isCorrect = false;
908
- queryResultErrors.birthdate.disclose = {
909
- expected: `${DEFAULT_DATE_VALUE.toISOString()}`,
910
- received: `${maxDate.toISOString()}`,
911
- message: "Maximum birthdate should be equal to default date value",
912
- };
913
- }
914
- if (!queryResult.birthdate.gte &&
915
- !queryResult.birthdate.range &&
916
- minDate.getTime() != DEFAULT_DATE_VALUE.getTime()) {
917
- console.warn("Minimum birthdate should be equal to default date value");
918
- isCorrect = false;
919
- queryResultErrors.birthdate.disclose = {
920
- expected: `${DEFAULT_DATE_VALUE.toISOString()}`,
921
- received: `${minDate.toISOString()}`,
922
- message: "Minimum birthdate should be equal to default date value",
923
- };
924
- }
925
- }
926
- else {
927
- console.warn("Birthdate is not set in the query result");
928
- isCorrect = false;
929
- queryResultErrors.birthdate.disclose = {
930
- message: "Birthdate is not set in the query result",
931
- };
932
- }
933
- if (currentDate.getTime() !== today.getTime() &&
934
- currentDate.getTime() !== today.getTime() - 86400000) {
935
- console.warn("Current date in the proof is too old");
936
- isCorrect = false;
937
- queryResultErrors.age.disclose = {
938
- expected: `${today.toISOString()}`,
939
- received: `${currentDate.toISOString()}`,
940
- message: "Current date in the proof is too old",
941
- };
942
- }
943
- return { isCorrect, queryResultErrors };
944
- }
945
- checkExpiryDatePublicInputs(proof, queryResult) {
946
- const queryResultErrors = {
947
- sig_check_dsc: {},
948
- sig_check_id_data: {},
949
- data_check_integrity: {},
950
- disclose: {},
951
- age: {},
952
- birthdate: {},
953
- expiry_date: {},
954
- document_type: {},
955
- issuing_country: {},
956
- gender: {},
957
- nationality: {},
958
- firstname: {},
959
- lastname: {},
960
- fullname: {},
961
- document_number: {},
962
- outer: {},
963
- bind: {},
964
- };
965
- let isCorrect = true;
966
- const currentTime = new Date();
967
- const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0);
968
- const minDate = (0, utils_1.getMinDateFromCommittedInputs)(proof.committedInputs?.compare_expiry);
969
- const maxDate = (0, utils_1.getMaxDateFromCommittedInputs)(proof.committedInputs?.compare_expiry);
970
- const currentDate = (0, utils_1.getCurrentDateFromCommittedInputs)(proof.committedInputs?.compare_expiry);
971
- if (queryResult.expiry_date) {
972
- if (queryResult.expiry_date.gte &&
973
- queryResult.expiry_date.gte.result &&
974
- minDate !== queryResult.expiry_date.gte.expected) {
975
- console.warn("Expiry date is not greater than or equal to the expected expiry date");
976
- isCorrect = false;
977
- queryResultErrors.expiry_date.gte = {
978
- expected: queryResult.expiry_date.gte.expected,
979
- received: minDate,
980
- message: "Expiry date is not greater than or equal to the expected expiry date",
981
- };
982
- }
983
- if (queryResult.expiry_date.lte &&
984
- queryResult.expiry_date.lte.result &&
985
- maxDate !== queryResult.expiry_date.lte.expected) {
986
- console.warn("Expiry date is not less than the expected expiry date");
987
- isCorrect = false;
988
- queryResultErrors.expiry_date.lte = {
989
- expected: queryResult.expiry_date.lte.expected,
990
- received: maxDate,
991
- message: "Expiry date is not less than the expected expiry date",
992
- };
993
- }
994
- if (queryResult.expiry_date.range) {
995
- if (queryResult.expiry_date.range.result &&
996
- (minDate !== queryResult.expiry_date.range.expected[0] ||
997
- maxDate !== queryResult.expiry_date.range.expected[1])) {
998
- console.warn("Expiry date is not in the expected range");
999
- isCorrect = false;
1000
- queryResultErrors.expiry_date.range = {
1001
- expected: queryResult.expiry_date.range.expected,
1002
- received: [minDate, maxDate],
1003
- message: "Expiry date is not in the expected range",
1004
- };
1005
- }
1006
- }
1007
- if (!queryResult.expiry_date.lte &&
1008
- !queryResult.expiry_date.range &&
1009
- maxDate.getTime() != DEFAULT_DATE_VALUE.getTime()) {
1010
- console.warn("Maximum expiry date should be equal to default date value");
1011
- isCorrect = false;
1012
- queryResultErrors.expiry_date.disclose = {
1013
- expected: `${DEFAULT_DATE_VALUE.toISOString()}`,
1014
- received: `${maxDate.toISOString()}`,
1015
- message: "Maximum expiry date should be equal to default date value",
1016
- };
1017
- }
1018
- if (!queryResult.expiry_date.gte &&
1019
- !queryResult.expiry_date.range &&
1020
- minDate.getTime() != DEFAULT_DATE_VALUE.getTime()) {
1021
- console.warn("Minimum expiry date should be equal to default date value");
1022
- isCorrect = false;
1023
- queryResultErrors.expiry_date.disclose = {
1024
- expected: `${DEFAULT_DATE_VALUE.toISOString()}`,
1025
- received: `${minDate.toISOString()}`,
1026
- message: "Minimum expiry date should be equal to default date value",
1027
- };
1028
- }
1029
- }
1030
- else {
1031
- console.warn("Expiry date is not set in the query result");
1032
- isCorrect = false;
1033
- queryResultErrors.expiry_date.disclose = {
1034
- message: "Expiry date is not set in the query result",
1035
- };
1036
- }
1037
- if (currentDate.getTime() !== today.getTime() &&
1038
- currentDate.getTime() !== today.getTime() - 86400000) {
1039
- console.warn("Current date in the proof is too old");
1040
- isCorrect = false;
1041
- queryResultErrors.age.disclose = {
1042
- expected: `${today.toISOString()}`,
1043
- received: `${currentDate.toISOString()}`,
1044
- message: "Current date in the proof is too old",
1045
- };
1046
- }
1047
- return { isCorrect, queryResultErrors };
1048
- }
1049
- checkNationalityExclusionPublicInputs(queryResult, countryList) {
1050
- const queryResultErrors = {
1051
- sig_check_dsc: {},
1052
- sig_check_id_data: {},
1053
- data_check_integrity: {},
1054
- disclose: {},
1055
- age: {},
1056
- birthdate: {},
1057
- expiry_date: {},
1058
- document_type: {},
1059
- issuing_country: {},
1060
- gender: {},
1061
- nationality: {},
1062
- firstname: {},
1063
- lastname: {},
1064
- fullname: {},
1065
- document_number: {},
1066
- outer: {},
1067
- bind: {},
1068
- };
1069
- let isCorrect = true;
1070
- if (queryResult.nationality &&
1071
- queryResult.nationality.out &&
1072
- queryResult.nationality.out.result) {
1073
- if (!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))) {
1074
- console.warn("Nationality exclusion list does not match the one from the query results");
1075
- isCorrect = false;
1076
- queryResultErrors.nationality.out = {
1077
- expected: queryResult.nationality.out.expected,
1078
- received: countryList,
1079
- message: "Nationality exclusion list does not match the one from the query results",
1080
- };
1081
- }
1082
- }
1083
- else if (!queryResult.nationality || !queryResult.nationality.out) {
1084
- console.warn("Nationality exclusion is not set in the query result");
1085
- isCorrect = false;
1086
- queryResultErrors.nationality.out = {
1087
- message: "Nationality exclusion is not set in the query result",
1088
- };
1089
- }
1090
- // Check the countryList is in ascending order
1091
- // If the prover doesn't use a sorted list then the proof cannot be trusted
1092
- // as it is requirement in the circuit for the exclusion check to work
1093
- for (let i = 1; i < countryList.length; i++) {
1094
- if (countryList[i] < countryList[i - 1]) {
1095
- console.warn("The nationality exclusion list has not been sorted, and thus the proof cannot be trusted");
1096
- isCorrect = false;
1097
- queryResultErrors.nationality.out = {
1098
- message: "The nationality exclusion list has not been sorted, and thus the proof cannot be trusted",
1099
- };
1100
- }
1101
- }
1102
- return { isCorrect, queryResultErrors };
1103
- }
1104
- checkIssuingCountryExclusionPublicInputs(queryResult, countryList) {
1105
- const queryResultErrors = {
1106
- sig_check_dsc: {},
1107
- sig_check_id_data: {},
1108
- data_check_integrity: {},
1109
- disclose: {},
1110
- age: {},
1111
- birthdate: {},
1112
- expiry_date: {},
1113
- document_type: {},
1114
- issuing_country: {},
1115
- gender: {},
1116
- nationality: {},
1117
- firstname: {},
1118
- lastname: {},
1119
- fullname: {},
1120
- document_number: {},
1121
- outer: {},
1122
- bind: {},
1123
- };
1124
- let isCorrect = true;
1125
- if (queryResult.issuing_country &&
1126
- queryResult.issuing_country.out &&
1127
- queryResult.issuing_country.out.result) {
1128
- if (!queryResult.issuing_country.out.expected?.every((country) => countryList.includes(country))) {
1129
- console.warn("Issuing country exclusion list does not match the one from the query results");
1130
- isCorrect = false;
1131
- queryResultErrors.issuing_country.out = {
1132
- expected: queryResult.issuing_country.out.expected,
1133
- received: countryList,
1134
- message: "Issuing country exclusion list does not match the one from the query results",
1135
- };
1136
- }
1137
- }
1138
- else if (!queryResult.issuing_country || !queryResult.issuing_country.out) {
1139
- console.warn("Issuing country exclusion is not set in the query result");
1140
- isCorrect = false;
1141
- queryResultErrors.issuing_country.out = {
1142
- message: "Issuing country exclusion is not set in the query result",
1143
- };
1144
- }
1145
- // Check the countryList is in ascending order
1146
- // If the prover doesn't use a sorted list then the proof cannot be trusted
1147
- // as it is requirement in the circuit for the exclusion check to work
1148
- for (let i = 1; i < countryList.length; i++) {
1149
- if (countryList[i] < countryList[i - 1]) {
1150
- console.warn("The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted");
1151
- isCorrect = false;
1152
- queryResultErrors.issuing_country.out = {
1153
- message: "The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
1154
- };
1155
- }
1156
- }
1157
- return { isCorrect, queryResultErrors };
1158
- }
1159
- checkNationalityInclusionPublicInputs(queryResult, countryList) {
1160
- const queryResultErrors = {
1161
- sig_check_dsc: {},
1162
- sig_check_id_data: {},
1163
- data_check_integrity: {},
1164
- disclose: {},
1165
- age: {},
1166
- birthdate: {},
1167
- expiry_date: {},
1168
- document_type: {},
1169
- issuing_country: {},
1170
- gender: {},
1171
- nationality: {},
1172
- firstname: {},
1173
- lastname: {},
1174
- fullname: {},
1175
- document_number: {},
1176
- outer: {},
1177
- bind: {},
1178
- };
1179
- let isCorrect = true;
1180
- if (queryResult.nationality &&
1181
- queryResult.nationality.in &&
1182
- queryResult.nationality.in.result) {
1183
- if (!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))) {
1184
- console.warn("Nationality inclusion list does not match the one from the query results");
1185
- isCorrect = false;
1186
- queryResultErrors.nationality.in = {
1187
- expected: queryResult.nationality.in.expected,
1188
- received: countryList,
1189
- message: "Nationality inclusion list does not match the one from the query results",
1190
- };
1191
- }
1192
- }
1193
- else if (!queryResult.nationality || !queryResult.nationality.in) {
1194
- console.warn("Nationality inclusion is not set in the query result");
1195
- isCorrect = false;
1196
- queryResultErrors.nationality.in = {
1197
- message: "Nationality inclusion is not set in the query result",
1198
- };
1199
- }
1200
- return { isCorrect, queryResultErrors };
1201
- }
1202
- checkIssuingCountryInclusionPublicInputs(queryResult, countryList) {
1203
- const queryResultErrors = {
1204
- sig_check_dsc: {},
1205
- sig_check_id_data: {},
1206
- data_check_integrity: {},
1207
- disclose: {},
1208
- age: {},
1209
- birthdate: {},
1210
- expiry_date: {},
1211
- document_type: {},
1212
- issuing_country: {},
1213
- gender: {},
1214
- nationality: {},
1215
- firstname: {},
1216
- lastname: {},
1217
- fullname: {},
1218
- document_number: {},
1219
- outer: {},
1220
- bind: {},
1221
- };
1222
- let isCorrect = true;
1223
- if (queryResult.issuing_country &&
1224
- queryResult.issuing_country.in &&
1225
- queryResult.issuing_country.in.result) {
1226
- if (!queryResult.issuing_country.in.expected?.every((country) => countryList.includes(country))) {
1227
- console.warn("Issuing country inclusion list does not match the one from the query results");
1228
- isCorrect = false;
1229
- queryResultErrors.issuing_country.in = {
1230
- expected: queryResult.issuing_country.in.expected,
1231
- received: countryList,
1232
- message: "Issuing country inclusion list does not match the one from the query results",
1233
- };
1234
- }
1235
- }
1236
- else if (!queryResult.issuing_country || !queryResult.issuing_country.in) {
1237
- console.warn("Issuing country inclusion is not set in the query result");
1238
- isCorrect = false;
1239
- queryResultErrors.issuing_country.in = {
1240
- message: "Issuing country inclusion is not set in the query result",
1241
- };
1242
- }
1243
- return { isCorrect, queryResultErrors };
1244
- }
1245
- checkScopeFromDisclosureProof(proofData, queryResultErrors, key, scope, chainId) {
1246
- let isCorrect = true;
1247
- if (this.domain &&
1248
- (0, utils_1.getServiceScopeHash)(this.domain, chainId) !== BigInt(proofData.publicInputs[1])) {
1249
- console.warn("The proof comes from a different domain than the one expected");
1250
- isCorrect = false;
1251
- queryResultErrors[key].scope = {
1252
- expected: `Scope: ${(0, utils_1.getServiceScopeHash)(this.domain, chainId).toString()}`,
1253
- received: `Scope: ${BigInt(proofData.publicInputs[1]).toString()}`,
1254
- message: "The proof comes from a different domain than the one expected",
1255
- };
1256
- }
1257
- if (scope && (0, utils_1.getScopeHash)(scope) !== BigInt(proofData.publicInputs[2])) {
1258
- console.warn("The proof uses a different scope than the one expected");
1259
- isCorrect = false;
1260
- queryResultErrors[key].scope = {
1261
- expected: `Scope: ${(0, utils_1.getScopeHash)(scope).toString()}`,
1262
- received: `Scope: ${BigInt(proofData.publicInputs[2]).toString()}`,
1263
- message: "The proof uses a different scope than the one expected",
1264
- };
1265
- }
1266
- return { isCorrect, queryResultErrors };
1267
- }
1268
- async checkCertificateRegistryRoot(root, queryResultErrors, outer) {
1269
- let isCorrect = true;
1270
- try {
1271
- // Maintained certificate registry settled onchain
1272
- // Here we use Ethereum Sepolia
1273
- const registryClient = new registry_1.RegistryClient({ chainId: 11155111 });
1274
- const isValid = await registryClient.isCertificateRootValid(root);
1275
- if (!isValid) {
1276
- console.warn("The ID was signed by an unrecognized root certificate");
1277
- isCorrect = false;
1278
- queryResultErrors[outer ? "outer" : "sig_check_dsc"].certificate = {
1279
- expected: `A valid root from ZKPassport Registry`,
1280
- received: `Got invalid certificate registry root: ${root}`,
1281
- message: "The ID was signed by an unrecognized root certificate",
1282
- };
1283
- }
1284
- }
1285
- catch (error) {
1286
- console.warn(error);
1287
- console.warn("The ID was signed by an unrecognized root certificate");
1288
- isCorrect = false;
1289
- queryResultErrors[outer ? "outer" : "sig_check_dsc"].certificate = {
1290
- expected: `A valid root from ZKPassport Registry`,
1291
- received: `Got invalid certificate registry root: ${root}`,
1292
- message: "The ID was signed by an unrecognized root certificate",
1293
- };
1294
- }
1295
- return { isCorrect, queryResultErrors };
1296
- }
1297
- async checkCircuitRegistryRoot(root, queryResultErrors) {
1298
- let isCorrect = true;
1299
- try {
1300
- const registryClient = new registry_1.RegistryClient({ chainId: 11155111 });
1301
- const isValid = await registryClient.isCircuitRootValid(root);
1302
- if (!isValid) {
1303
- console.warn("The proof uses unrecognized circuits");
1304
- isCorrect = false;
1305
- queryResultErrors.outer.circuit = {
1306
- expected: `A valid circuit from ZKPassport Registry`,
1307
- received: `Got invalid circuit registry root: ${root}`,
1308
- message: "The proof uses an unrecognized circuit",
1309
- };
1310
- }
1311
- }
1312
- catch (error) {
1313
- console.warn(error);
1314
- console.warn("The proof uses unrecognized circuits");
1315
- isCorrect = false;
1316
- queryResultErrors.outer.circuit = {
1317
- expected: `A valid circuit from ZKPassport Registry`,
1318
- received: `Got invalid circuit registry root: ${root}`,
1319
- message: "The proof uses an unrecognized circuit",
1320
- };
1321
- }
1322
- return { isCorrect, queryResultErrors };
1323
- }
1324
- checkBindPublicInputs(queryResult, boundData) {
1325
- const queryResultErrors = {
1326
- sig_check_dsc: {},
1327
- sig_check_id_data: {},
1328
- data_check_integrity: {},
1329
- disclose: {},
1330
- age: {},
1331
- birthdate: {},
1332
- expiry_date: {},
1333
- document_type: {},
1334
- issuing_country: {},
1335
- gender: {},
1336
- nationality: {},
1337
- firstname: {},
1338
- lastname: {},
1339
- fullname: {},
1340
- document_number: {},
1341
- outer: {},
1342
- bind: {},
1343
- };
1344
- let isCorrect = true;
1345
- if (queryResult.bind) {
1346
- if (queryResult.bind.user_address?.toLowerCase().replace("0x", "") !==
1347
- boundData.user_address?.toLowerCase().replace("0x", "")) {
1348
- console.warn("Bound user address does not match the one from the query results");
1349
- isCorrect = false;
1350
- queryResultErrors.bind.eq = {
1351
- expected: queryResult.bind.user_address,
1352
- received: boundData.user_address,
1353
- message: "Bound user address does not match the one from the query results",
1354
- };
1355
- }
1356
- if (queryResult.bind.custom_data?.trim().toLowerCase() !==
1357
- boundData.custom_data?.trim().toLowerCase()) {
1358
- console.warn("Bound custom data does not match the one from the query results");
1359
- isCorrect = false;
1360
- queryResultErrors.bind.eq = {
1361
- expected: queryResult.bind.custom_data,
1362
- received: boundData.custom_data,
1363
- message: "Bound custom data does not match the one from the query results",
1364
- };
1365
- }
1366
- }
1367
- return { isCorrect, queryResultErrors };
1368
- }
1369
- async checkPublicInputs(proofs, queryResult, validity, scope, chainId) {
1370
- let commitmentIn;
1371
- let commitmentOut;
1372
- let isCorrect = true;
1373
- let uniqueIdentifier;
1374
- const currentTime = new Date();
1375
- const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0, 0);
1376
- let queryResultErrors = {
1377
- sig_check_dsc: {},
1378
- sig_check_id_data: {},
1379
- data_check_integrity: {},
1380
- disclose: {},
1381
- age: {},
1382
- birthdate: {},
1383
- expiry_date: {},
1384
- document_type: {},
1385
- issuing_country: {},
1386
- gender: {},
1387
- nationality: {},
1388
- firstname: {},
1389
- lastname: {},
1390
- fullname: {},
1391
- document_number: {},
1392
- outer: {},
1393
- bind: {},
1394
- };
1395
- // Since the order is important for the commitments, we need to sort the proofs
1396
- // by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
1397
- const sortedProofs = proofs.sort((a, b) => {
1398
- const proofOrder = [
1399
- "sig_check_dsc",
1400
- "sig_check_id_data",
1401
- "data_check_integrity",
1402
- "disclose_bytes",
1403
- "compare_age",
1404
- "compare_birthdate",
1405
- "compare_expiry",
1406
- "exclusion_check_nationality",
1407
- "inclusion_check_nationality",
1408
- "exclusion_check_issuing_country",
1409
- "inclusion_check_issuing_country",
1410
- "bind",
1411
- ];
1412
- const getIndex = (proof) => {
1413
- const name = proof.name || "";
1414
- return proofOrder.findIndex((p) => name.startsWith(p));
1415
- };
1416
- return getIndex(a) - getIndex(b);
1417
- });
1418
- for (const proof of sortedProofs) {
1419
- const proofData = (0, utils_1.getProofData)(proof.proof, (0, utils_1.getNumberOfPublicInputs)(proof.name));
1420
- if (proof.name?.startsWith("outer")) {
1421
- const isForEVM = proof.name?.startsWith("outer_evm");
1422
- const certificateRegistryRoot = (0, utils_1.getCertificateRegistryRootFromOuterProof)(proofData);
1423
- const { isCorrect: isCorrectCertificateRegistryRoot, queryResultErrors: queryResultErrorsCertificateRegistryRoot, } = await this.checkCertificateRegistryRoot(certificateRegistryRoot.toString(16), queryResultErrors, true);
1424
- isCorrect = isCorrect && isCorrectCertificateRegistryRoot;
1425
- queryResultErrors = {
1426
- ...queryResultErrors,
1427
- ...queryResultErrorsCertificateRegistryRoot,
1428
- };
1429
- const circuitRegistryRoot = (0, utils_1.getCircuitRegistryRootFromOuterProof)(proofData);
1430
- const { isCorrect: isCorrectCircuitRegistryRoot, queryResultErrors: queryResultErrorsCircuitRegistryRoot, } = await this.checkCircuitRegistryRoot(circuitRegistryRoot.toString(16), queryResultErrors);
1431
- isCorrect = isCorrect && isCorrectCircuitRegistryRoot;
1432
- queryResultErrors = {
1433
- ...queryResultErrors,
1434
- ...queryResultErrorsCircuitRegistryRoot,
1435
- };
1436
- const currentDate = (0, utils_1.getCurrentDateFromOuterProof)(proofData);
1437
- const todayToCurrentDate = today.getTime() - currentDate.getTime();
1438
- const differenceInDays = validity ?? 180;
1439
- const expectedDifference = differenceInDays * 86400000;
1440
- const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
1441
- // The ID should not expire within the next 6 months (or whatever the custom value is)
1442
- if (todayToCurrentDate >= actualDifference) {
1443
- console.warn(`The date used to check the validity of the ID is older than ${differenceInDays} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
1444
- isCorrect = false;
1445
- queryResultErrors.outer.date = {
1446
- expected: `Difference: ${differenceInDays} days`,
1447
- received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
1448
- message: "The date used to check the validity of the ID is older than the validity period",
1449
- };
1450
- }
1451
- const paramCommitments = (0, utils_1.getParamCommitmentsFromOuterProof)(proofData);
1452
- const committedInputs = proof.committedInputs;
1453
- const keysInCommittedInputs = Object.keys(committedInputs || {});
1454
- if (keysInCommittedInputs.length !== paramCommitments.length) {
1455
- console.warn("The proof does not verify all the requested conditions and information");
1456
- isCorrect = false;
1457
- queryResultErrors.outer.commitment = {
1458
- expected: `Number of parameter commitments: ${paramCommitments.length}`,
1459
- received: `Number of disclosure proofs provided: ${keysInCommittedInputs.length}`,
1460
- message: "The proof does not verify all the requested conditions and information",
1461
- };
1462
- }
1463
- if (this.domain &&
1464
- (0, utils_1.getServiceScopeHash)(this.domain, chainId) !== (0, utils_1.getScopeFromOuterProof)(proofData)) {
1465
- console.warn("The proof comes from a different domain than the one expected");
1466
- isCorrect = false;
1467
- queryResultErrors.outer.scope = {
1468
- expected: `Scope: ${(0, utils_1.getServiceScopeHash)(this.domain, chainId).toString()}`,
1469
- received: `Scope: ${(0, utils_1.getScopeFromOuterProof)(proofData).toString()}`,
1470
- message: "The proof comes from a different domain than the one expected",
1471
- };
1472
- }
1473
- if (scope && (0, utils_1.getScopeHash)(scope) !== (0, utils_1.getSubscopeFromOuterProof)(proofData)) {
1474
- console.warn("The proof uses a different scope than the one expected");
1475
- isCorrect = false;
1476
- queryResultErrors.outer.scope = {
1477
- expected: `Scope: ${(0, utils_1.getScopeHash)(scope).toString()}`,
1478
- received: `Scope: ${(0, utils_1.getSubscopeFromOuterProof)(proofData).toString()}`,
1479
- message: "The proof uses a different scope than the one expected",
1480
- };
1481
- }
1482
- if (!!committedInputs?.compare_age) {
1483
- const ageCommittedInputs = committedInputs?.compare_age;
1484
- const ageParameterCommitment = isForEVM
1485
- ? await (0, utils_1.getAgeEVMParameterCommitment)(ageCommittedInputs.currentDate, ageCommittedInputs.minAge, ageCommittedInputs.maxAge)
1486
- : await (0, utils_1.getAgeParameterCommitment)(ageCommittedInputs.currentDate, ageCommittedInputs.minAge, ageCommittedInputs.maxAge);
1487
- if (!paramCommitments.includes(ageParameterCommitment)) {
1488
- console.warn("This proof does not verify the age");
1489
- isCorrect = false;
1490
- queryResultErrors.age.commitment = {
1491
- expected: `Age parameter commitment: ${ageParameterCommitment.toString()}`,
1492
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1493
- message: "This proof does not verify the age",
1494
- };
1495
- }
1496
- const { isCorrect: isCorrectAge, queryResultErrors: queryResultErrorsAge } = this.checkAgePublicInputs(proof, queryResult);
1497
- isCorrect = isCorrect && isCorrectAge;
1498
- queryResultErrors = {
1499
- ...queryResultErrors,
1500
- ...queryResultErrorsAge,
1501
- };
1502
- }
1503
- else if (!!committedInputs?.compare_birthdate) {
1504
- const birthdateCommittedInputs = committedInputs?.compare_birthdate;
1505
- const birthdateParameterCommitment = isForEVM
1506
- ? await (0, utils_1.getDateEVMParameterCommitment)(utils_1.ProofType.BIRTHDATE, birthdateCommittedInputs.currentDate, birthdateCommittedInputs.minDate, birthdateCommittedInputs.maxDate)
1507
- : await (0, utils_1.getDateParameterCommitment)(utils_1.ProofType.BIRTHDATE, birthdateCommittedInputs.currentDate, birthdateCommittedInputs.minDate, birthdateCommittedInputs.maxDate);
1508
- if (!paramCommitments.includes(birthdateParameterCommitment)) {
1509
- console.warn("This proof does not verify the birthdate");
1510
- isCorrect = false;
1511
- queryResultErrors.birthdate.commitment = {
1512
- expected: `Birthdate parameter commitment: ${birthdateParameterCommitment.toString()}`,
1513
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1514
- message: "This proof does not verify the birthdate",
1515
- };
1516
- }
1517
- const { isCorrect: isCorrectBirthdate, queryResultErrors: queryResultErrorsBirthdate } = this.checkBirthdatePublicInputs(proof, queryResult);
1518
- isCorrect = isCorrect && isCorrectBirthdate;
1519
- queryResultErrors = {
1520
- ...queryResultErrors,
1521
- ...queryResultErrorsBirthdate,
1522
- };
1523
- }
1524
- else if (!!committedInputs?.compare_expiry) {
1525
- const expiryCommittedInputs = committedInputs?.compare_expiry;
1526
- const expiryParameterCommitment = isForEVM
1527
- ? await (0, utils_1.getDateEVMParameterCommitment)(utils_1.ProofType.EXPIRY_DATE, expiryCommittedInputs.currentDate, expiryCommittedInputs.minDate, expiryCommittedInputs.maxDate)
1528
- : await (0, utils_1.getDateParameterCommitment)(utils_1.ProofType.EXPIRY_DATE, expiryCommittedInputs.currentDate, expiryCommittedInputs.minDate, expiryCommittedInputs.maxDate);
1529
- if (!paramCommitments.includes(expiryParameterCommitment)) {
1530
- console.warn("This proof does not verify the expiry date");
1531
- isCorrect = false;
1532
- queryResultErrors.expiry_date.commitment = {
1533
- expected: `Expiry date parameter commitment: ${expiryParameterCommitment.toString()}`,
1534
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1535
- message: "This proof does not verify the expiry date",
1536
- };
1537
- }
1538
- const { isCorrect: isCorrectExpiryDate, queryResultErrors: queryResultErrorsExpiryDate } = this.checkExpiryDatePublicInputs(proof, queryResult);
1539
- isCorrect = isCorrect && isCorrectExpiryDate;
1540
- queryResultErrors = {
1541
- ...queryResultErrors,
1542
- ...queryResultErrorsExpiryDate,
1543
- };
1544
- }
1545
- else if (!!committedInputs?.disclose_bytes) {
1546
- const discloseCommittedInputs = committedInputs?.disclose_bytes;
1547
- const discloseParameterCommitment = isForEVM
1548
- ? await (0, utils_1.getDiscloseEVMParameterCommitment)(discloseCommittedInputs.discloseMask, discloseCommittedInputs.disclosedBytes)
1549
- : await (0, utils_1.getDiscloseParameterCommitment)(discloseCommittedInputs.discloseMask, discloseCommittedInputs.disclosedBytes);
1550
- if (!paramCommitments.includes(discloseParameterCommitment)) {
1551
- console.warn("This proof does not verify any of the data disclosed");
1552
- isCorrect = false;
1553
- queryResultErrors.disclose.commitment = {
1554
- expected: `Disclosure parameter commitment: ${discloseParameterCommitment.toString()}`,
1555
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1556
- message: "This proof does not verify any of the data disclosed",
1557
- };
1558
- }
1559
- const { isCorrect: isCorrectDisclose, queryResultErrors: queryResultErrorsDisclose } = this.checkDiscloseBytesPublicInputs(proof, queryResult);
1560
- isCorrect = isCorrect && isCorrectDisclose;
1561
- queryResultErrors = {
1562
- ...queryResultErrors,
1563
- ...queryResultErrorsDisclose,
1564
- };
1565
- }
1566
- else if (!!committedInputs?.inclusion_check_nationality) {
1567
- const inclusionCheckNationalityCommittedInputs = committedInputs?.inclusion_check_nationality;
1568
- const inclusionCheckNationalityParameterCommitment = isForEVM
1569
- ? await (0, utils_1.getCountryEVMParameterCommitment)(utils_1.ProofType.NATIONALITY_INCLUSION, inclusionCheckNationalityCommittedInputs.countries)
1570
- : await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.NATIONALITY_INCLUSION, inclusionCheckNationalityCommittedInputs.countries);
1571
- if (!paramCommitments.includes(inclusionCheckNationalityParameterCommitment)) {
1572
- console.warn("This proof does not verify the inclusion of the nationality");
1573
- isCorrect = false;
1574
- queryResultErrors.nationality.commitment = {
1575
- expected: `Nationality parameter commitment: ${inclusionCheckNationalityParameterCommitment.toString()}`,
1576
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1577
- message: "This proof does not verify the inclusion of the nationality",
1578
- };
1579
- }
1580
- const countryList = inclusionCheckNationalityCommittedInputs.countries;
1581
- const { isCorrect: isCorrectNationalityInclusion, queryResultErrors: queryResultErrorsNationalityInclusion, } = this.checkNationalityInclusionPublicInputs(queryResult, countryList);
1582
- isCorrect = isCorrect && isCorrectNationalityInclusion;
1583
- queryResultErrors = {
1584
- ...queryResultErrors,
1585
- ...queryResultErrorsNationalityInclusion,
1586
- };
1587
- }
1588
- else if (!!committedInputs?.inclusion_check_issuing_country) {
1589
- const inclusionCheckIssuingCountryCommittedInputs = committedInputs?.inclusion_check_issuing_country;
1590
- const inclusionCheckIssuingCountryParameterCommitment = isForEVM
1591
- ? await (0, utils_1.getCountryEVMParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_INCLUSION, inclusionCheckIssuingCountryCommittedInputs.countries)
1592
- : await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_INCLUSION, inclusionCheckIssuingCountryCommittedInputs.countries);
1593
- if (!paramCommitments.includes(inclusionCheckIssuingCountryParameterCommitment)) {
1594
- console.warn("This proof does not verify the inclusion of the issuing country");
1595
- isCorrect = false;
1596
- queryResultErrors.issuing_country.commitment = {
1597
- expected: `Issuing country parameter commitment: ${inclusionCheckIssuingCountryParameterCommitment.toString()}`,
1598
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1599
- message: "This proof does not verify the inclusion of the issuing country",
1600
- };
1601
- }
1602
- const countryList = inclusionCheckIssuingCountryCommittedInputs.countries;
1603
- const { isCorrect: isCorrectIssuingCountryInclusion, queryResultErrors: queryResultErrorsIssuingCountryInclusion, } = this.checkIssuingCountryInclusionPublicInputs(queryResult, countryList);
1604
- isCorrect = isCorrect && isCorrectIssuingCountryInclusion;
1605
- queryResultErrors = {
1606
- ...queryResultErrors,
1607
- ...queryResultErrorsIssuingCountryInclusion,
1608
- };
1609
- }
1610
- else if (!!committedInputs?.exclusion_check_nationality) {
1611
- const exclusionCheckNationalityCommittedInputs = committedInputs?.exclusion_check_nationality;
1612
- const exclusionCheckNationalityParameterCommitment = isForEVM
1613
- ? await (0, utils_1.getCountryEVMParameterCommitment)(utils_1.ProofType.NATIONALITY_EXCLUSION, exclusionCheckNationalityCommittedInputs.countries)
1614
- : await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.NATIONALITY_EXCLUSION, exclusionCheckNationalityCommittedInputs.countries);
1615
- if (!paramCommitments.includes(exclusionCheckNationalityParameterCommitment)) {
1616
- console.warn("This proof does not verify the exclusion of the nationality");
1617
- isCorrect = false;
1618
- queryResultErrors.nationality.commitment = {
1619
- expected: `Nationality parameter commitment: ${exclusionCheckNationalityParameterCommitment.toString()}`,
1620
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1621
- message: "This proof does not verify the exclusion of the nationality",
1622
- };
1623
- }
1624
- const countryList = exclusionCheckNationalityCommittedInputs.countries;
1625
- const { isCorrect: isCorrectNationalityExclusion, queryResultErrors: queryResultErrorsNationalityExclusion, } = this.checkNationalityExclusionPublicInputs(queryResult, countryList);
1626
- isCorrect = isCorrect && isCorrectNationalityExclusion;
1627
- queryResultErrors = {
1628
- ...queryResultErrors,
1629
- ...queryResultErrorsNationalityExclusion,
1630
- };
1631
- }
1632
- else if (!!committedInputs?.exclusion_check_issuing_country) {
1633
- const exclusionCheckIssuingCountryCommittedInputs = committedInputs?.exclusion_check_issuing_country;
1634
- const exclusionCheckIssuingCountryParameterCommitment = isForEVM
1635
- ? await (0, utils_1.getCountryEVMParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_EXCLUSION, exclusionCheckIssuingCountryCommittedInputs.countries)
1636
- : await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_EXCLUSION, exclusionCheckIssuingCountryCommittedInputs.countries);
1637
- if (!paramCommitments.includes(exclusionCheckIssuingCountryParameterCommitment)) {
1638
- console.warn("This proof does not verify the exclusion of the issuing country");
1639
- isCorrect = false;
1640
- queryResultErrors.issuing_country.commitment = {
1641
- expected: `Issuing country parameter commitment: ${exclusionCheckIssuingCountryParameterCommitment.toString()}`,
1642
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1643
- message: "This proof does not verify the exclusion of the issuing country",
1644
- };
1645
- }
1646
- const countryList = exclusionCheckIssuingCountryCommittedInputs.countries;
1647
- const { isCorrect: isCorrectIssuingCountryExclusion, queryResultErrors: queryResultErrorsIssuingCountryExclusion, } = this.checkIssuingCountryExclusionPublicInputs(queryResult, countryList);
1648
- isCorrect = isCorrect && isCorrectIssuingCountryExclusion;
1649
- queryResultErrors = {
1650
- ...queryResultErrors,
1651
- ...queryResultErrorsIssuingCountryExclusion,
1652
- };
1653
- }
1654
- else if (!!committedInputs?.bind) {
1655
- const bindCommittedInputs = committedInputs?.bind;
1656
- const bindParameterCommitment = isForEVM
1657
- ? await (0, utils_1.getBindEVMParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data))
1658
- : await (0, utils_1.getBindParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data));
1659
- if (!paramCommitments.includes(bindParameterCommitment)) {
1660
- console.warn("This proof does not verify the bound data");
1661
- isCorrect = false;
1662
- queryResultErrors.bind.commitment = {
1663
- expected: `Bind parameter commitment: ${bindParameterCommitment.toString()}`,
1664
- received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
1665
- message: "This proof does not verify the bound data",
1666
- };
1667
- }
1668
- const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
1669
- isCorrect = isCorrect && isCorrectBind;
1670
- queryResultErrors = {
1671
- ...queryResultErrors,
1672
- ...queryResultErrorsBind,
1673
- };
1674
- }
1675
- uniqueIdentifier = (0, utils_1.getNullifierFromOuterProof)(proofData).toString(10);
1676
- }
1677
- else if (proof.name?.startsWith("sig_check_dsc")) {
1678
- commitmentOut = (0, utils_1.getCommitmentFromDSCProof)(proofData);
1679
- const merkleRoot = (0, utils_1.getMerkleRootFromDSCProof)(proofData);
1680
- const { isCorrect: isCorrectCertificateRegistryRoot, queryResultErrors: queryResultErrorsCertificateRegistryRoot, } = await this.checkCertificateRegistryRoot(merkleRoot.toString(16), queryResultErrors, false);
1681
- isCorrect = isCorrect && isCorrectCertificateRegistryRoot;
1682
- queryResultErrors = {
1683
- ...queryResultErrors,
1684
- ...queryResultErrorsCertificateRegistryRoot,
1685
- };
1686
- }
1687
- else if (proof.name?.startsWith("sig_check_id_data")) {
1688
- commitmentIn = (0, utils_1.getCommitmentInFromIDDataProof)(proofData);
1689
- if (commitmentIn !== commitmentOut) {
1690
- console.warn("Failed to check the link between the certificate signature and ID signature");
1691
- isCorrect = false;
1692
- queryResultErrors.sig_check_id_data.commitment = {
1693
- expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
1694
- received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
1695
- message: "Failed to check the link between the certificate signature and ID signature",
1696
- };
1697
- }
1698
- commitmentOut = (0, utils_1.getCommitmentOutFromIDDataProof)(proofData);
1699
- }
1700
- else if (proof.name?.startsWith("data_check_integrity")) {
1701
- commitmentIn = (0, utils_1.getCommitmentInFromIntegrityProof)(proofData);
1702
- if (commitmentIn !== commitmentOut) {
1703
- console.warn("Failed to check the link between the ID signature and the data signed");
1704
- isCorrect = false;
1705
- queryResultErrors.data_check_integrity.commitment = {
1706
- expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
1707
- received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
1708
- message: "Failed to check the link between the ID signature and the data signed",
1709
- };
1710
- }
1711
- commitmentOut = (0, utils_1.getCommitmentOutFromIntegrityProof)(proofData);
1712
- const currentDate = (0, utils_1.getCurrentDateFromIntegrityProof)(proofData);
1713
- const todayToCurrentDate = today.getTime() - currentDate.getTime();
1714
- const differenceInDays = validity ?? 180;
1715
- const expectedDifference = differenceInDays * 86400000;
1716
- const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
1717
- // The ID should not expire within the next 6 months (or whatever the custom value is)
1718
- if (todayToCurrentDate >= actualDifference) {
1719
- console.warn(`The date used to check the validity of the ID is older than ${differenceInDays} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
1720
- isCorrect = false;
1721
- queryResultErrors.data_check_integrity.date = {
1722
- expected: `Difference: ${differenceInDays} days`,
1723
- received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
1724
- message: "The date used to check the validity of the ID is older than the validity period",
1725
- };
1726
- }
1727
- }
1728
- else if (proof.name === "disclose_bytes") {
1729
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1730
- if (commitmentIn !== commitmentOut) {
1731
- console.warn("Failed to check the link between the validity of the ID and the data to disclose");
1732
- isCorrect = false;
1733
- queryResultErrors.disclose.commitment = {
1734
- expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
1735
- received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
1736
- message: "Failed to check the link between the validity of the ID and the data to disclose",
1737
- };
1738
- }
1739
- const paramCommitment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1740
- const calculatedParamCommitment = await (0, utils_1.getDiscloseParameterCommitment)((proof.committedInputs?.disclose_bytes).discloseMask, (proof.committedInputs?.disclose_bytes).disclosedBytes);
1741
- if (paramCommitment !== calculatedParamCommitment) {
1742
- console.warn("The disclosed data does not match the data committed by the proof");
1743
- isCorrect = false;
1744
- queryResultErrors.disclose.commitment = {
1745
- expected: `Commitment: ${calculatedParamCommitment}`,
1746
- received: `Commitment: ${paramCommitment}`,
1747
- message: "The disclosed data does not match the data committed by the proof",
1748
- };
1749
- }
1750
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "disclose", scope);
1751
- isCorrect = isCorrect && isCorrectScope;
1752
- queryResultErrors = {
1753
- ...queryResultErrors,
1754
- ...queryResultErrorsScope,
1755
- };
1756
- const { isCorrect: isCorrectDisclose, queryResultErrors: queryResultErrorsDisclose } = this.checkDiscloseBytesPublicInputs(proof, queryResult);
1757
- isCorrect = isCorrect && isCorrectDisclose && isCorrectScope;
1758
- queryResultErrors = {
1759
- ...queryResultErrors,
1760
- ...queryResultErrorsDisclose,
1761
- ...queryResultErrorsScope,
1762
- };
1763
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1764
- }
1765
- else if (proof.name === "compare_age") {
1766
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1767
- if (commitmentIn !== commitmentOut) {
1768
- console.warn("Failed to check the link between the validity of the ID and the age derived from it");
1769
- isCorrect = false;
1770
- queryResultErrors.age.commitment = {
1771
- expected: `Commitment: ${commitmentOut}`,
1772
- received: `Commitment: ${commitmentIn}`,
1773
- message: "Failed to check the link between the validity of the ID and the age derived from it",
1774
- };
1775
- }
1776
- const paramCommitment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1777
- const committedInputs = proof.committedInputs?.compare_age;
1778
- const calculatedParamCommitment = await (0, utils_1.getAgeParameterCommitment)(committedInputs.currentDate, committedInputs.minAge, committedInputs.maxAge);
1779
- if (paramCommitment !== calculatedParamCommitment) {
1780
- console.warn("The conditions for the age check do not match the conditions checked by the proof");
1781
- isCorrect = false;
1782
- queryResultErrors.age.commitment = {
1783
- expected: `Commitment: ${calculatedParamCommitment}`,
1784
- received: `Commitment: ${paramCommitment}`,
1785
- message: "The conditions for the age check do not match the conditions checked by the proof",
1786
- };
1787
- }
1788
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "age", scope);
1789
- const { isCorrect: isCorrectAge, queryResultErrors: queryResultErrorsAge } = this.checkAgePublicInputs(proof, queryResult);
1790
- isCorrect = isCorrect && isCorrectAge && isCorrectScope;
1791
- queryResultErrors = {
1792
- ...queryResultErrors,
1793
- ...queryResultErrorsAge,
1794
- ...queryResultErrorsScope,
1795
- };
1796
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1797
- }
1798
- else if (proof.name === "compare_birthdate") {
1799
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1800
- if (commitmentIn !== commitmentOut) {
1801
- console.warn("Failed to check the link between the validity of the ID and the birthdate derived from it");
1802
- isCorrect = false;
1803
- queryResultErrors.birthdate.commitment = {
1804
- expected: `Commitment: ${commitmentOut}`,
1805
- received: `Commitment: ${commitmentIn}`,
1806
- message: "Failed to check the link between the validity of the ID and the birthdate derived from it",
1807
- };
1808
- }
1809
- const paramCommitment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1810
- const committedInputs = proof.committedInputs?.compare_birthdate;
1811
- const calculatedParamCommitment = await (0, utils_1.getDateParameterCommitment)(utils_1.ProofType.BIRTHDATE, committedInputs.currentDate, committedInputs.minDate, committedInputs.maxDate);
1812
- if (paramCommitment !== calculatedParamCommitment) {
1813
- console.warn("The conditions for the birthdate check do not match the conditions checked by the proof");
1814
- isCorrect = false;
1815
- queryResultErrors.birthdate.commitment = {
1816
- expected: `Commitment: ${calculatedParamCommitment}`,
1817
- received: `Commitment: ${paramCommitment}`,
1818
- message: "The conditions for the birthdate check do not match the conditions checked by the proof",
1819
- };
1820
- }
1821
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "birthdate", scope);
1822
- const { isCorrect: isCorrectBirthdate, queryResultErrors: queryResultErrorsBirthdate } = this.checkBirthdatePublicInputs(proof, queryResult);
1823
- isCorrect = isCorrect && isCorrectBirthdate && isCorrectScope;
1824
- queryResultErrors = {
1825
- ...queryResultErrors,
1826
- ...queryResultErrorsBirthdate,
1827
- ...queryResultErrorsScope,
1828
- };
1829
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1830
- }
1831
- else if (proof.name === "compare_expiry") {
1832
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1833
- if (commitmentIn !== commitmentOut) {
1834
- console.warn("Failed to check the link between the validity of the ID and its expiry date");
1835
- isCorrect = false;
1836
- queryResultErrors.expiry_date.commitment = {
1837
- expected: `Commitment: ${commitmentOut}`,
1838
- received: `Commitment: ${commitmentIn}`,
1839
- message: "Failed to check the link between the validity of the ID and its expiry date",
1840
- };
1841
- }
1842
- const paramCommitment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1843
- const committedInputs = proof.committedInputs?.compare_expiry;
1844
- const calculatedParamCommitment = await (0, utils_1.getDateParameterCommitment)(utils_1.ProofType.EXPIRY_DATE, committedInputs.currentDate, committedInputs.minDate, committedInputs.maxDate);
1845
- if (paramCommitment !== calculatedParamCommitment) {
1846
- console.warn("The conditions for the expiry date check do not match the conditions checked by the proof");
1847
- isCorrect = false;
1848
- queryResultErrors.expiry_date.commitment = {
1849
- expected: `Commitment: ${calculatedParamCommitment}`,
1850
- received: `Commitment: ${paramCommitment}`,
1851
- message: "The conditions for the expiry date check do not match the conditions checked by the proof",
1852
- };
1853
- }
1854
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "expiry_date", scope);
1855
- const { isCorrect: isCorrectExpiryDate, queryResultErrors: queryResultErrorsExpiryDate } = this.checkExpiryDatePublicInputs(proof, queryResult);
1856
- isCorrect = isCorrect && isCorrectExpiryDate && isCorrectScope;
1857
- queryResultErrors = {
1858
- ...queryResultErrors,
1859
- ...queryResultErrorsExpiryDate,
1860
- ...queryResultErrorsScope,
1861
- };
1862
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1863
- }
1864
- else if (proof.name === "exclusion_check_nationality") {
1865
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1866
- if (commitmentIn !== commitmentOut) {
1867
- console.warn("Failed to check the link between the validity of the ID and the nationality exclusion check");
1868
- isCorrect = false;
1869
- queryResultErrors.nationality.commitment = {
1870
- expected: `Commitment: ${commitmentOut}`,
1871
- received: `Commitment: ${commitmentIn}`,
1872
- message: "Failed to check the link between the validity of the ID and the nationality exclusion check",
1873
- };
1874
- }
1875
- const countryList = (proof.committedInputs?.exclusion_check_nationality).countries;
1876
- const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1877
- const calculatedParamCommitment = await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.NATIONALITY_EXCLUSION, countryList, true);
1878
- if (paramCommittment !== calculatedParamCommitment) {
1879
- console.warn("The committed country list for the exclusion check does not match the one from the proof");
1880
- isCorrect = false;
1881
- queryResultErrors.nationality.commitment = {
1882
- expected: `Commitment: ${calculatedParamCommitment}`,
1883
- received: `Commitment: ${paramCommittment}`,
1884
- message: "The committed country list for the exclusion check does not match the one from the proof",
1885
- };
1886
- }
1887
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "nationality", scope);
1888
- const { isCorrect: isCorrectNationalityExclusion, queryResultErrors: queryResultErrorsNationalityExclusion, } = this.checkNationalityExclusionPublicInputs(queryResult, countryList);
1889
- isCorrect = isCorrect && isCorrectNationalityExclusion && isCorrectScope;
1890
- queryResultErrors = {
1891
- ...queryResultErrors,
1892
- ...queryResultErrorsNationalityExclusion,
1893
- ...queryResultErrorsScope,
1894
- };
1895
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1896
- }
1897
- else if (proof.name === "exclusion_check_issuing_country") {
1898
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1899
- if (commitmentIn !== commitmentOut) {
1900
- console.warn("Failed to check the link between the validity of the ID and the issuing country exclusion check");
1901
- isCorrect = false;
1902
- queryResultErrors.nationality.commitment = {
1903
- expected: `Commitment: ${commitmentOut}`,
1904
- received: `Commitment: ${commitmentIn}`,
1905
- message: "Failed to check the link between the validity of the ID and the issuing country exclusion check",
1906
- };
1907
- }
1908
- const countryList = (proof.committedInputs?.exclusion_check_issuing_country).countries;
1909
- const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1910
- const calculatedParamCommitment = await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_EXCLUSION, countryList, true);
1911
- if (paramCommittment !== calculatedParamCommitment) {
1912
- console.warn("The committed country list for the issuing country exclusion check does not match the one from the proof");
1913
- isCorrect = false;
1914
- queryResultErrors.issuing_country.commitment = {
1915
- expected: `Commitment: ${calculatedParamCommitment}`,
1916
- received: `Commitment: ${paramCommittment}`,
1917
- message: "The committed country list for the issuing country exclusion check does not match the one from the proof",
1918
- };
1919
- }
1920
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "nationality", scope);
1921
- const { isCorrect: isCorrectIssuingCountryExclusion, queryResultErrors: queryResultErrorsIssuingCountryExclusion, } = this.checkIssuingCountryExclusionPublicInputs(queryResult, countryList);
1922
- isCorrect = isCorrect && isCorrectIssuingCountryExclusion && isCorrectScope;
1923
- queryResultErrors = {
1924
- ...queryResultErrors,
1925
- ...queryResultErrorsIssuingCountryExclusion,
1926
- ...queryResultErrorsScope,
1927
- };
1928
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1929
- }
1930
- else if (proof.name === "inclusion_check_nationality") {
1931
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1932
- if (commitmentIn !== commitmentOut) {
1933
- console.warn("Failed to check the link between the validity of the ID and the nationality inclusion check");
1934
- isCorrect = false;
1935
- queryResultErrors.nationality.commitment = {
1936
- expected: `Commitment: ${commitmentOut}`,
1937
- received: `Commitment: ${commitmentIn}`,
1938
- message: "Failed to check the link between the validity of the ID and the nationality inclusion check",
1939
- };
1940
- }
1941
- const countryList = (proof.committedInputs?.inclusion_check_nationality).countries;
1942
- const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1943
- const calculatedParamCommitment = await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.NATIONALITY_INCLUSION, countryList, false);
1944
- if (paramCommittment !== calculatedParamCommitment) {
1945
- console.warn("The committed country list for the nationality inclusion check does not match the one from the proof");
1946
- isCorrect = false;
1947
- queryResultErrors.nationality.commitment = {
1948
- expected: `Commitment: ${calculatedParamCommitment}`,
1949
- received: `Commitment: ${paramCommittment}`,
1950
- message: "The committed country list for the nationality inclusion check does not match the one from the proof",
1951
- };
1952
- }
1953
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "nationality", scope);
1954
- const { isCorrect: isCorrectNationalityInclusion, queryResultErrors: queryResultErrorsNationalityInclusion, } = this.checkNationalityInclusionPublicInputs(queryResult, countryList);
1955
- isCorrect = isCorrect && isCorrectNationalityInclusion && isCorrectScope;
1956
- queryResultErrors = {
1957
- ...queryResultErrors,
1958
- ...queryResultErrorsNationalityInclusion,
1959
- ...queryResultErrorsScope,
1960
- };
1961
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1962
- }
1963
- else if (proof.name === "inclusion_check_issuing_country") {
1964
- commitmentIn = (0, utils_1.getCommitmentInFromDisclosureProof)(proofData);
1965
- if (commitmentIn !== commitmentOut) {
1966
- console.warn("Failed to check the link between the validity of the ID and the issuing country inclusion check");
1967
- isCorrect = false;
1968
- queryResultErrors.nationality.commitment = {
1969
- expected: `Commitment: ${commitmentOut}`,
1970
- received: `Commitment: ${commitmentIn}`,
1971
- message: "Failed to check the link between the validity of the ID and the issuing country inclusion check",
1972
- };
1973
- }
1974
- const countryList = (proof.committedInputs?.inclusion_check_issuing_country).countries;
1975
- const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1976
- const calculatedParamCommitment = await (0, utils_1.getCountryParameterCommitment)(utils_1.ProofType.ISSUING_COUNTRY_INCLUSION, countryList, false);
1977
- if (paramCommittment !== calculatedParamCommitment) {
1978
- console.warn("The committed country list for the issuing country inclusion check does not match the one from the proof");
1979
- isCorrect = false;
1980
- queryResultErrors.issuing_country.commitment = {
1981
- expected: `Commitment: ${calculatedParamCommitment}`,
1982
- received: `Commitment: ${paramCommittment}`,
1983
- message: "The committed country list for the issuing country inclusion check does not match the one from the proof",
1984
- };
1985
- }
1986
- const { isCorrect: isCorrectScope, queryResultErrors: queryResultErrorsScope } = this.checkScopeFromDisclosureProof(proofData, queryResultErrors, "nationality", scope);
1987
- const { isCorrect: isCorrectIssuingCountryInclusion, queryResultErrors: queryResultErrorsIssuingCountryInclusion, } = this.checkIssuingCountryInclusionPublicInputs(queryResult, countryList);
1988
- isCorrect = isCorrect && isCorrectIssuingCountryInclusion && isCorrectScope;
1989
- queryResultErrors = {
1990
- ...queryResultErrors,
1991
- ...queryResultErrorsIssuingCountryInclusion,
1992
- ...queryResultErrorsScope,
1993
- };
1994
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
1995
- }
1996
- else if (proof.name === "bind") {
1997
- const bindCommittedInputs = proof.committedInputs?.bind;
1998
- const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
1999
- const calculatedParamCommitment = await (0, utils_1.getBindParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data));
2000
- if (paramCommittment !== calculatedParamCommitment) {
2001
- console.warn("The bound data does not match the one from the proof");
2002
- isCorrect = false;
2003
- queryResultErrors.bind.commitment = {
2004
- expected: `Commitment: ${calculatedParamCommitment}`,
2005
- received: `Commitment: ${paramCommittment}`,
2006
- message: "The bound data does not match the one from the proof",
2007
- };
2008
- }
2009
- const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
2010
- isCorrect = isCorrect && isCorrectBind;
2011
- queryResultErrors = {
2012
- ...queryResultErrors,
2013
- ...queryResultErrorsBind,
2014
- };
2015
- uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
2016
- }
2017
- }
2018
- return { isCorrect, uniqueIdentifier, queryResultErrors };
2019
- }
2020
- /**
2021
- * @notice Verify the proofs received from the mobile app.
2022
- * @param proofs The proofs to verify.
2023
- * @param queryResult The query result to verify against
2024
- * @param validity How many days ago should have the ID been last scanned by the user?
2025
- * @param scope Scope this request to a specific use case
2026
- * @param evmChain The EVM chain to use for the verification (if using the proof onchain)
2027
- * @param devMode Whether to enable dev mode. This will allow you to verify mock proofs (i.e. from ZKR)
2028
- * @param writingDirectory The directory (e.g. `./tmp`) where the necessary temporary artifacts for verification are written to.
2029
- * It should only be needed when running the `verify` function on a server with restricted write access (e.g. Vercel)
2030
- * @returns An object containing the unique identifier associated to the user
2031
- * and a boolean indicating whether the proofs were successfully verified.
2032
- */
2033
- async verify({ proofs, queryResult, validity, scope, evmChain, devMode = false, writingDirectory, }) {
2034
- // If no proofs were generated, the results can't be trusted.
2035
- // We still return it but verified will be false
2036
- if (!proofs || proofs.length === 0) {
2037
- return {
2038
- uniqueIdentifier: undefined,
2039
- verified: false,
2040
- };
2041
- }
2042
- const formattedResult = queryResult;
2043
- // Make sure to reconvert the dates to Date objects
2044
- if (formattedResult.birthdate && formattedResult.birthdate.disclose) {
2045
- formattedResult.birthdate.disclose.result = new Date(formattedResult.birthdate.disclose.result);
2046
- }
2047
- if (formattedResult.expiry_date && formattedResult.expiry_date.disclose) {
2048
- formattedResult.expiry_date.disclose.result = new Date(formattedResult.expiry_date.disclose.result);
2049
- }
2050
- const { BarretenbergVerifier } = await Promise.resolve().then(() => tslib_1.__importStar(require("@aztec/bb.js")));
2051
- // Automatically set the writing directory to `/tmp` if it is not provided
2052
- // and the code is not running in the browser
2053
- if (typeof window === "undefined" && !writingDirectory) {
2054
- writingDirectory = "/tmp";
2055
- }
2056
- const verifier = new BarretenbergVerifier({
2057
- crsPath: writingDirectory ? writingDirectory + "/.bb-crs" : undefined,
2058
- });
2059
- let verified = true;
2060
- let uniqueIdentifier;
2061
- let queryResultErrors;
2062
- const chainId = evmChain ? getChainIdFromEVMChain(evmChain) : undefined;
2063
- const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofs, formattedResult, validity, scope, chainId);
2064
- uniqueIdentifier = uniqueIdentifierFromPublicInputs;
2065
- verified = isCorrect;
2066
- queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
2067
- if (uniqueIdentifier &&
2068
- (BigInt(uniqueIdentifier) === BigInt(1) || BigInt(uniqueIdentifier) === BigInt(0)) &&
2069
- !devMode) {
2070
- // If the unique identifier is 0 (old ZKR proofs) or 1 (new ZKR proofs) and it is not in dev mode,
2071
- // the proofs are considered invalid as these are mock proofs only meant
2072
- // for testing purposes
2073
- verified = false;
2074
- console.warn("You are trying to verify a mock proof. This is only allowed in dev mode. To enable dev mode, set the `devMode` parameter to `true` in the request function parameters.");
2075
- }
2076
- // Only proceed with the proof verification if the public inputs are correct
2077
- if (verified) {
2078
- const registryClient = new registry_1.RegistryClient({ chainId: 11155111 });
2079
- const circuitManifest = await registryClient.getCircuitManifest(undefined, {
2080
- // We assume all proofs have the same version
2081
- version: proofs[0].version,
2082
- });
2083
- for (const proof of proofs) {
2084
- const proofData = (0, utils_1.getProofData)(proof.proof, (0, utils_1.getNumberOfPublicInputs)(proof.name));
2085
- const hostedPackagedCircuit = await registryClient.getPackagedCircuit(proof.name, circuitManifest);
2086
- if (proof.name?.startsWith("outer_evm")) {
2087
- try {
2088
- const { createPublicClient, http } = await Promise.resolve().then(() => tslib_1.__importStar(require("viem")));
2089
- const { sepolia } = await Promise.resolve().then(() => tslib_1.__importStar(require("viem/chains")));
2090
- const { address, abi, functionName } = this.getSolidityVerifierDetails("ethereum_sepolia");
2091
- const client = createPublicClient({
2092
- chain: sepolia,
2093
- transport: http("https://ethereum-sepolia-rpc.publicnode.com"),
2094
- });
2095
- const params = this.getSolidityVerifierParameters({
2096
- proof,
2097
- validityPeriodInDays: validity,
2098
- domain: this.domain,
2099
- scope,
2100
- devMode,
2101
- });
2102
- const result = await client.readContract({
2103
- address,
2104
- abi,
2105
- functionName,
2106
- args: [params],
2107
- });
2108
- const isVerified = Array.isArray(result) ? Boolean(result[0]) : false;
2109
- verified = isVerified;
2110
- }
2111
- catch (error) {
2112
- console.warn("Error verifying proof", error);
2113
- verified = false;
2114
- }
2115
- }
2116
- else {
2117
- const vkeyBytes = buffer_1.Buffer.from(hostedPackagedCircuit.vkey, "base64");
2118
- try {
2119
- verified = await verifier.verifyUltraHonkProof({
2120
- proof: buffer_1.Buffer.from(proofData.proof.join(""), "hex"),
2121
- publicInputs: proofData.publicInputs,
2122
- }, new Uint8Array(vkeyBytes));
2123
- }
2124
- catch (e) {
2125
- console.warn("Error verifying proof", e);
2126
- verified = false;
2127
- }
2128
- }
2129
- if (!verified) {
2130
- // Break the loop if the proof is not valid
2131
- // and don't bother checking the other proofs
2132
- break;
2133
- }
2134
- }
2135
- }
2136
- // If the proofs are not verified, we don't return the unique identifier
2137
- uniqueIdentifier = verified ? uniqueIdentifier : undefined;
2138
- return { uniqueIdentifier, verified, queryResultErrors };
2139
- }
2140
- getSolidityVerifierDetails(network) {
2141
- const baseConfig = {
2142
- functionName: "verifyProof",
2143
- abi: ZKPassportVerifier_json_1.default.abi,
2144
- };
2145
- if (network === "ethereum_sepolia") {
2146
- return {
2147
- ...baseConfig,
2148
- address: "0xDDeFf76024052D26B78A7Fac66FFbd6fbc5bd9Ad",
2149
- };
2150
- }
2151
- else if (network === "local_anvil") {
2152
- return {
2153
- ...baseConfig,
2154
- address: "0x0",
2155
- };
2156
- }
2157
- throw new Error(`Unsupported network: ${network}`);
2158
- }
2159
- getSolidityVerifierParameters({ proof, validityPeriodInDays = 7, domain, scope, devMode = false, }) {
2160
- if (!proof.name?.startsWith("outer_evm")) {
2161
- throw new Error("This proof cannot be verified on an EVM chain. Please make sure to use the `compressed-evm` mode.");
2162
- }
2163
- const proofData = (0, utils_1.getProofData)(proof.proof, (0, utils_1.getNumberOfPublicInputs)(proof.name));
2164
- // For EVM optimised proofs, the first 16 bytes of the proof are the aggregation object
2165
- // and should be moved at the end of the public inputs
2166
- const actualProof = proofData.proof.slice(16);
2167
- const actualPublicInputs = proofData.publicInputs.concat(proofData.proof.slice(0, 16).map((x) => `0x${x}`));
2168
- let committedInputCounts = [];
2169
- let committedInputs = [];
2170
- for (const key in proof.committedInputs) {
2171
- const committedInputCount = (0, utils_1.getCommittedInputCount)(key);
2172
- const circuitName = key;
2173
- committedInputCounts.push({ circuitName, count: committedInputCount });
2174
- let compressedCommittedInputs = "";
2175
- if (circuitName === "inclusion_check_issuing_country_evm" ||
2176
- circuitName === "inclusion_check_nationality_evm" ||
2177
- circuitName === "exclusion_check_issuing_country_evm" ||
2178
- circuitName === "exclusion_check_nationality_evm") {
2179
- const value = proof.committedInputs[circuitName];
2180
- const formattedCountries = value.countries;
2181
- if (circuitName === "exclusion_check_issuing_country_evm" ||
2182
- circuitName === "exclusion_check_nationality_evm") {
2183
- formattedCountries.sort((a, b) => a.localeCompare(b));
2184
- }
2185
- const proofType = (() => {
2186
- switch (circuitName) {
2187
- case "exclusion_check_issuing_country_evm":
2188
- return utils_1.ProofType.ISSUING_COUNTRY_EXCLUSION;
2189
- case "exclusion_check_nationality_evm":
2190
- return utils_1.ProofType.NATIONALITY_EXCLUSION;
2191
- case "inclusion_check_issuing_country_evm":
2192
- return utils_1.ProofType.ISSUING_COUNTRY_INCLUSION;
2193
- case "inclusion_check_nationality_evm":
2194
- return utils_1.ProofType.NATIONALITY_INCLUSION;
2195
- }
2196
- })();
2197
- compressedCommittedInputs =
2198
- proofType.toString(16).padStart(2, "0") +
2199
- (0, utils_1.rightPadArrayWithZeros)(formattedCountries.map((c) => Array.from(new TextEncoder().encode(c))).flat(), 600)
2200
- .map((x) => x.toString(16).padStart(2, "0"))
2201
- .join("");
2202
- }
2203
- else if (circuitName === "compare_age_evm") {
2204
- const value = proof.committedInputs[circuitName];
2205
- const currentDateBytes = Array.from(new TextEncoder().encode(value.currentDate));
2206
- compressedCommittedInputs =
2207
- utils_1.ProofType.AGE.toString(16).padStart(2, "0") +
2208
- currentDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("") +
2209
- value.minAge.toString(16).padStart(2, "0") +
2210
- value.maxAge.toString(16).padStart(2, "0");
2211
- }
2212
- else if (circuitName === "compare_birthdate_evm") {
2213
- const value = proof.committedInputs[circuitName];
2214
- const currentDateBytes = Array.from(new TextEncoder().encode(value.currentDate));
2215
- const minDateBytes = Array.from(new TextEncoder().encode(value.minDate));
2216
- const maxDateBytes = Array.from(new TextEncoder().encode(value.maxDate));
2217
- compressedCommittedInputs =
2218
- utils_1.ProofType.BIRTHDATE.toString(16).padStart(2, "0") +
2219
- currentDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("") +
2220
- minDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("") +
2221
- maxDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
2222
- }
2223
- else if (circuitName === "compare_expiry_evm") {
2224
- const value = proof.committedInputs[circuitName];
2225
- const currentDateBytes = Array.from(new TextEncoder().encode(value.currentDate));
2226
- const minDateBytes = Array.from(new TextEncoder().encode(value.minDate));
2227
- const maxDateBytes = Array.from(new TextEncoder().encode(value.maxDate));
2228
- compressedCommittedInputs =
2229
- utils_1.ProofType.EXPIRY_DATE.toString(16).padStart(2, "0") +
2230
- currentDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("") +
2231
- minDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("") +
2232
- maxDateBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
2233
- }
2234
- else if (circuitName === "disclose_bytes_evm") {
2235
- const value = proof.committedInputs[circuitName];
2236
- compressedCommittedInputs =
2237
- utils_1.ProofType.DISCLOSE.toString(16).padStart(2, "0") +
2238
- value.discloseMask.map((x) => x.toString(16).padStart(2, "0")).join("") +
2239
- value.disclosedBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
2240
- }
2241
- else if (circuitName === "bind_evm") {
2242
- const value = proof.committedInputs[circuitName];
2243
- compressedCommittedInputs =
2244
- utils_1.ProofType.BIND.toString(16).padStart(2, "0") +
2245
- (0, utils_1.rightPadArrayWithZeros)((0, utils_1.formatBoundData)(value.data), 500)
2246
- .map((x) => x.toString(16).padStart(2, "0"))
2247
- .join("");
2248
- }
2249
- else {
2250
- throw new Error(`Unsupported circuit for EVM verification: ${circuitName}`);
2251
- }
2252
- committedInputs.push({ circuitName, inputs: compressedCommittedInputs });
2253
- }
2254
- const parameterCommitments = proofData.publicInputs.slice(12, proofData.publicInputs.length - 1);
2255
- let compressedCommittedInputs = "";
2256
- let committedInputCountsArray = [];
2257
- for (const commitment of parameterCommitments) {
2258
- const committedInput = committedInputs.find((x) => {
2259
- const rawHashedInputs = (0, sha2_1.sha256)((0, utils_3.hexToBytes)(x.inputs));
2260
- // Shift the hash 8 bits to the right (1 byte)
2261
- // as one byte is dropped in the circuit to fit in the 254-bit field size
2262
- const hashedInputs = new Uint8Array(rawHashedInputs.length);
2263
- // Move each byte 1 position to the right (shifting 8 bits)
2264
- for (let i = 0; i < rawHashedInputs.length - 1; i++) {
2265
- hashedInputs[i + 1] = rawHashedInputs[i];
2266
- }
2267
- // First byte becomes 0 (since we're shifting right)
2268
- hashedInputs[0] = 0;
2269
- return (0, utils_2.bytesToHex)(hashedInputs) === commitment.replace("0x", "");
2270
- });
2271
- if (committedInput) {
2272
- const count = committedInputCounts.find((x) => x.circuitName === committedInput.circuitName)?.count;
2273
- if (count) {
2274
- committedInputCountsArray.push(count);
2275
- compressedCommittedInputs += committedInput.inputs;
2276
- }
2277
- else {
2278
- throw new Error(`Unknown circuit name: ${committedInput.circuitName}`);
2279
- }
2280
- }
2281
- else {
2282
- throw new Error(`Invalid commitment: ${commitment}`);
2283
- }
2284
- }
2285
- const params = {
2286
- // Make sure the vkeyHash is 32 bytes
2287
- vkeyHash: `0x${proof.vkeyHash.replace("0x", "").padStart(64, "0")}`,
2288
- proof: `0x${actualProof.join("")}`,
2289
- publicInputs: actualPublicInputs,
2290
- committedInputs: `0x${compressedCommittedInputs}`,
2291
- committedInputCounts: committedInputCountsArray,
2292
- validityPeriodInDays,
2293
- domain: domain ?? this.domain,
2294
- scope: scope ?? "",
2295
- devMode,
2296
- };
2297
- return params;
2298
- }
2299
- _getUrl(requestId) {
2300
- const base64Config = buffer_1.Buffer.from(JSON.stringify(this.topicToConfig[requestId])).toString("base64");
2301
- const base64Service = buffer_1.Buffer.from(JSON.stringify(this.topicToService[requestId])).toString("base64");
2302
- const pubkey = this.topicToPublicKey[requestId];
2303
- return `https://zkpassport.id/r?d=${this.domain}&t=${requestId}&c=${base64Config}&s=${base64Service}&p=${pubkey}&m=${this.topicToLocalConfig[requestId].mode}&v=${VERSION}`;
2304
- }
2305
- /**
2306
- * @notice Returns the URL of the request.
2307
- * @param requestId The request ID.
2308
- * @returns The URL of the request.
2309
- */
2310
- getUrl(requestId) {
2311
- return this._getUrl(requestId);
2312
- }
2313
- /**
2314
- * @notice Cancels a request by closing the WebSocket connection and deleting the associated data.
2315
- * @param requestId The request ID.
2316
- */
2317
- cancelRequest(requestId) {
2318
- if (this.topicToBridge[requestId]) {
2319
- this.topicToBridge[requestId].close();
2320
- delete this.topicToBridge[requestId];
2321
- }
2322
- delete this.topicToPublicKey[requestId];
2323
- delete this.topicToConfig[requestId];
2324
- delete this.topicToLocalConfig[requestId];
2325
- delete this.topicToProofs[requestId];
2326
- delete this.topicToExpectedProofCount[requestId];
2327
- delete this.topicToFailedProofCount[requestId];
2328
- delete this.topicToResults[requestId];
2329
- this.onRequestReceivedCallbacks[requestId] = [];
2330
- this.onGeneratingProofCallbacks[requestId] = [];
2331
- this.onBridgeConnectCallbacks[requestId] = [];
2332
- this.onProofGeneratedCallbacks[requestId] = [];
2333
- this.onRejectCallbacks[requestId] = [];
2334
- this.onErrorCallbacks[requestId] = [];
2335
- }
2336
- /**
2337
- * @notice Clears all requests.
2338
- */
2339
- clearAllRequests() {
2340
- for (const requestId in this.topicToBridge) {
2341
- this.cancelRequest(requestId);
2342
- }
2343
- }
2344
- }
2345
- exports.ZKPassport = ZKPassport;