@zkpassport/sdk 0.2.9 → 0.2.11
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.d.ts +8 -4
- package/dist/cjs/index.js +151 -70
- package/dist/esm/index.d.ts +8 -4
- package/dist/esm/index.js +151 -70
- package/package.json +3 -3
- package/src/index.ts +202 -87
package/dist/esm/index.js
CHANGED
|
@@ -7,8 +7,6 @@ import { createEncryptedJsonRpcRequest } from "./json-rpc";
|
|
|
7
7
|
import { decrypt, generateECDHKeyPair, getSharedSecret } from "./encryption";
|
|
8
8
|
import { noLogger as logger } from "./logger";
|
|
9
9
|
import { inflate } from "pako";
|
|
10
|
-
//import initNoirC from '@noir-lang/noirc_abi'
|
|
11
|
-
//import initACVM from '@noir-lang/acvm_js'
|
|
12
10
|
import i18en from "i18n-iso-countries/langs/en.json";
|
|
13
11
|
import { Buffer } from "buffer/";
|
|
14
12
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
@@ -84,18 +82,17 @@ export class ZKPassport {
|
|
|
84
82
|
}
|
|
85
83
|
this.domain = _domain || window.location.hostname;
|
|
86
84
|
}
|
|
87
|
-
/*private async initWasmVerifier() {
|
|
88
|
-
const acvm = await import('@noir-lang/acvm_js/web/acvm_js_bg.wasm')
|
|
89
|
-
const noirc = await import('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm')
|
|
90
|
-
await Promise.all([initACVM(acvm), initNoirC(noirc)])
|
|
91
|
-
this.wasmVerifierInit = true
|
|
92
|
-
}*/
|
|
93
85
|
async handleResult(topic) {
|
|
94
86
|
const result = this.topicToResults[topic];
|
|
95
87
|
// Clear the results straight away to avoid concurrency issues
|
|
96
88
|
delete this.topicToResults[topic];
|
|
97
89
|
// Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
|
|
98
|
-
const { uniqueIdentifier, verified, queryResultErrors } = await this.verify(
|
|
90
|
+
const { uniqueIdentifier, verified, queryResultErrors } = await this.verify({
|
|
91
|
+
proofs: this.topicToProofs[topic],
|
|
92
|
+
queryResult: result,
|
|
93
|
+
validity: this.topicToLocalConfig[topic]?.validity,
|
|
94
|
+
});
|
|
95
|
+
delete this.topicToProofs[topic];
|
|
99
96
|
const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
|
|
100
97
|
await Promise.all(this.onResultCallbacks[topic].map((callback) => callback({
|
|
101
98
|
// If there are failed proofs, we don't return the unique identifier
|
|
@@ -141,13 +138,23 @@ export class ZKPassport {
|
|
|
141
138
|
}
|
|
142
139
|
break;
|
|
143
140
|
case "in":
|
|
144
|
-
if (field === "nationality" &&
|
|
145
|
-
neededCircuits.
|
|
141
|
+
if (field === "nationality" &&
|
|
142
|
+
!neededCircuits.includes("inclusion_check_nationality")) {
|
|
143
|
+
neededCircuits.push("inclusion_check_nationality");
|
|
144
|
+
}
|
|
145
|
+
else if (field === "issuing_country" &&
|
|
146
|
+
!neededCircuits.includes("inclusion_check_issuing_country")) {
|
|
147
|
+
neededCircuits.push("inclusion_check_issuing_country");
|
|
146
148
|
}
|
|
147
149
|
break;
|
|
148
150
|
case "out":
|
|
149
|
-
if (field === "nationality" &&
|
|
150
|
-
neededCircuits.
|
|
151
|
+
if (field === "nationality" &&
|
|
152
|
+
!neededCircuits.includes("exclusion_check_nationality")) {
|
|
153
|
+
neededCircuits.push("exclusion_check_nationality");
|
|
154
|
+
}
|
|
155
|
+
else if (field === "issuing_country" &&
|
|
156
|
+
!neededCircuits.includes("exclusion_check_issuing_country")) {
|
|
157
|
+
neededCircuits.push("exclusion_check_issuing_country");
|
|
151
158
|
}
|
|
152
159
|
break;
|
|
153
160
|
}
|
|
@@ -381,7 +388,7 @@ export class ZKPassport {
|
|
|
381
388
|
};
|
|
382
389
|
return this.getZkPassportRequest(topic);
|
|
383
390
|
}
|
|
384
|
-
async checkPublicInputs(proofs, queryResult,
|
|
391
|
+
async checkPublicInputs(proofs, queryResult, validity) {
|
|
385
392
|
let commitmentIn;
|
|
386
393
|
let commitmentOut;
|
|
387
394
|
let isCorrect = true;
|
|
@@ -418,8 +425,10 @@ export class ZKPassport {
|
|
|
418
425
|
"compare_age",
|
|
419
426
|
"compare_birthdate",
|
|
420
427
|
"compare_expiry",
|
|
421
|
-
"
|
|
422
|
-
"
|
|
428
|
+
"exclusion_check_nationality",
|
|
429
|
+
"inclusion_check_nationality",
|
|
430
|
+
"exclusion_check_issuing_country",
|
|
431
|
+
"inclusion_check_issuing_country",
|
|
423
432
|
];
|
|
424
433
|
const getIndex = (proof) => {
|
|
425
434
|
const name = proof.name || "";
|
|
@@ -469,14 +478,15 @@ export class ZKPassport {
|
|
|
469
478
|
commitmentOut = getCommitmentOutFromIntegrityProof(proofData);
|
|
470
479
|
const currentDate = getCurrentDateFromIntegrityProof(proofData);
|
|
471
480
|
const todayToCurrentDate = today.getTime() - currentDate.getTime();
|
|
472
|
-
const
|
|
481
|
+
const differenceInDays = validity ?? 180;
|
|
482
|
+
const expectedDifference = differenceInDays * 86400000;
|
|
473
483
|
const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
|
|
474
484
|
// The ID should not expire within the next 6 months (or whatever the custom value is)
|
|
475
485
|
if (todayToCurrentDate >= actualDifference) {
|
|
476
|
-
console.warn(`The date used to check the validity of the ID is older than ${
|
|
486
|
+
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`);
|
|
477
487
|
isCorrect = false;
|
|
478
488
|
queryResultErrors.data_check_integrity.date = {
|
|
479
|
-
expected: `Difference: ${
|
|
489
|
+
expected: `Difference: ${differenceInDays} days`,
|
|
480
490
|
received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
|
|
481
491
|
message: "The date used to check the validity of the ID is older than the validity period",
|
|
482
492
|
};
|
|
@@ -506,7 +516,7 @@ export class ZKPassport {
|
|
|
506
516
|
isCorrect = false;
|
|
507
517
|
queryResultErrors.document_type.eq = {
|
|
508
518
|
expected: `${queryResult.document_type.eq.expected}`,
|
|
509
|
-
received: `${disclosedDataPassport.documentType}`,
|
|
519
|
+
received: `${disclosedDataPassport.documentType ?? disclosedDataIDCard.documentType}`,
|
|
510
520
|
message: "Document type does not match the expected document type",
|
|
511
521
|
};
|
|
512
522
|
}
|
|
@@ -515,7 +525,7 @@ export class ZKPassport {
|
|
|
515
525
|
isCorrect = false;
|
|
516
526
|
queryResultErrors.document_type.disclose = {
|
|
517
527
|
expected: `${queryResult.document_type.disclose?.result}`,
|
|
518
|
-
received: `${disclosedDataIDCard.documentType}`,
|
|
528
|
+
received: `${disclosedDataIDCard.documentType ?? disclosedDataPassport.documentType}`,
|
|
519
529
|
message: "Document type does not match the disclosed document type in query result",
|
|
520
530
|
};
|
|
521
531
|
}
|
|
@@ -531,7 +541,7 @@ export class ZKPassport {
|
|
|
531
541
|
isCorrect = false;
|
|
532
542
|
queryResultErrors.birthdate.eq = {
|
|
533
543
|
expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
|
|
534
|
-
received: `${birthdatePassport
|
|
544
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
535
545
|
message: "Birthdate does not match the expected birthdate",
|
|
536
546
|
};
|
|
537
547
|
}
|
|
@@ -542,7 +552,7 @@ export class ZKPassport {
|
|
|
542
552
|
isCorrect = false;
|
|
543
553
|
queryResultErrors.birthdate.disclose = {
|
|
544
554
|
expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
|
|
545
|
-
received: `${birthdatePassport
|
|
555
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
546
556
|
message: "Birthdate does not match the disclosed birthdate in query result",
|
|
547
557
|
};
|
|
548
558
|
}
|
|
@@ -558,7 +568,7 @@ export class ZKPassport {
|
|
|
558
568
|
isCorrect = false;
|
|
559
569
|
queryResultErrors.expiry_date.eq = {
|
|
560
570
|
expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
|
|
561
|
-
received: `${expiryDatePassport
|
|
571
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
562
572
|
message: "Expiry date does not match the expected expiry date",
|
|
563
573
|
};
|
|
564
574
|
}
|
|
@@ -569,7 +579,7 @@ export class ZKPassport {
|
|
|
569
579
|
isCorrect = false;
|
|
570
580
|
queryResultErrors.expiry_date.disclose = {
|
|
571
581
|
expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
|
|
572
|
-
received: `${expiryDatePassport
|
|
582
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
573
583
|
message: "Expiry date does not match the disclosed expiry date in query result",
|
|
574
584
|
};
|
|
575
585
|
}
|
|
@@ -585,7 +595,7 @@ export class ZKPassport {
|
|
|
585
595
|
isCorrect = false;
|
|
586
596
|
queryResultErrors.nationality.eq = {
|
|
587
597
|
expected: `${queryResult.nationality.eq.expected}`,
|
|
588
|
-
received: `${nationalityPassport}`,
|
|
598
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
589
599
|
message: "Nationality does not match the expected nationality",
|
|
590
600
|
};
|
|
591
601
|
}
|
|
@@ -596,7 +606,7 @@ export class ZKPassport {
|
|
|
596
606
|
isCorrect = false;
|
|
597
607
|
queryResultErrors.nationality.disclose = {
|
|
598
608
|
expected: `${queryResult.nationality.disclose.result}`,
|
|
599
|
-
received: `${nationalityPassport}`,
|
|
609
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
600
610
|
message: "Nationality does not match the disclosed nationality in query result",
|
|
601
611
|
};
|
|
602
612
|
}
|
|
@@ -612,7 +622,7 @@ export class ZKPassport {
|
|
|
612
622
|
isCorrect = false;
|
|
613
623
|
queryResultErrors.document_number.eq = {
|
|
614
624
|
expected: `${queryResult.document_number.eq.expected}`,
|
|
615
|
-
received: `${documentNumberPassport}`,
|
|
625
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
616
626
|
message: "Document number does not match the expected document number",
|
|
617
627
|
};
|
|
618
628
|
}
|
|
@@ -623,7 +633,7 @@ export class ZKPassport {
|
|
|
623
633
|
isCorrect = false;
|
|
624
634
|
queryResultErrors.document_number.disclose = {
|
|
625
635
|
expected: `${queryResult.document_number.disclose.result}`,
|
|
626
|
-
received: `${documentNumberPassport}`,
|
|
636
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
627
637
|
message: "Document number does not match the disclosed document number in query result",
|
|
628
638
|
};
|
|
629
639
|
}
|
|
@@ -639,7 +649,7 @@ export class ZKPassport {
|
|
|
639
649
|
isCorrect = false;
|
|
640
650
|
queryResultErrors.gender.eq = {
|
|
641
651
|
expected: `${queryResult.gender.eq.expected}`,
|
|
642
|
-
received: `${genderPassport}`,
|
|
652
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
643
653
|
message: "Gender does not match the expected gender",
|
|
644
654
|
};
|
|
645
655
|
}
|
|
@@ -650,7 +660,7 @@ export class ZKPassport {
|
|
|
650
660
|
isCorrect = false;
|
|
651
661
|
queryResultErrors.gender.disclose = {
|
|
652
662
|
expected: `${queryResult.gender.disclose.result}`,
|
|
653
|
-
received: `${genderPassport}`,
|
|
663
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
654
664
|
message: "Gender does not match the disclosed gender in query result",
|
|
655
665
|
};
|
|
656
666
|
}
|
|
@@ -666,7 +676,7 @@ export class ZKPassport {
|
|
|
666
676
|
isCorrect = false;
|
|
667
677
|
queryResultErrors.issuing_country.eq = {
|
|
668
678
|
expected: `${queryResult.issuing_country.eq.expected}`,
|
|
669
|
-
received: `${issuingCountryPassport}`,
|
|
679
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
670
680
|
message: "Issuing country does not match the expected issuing country",
|
|
671
681
|
};
|
|
672
682
|
}
|
|
@@ -677,7 +687,7 @@ export class ZKPassport {
|
|
|
677
687
|
isCorrect = false;
|
|
678
688
|
queryResultErrors.issuing_country.disclose = {
|
|
679
689
|
expected: `${queryResult.issuing_country.disclose.result}`,
|
|
680
|
-
received: `${issuingCountryPassport}`,
|
|
690
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
681
691
|
message: "Issuing country does not match the disclosed issuing country in query result",
|
|
682
692
|
};
|
|
683
693
|
}
|
|
@@ -695,7 +705,7 @@ export class ZKPassport {
|
|
|
695
705
|
isCorrect = false;
|
|
696
706
|
queryResultErrors.fullname.eq = {
|
|
697
707
|
expected: `${queryResult.fullname.eq.expected}`,
|
|
698
|
-
received: `${fullnamePassport}`,
|
|
708
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
699
709
|
message: "Fullname does not match the expected fullname",
|
|
700
710
|
};
|
|
701
711
|
}
|
|
@@ -708,7 +718,7 @@ export class ZKPassport {
|
|
|
708
718
|
isCorrect = false;
|
|
709
719
|
queryResultErrors.fullname.disclose = {
|
|
710
720
|
expected: `${queryResult.fullname.disclose.result}`,
|
|
711
|
-
received: `${fullnamePassport}`,
|
|
721
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
712
722
|
message: "Fullname does not match the disclosed fullname in query result",
|
|
713
723
|
};
|
|
714
724
|
}
|
|
@@ -731,7 +741,7 @@ export class ZKPassport {
|
|
|
731
741
|
isCorrect = false;
|
|
732
742
|
queryResultErrors.firstname.eq = {
|
|
733
743
|
expected: `${queryResult.firstname.eq.expected}`,
|
|
734
|
-
received: `${firstnamePassport}`,
|
|
744
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
735
745
|
message: "Firstname does not match the expected firstname",
|
|
736
746
|
};
|
|
737
747
|
}
|
|
@@ -744,7 +754,7 @@ export class ZKPassport {
|
|
|
744
754
|
isCorrect = false;
|
|
745
755
|
queryResultErrors.firstname.disclose = {
|
|
746
756
|
expected: `${queryResult.firstname.disclose.result}`,
|
|
747
|
-
received: `${firstnamePassport}`,
|
|
757
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
748
758
|
message: "Firstname does not match the disclosed firstname in query result",
|
|
749
759
|
};
|
|
750
760
|
}
|
|
@@ -767,7 +777,7 @@ export class ZKPassport {
|
|
|
767
777
|
isCorrect = false;
|
|
768
778
|
queryResultErrors.lastname.eq = {
|
|
769
779
|
expected: `${queryResult.lastname.eq.expected}`,
|
|
770
|
-
received: `${lastnamePassport}`,
|
|
780
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
771
781
|
message: "Lastname does not match the expected lastname",
|
|
772
782
|
};
|
|
773
783
|
}
|
|
@@ -780,7 +790,7 @@ export class ZKPassport {
|
|
|
780
790
|
isCorrect = false;
|
|
781
791
|
queryResultErrors.lastname.disclose = {
|
|
782
792
|
expected: `${queryResult.lastname.disclose.result}`,
|
|
783
|
-
received: `${lastnamePassport}`,
|
|
793
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
784
794
|
message: "Lastname does not match the disclosed lastname in query result",
|
|
785
795
|
};
|
|
786
796
|
}
|
|
@@ -884,7 +894,7 @@ export class ZKPassport {
|
|
|
884
894
|
message: "Current date in the proof is too old",
|
|
885
895
|
};
|
|
886
896
|
}
|
|
887
|
-
uniqueIdentifier =
|
|
897
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
888
898
|
}
|
|
889
899
|
else if (proof.name === "compare_birthdate") {
|
|
890
900
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
@@ -965,7 +975,7 @@ export class ZKPassport {
|
|
|
965
975
|
message: "Birthdate is not set in the query result",
|
|
966
976
|
};
|
|
967
977
|
}
|
|
968
|
-
uniqueIdentifier =
|
|
978
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
969
979
|
}
|
|
970
980
|
else if (proof.name === "compare_expiry") {
|
|
971
981
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
@@ -1048,15 +1058,15 @@ export class ZKPassport {
|
|
|
1048
1058
|
}
|
|
1049
1059
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1050
1060
|
}
|
|
1051
|
-
else if (proof.name === "
|
|
1061
|
+
else if (proof.name === "exclusion_check_nationality") {
|
|
1052
1062
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1053
1063
|
if (commitmentIn !== commitmentOut) {
|
|
1054
|
-
console.warn("Failed to check the link between the validity of the ID and the
|
|
1064
|
+
console.warn("Failed to check the link between the validity of the ID and the nationality exclusion check");
|
|
1055
1065
|
isCorrect = false;
|
|
1056
1066
|
queryResultErrors.nationality.commitment = {
|
|
1057
1067
|
expected: `Commitment: ${commitmentOut}`,
|
|
1058
1068
|
received: `Commitment: ${commitmentIn}`,
|
|
1059
|
-
message: "Failed to check the link between the validity of the ID and the
|
|
1069
|
+
message: "Failed to check the link between the validity of the ID and the nationality exclusion check",
|
|
1060
1070
|
};
|
|
1061
1071
|
}
|
|
1062
1072
|
const countryList = getCountryListFromExclusionProof(proofData);
|
|
@@ -1064,12 +1074,12 @@ export class ZKPassport {
|
|
|
1064
1074
|
queryResult.nationality.out &&
|
|
1065
1075
|
queryResult.nationality.out.result) {
|
|
1066
1076
|
if (!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))) {
|
|
1067
|
-
console.warn("
|
|
1077
|
+
console.warn("Nationality exclusion list does not match the one from the query results");
|
|
1068
1078
|
isCorrect = false;
|
|
1069
1079
|
queryResultErrors.nationality.out = {
|
|
1070
1080
|
expected: queryResult.nationality.out.expected,
|
|
1071
1081
|
received: countryList,
|
|
1072
|
-
message: "
|
|
1082
|
+
message: "Nationality exclusion list does not match the one from the query results",
|
|
1073
1083
|
};
|
|
1074
1084
|
}
|
|
1075
1085
|
}
|
|
@@ -1094,15 +1104,61 @@ export class ZKPassport {
|
|
|
1094
1104
|
}
|
|
1095
1105
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1096
1106
|
}
|
|
1097
|
-
else if (proof.name === "
|
|
1107
|
+
else if (proof.name === "exclusion_check_issuing_country") {
|
|
1108
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1109
|
+
if (commitmentIn !== commitmentOut) {
|
|
1110
|
+
console.warn("Failed to check the link between the validity of the ID and the issuing country exclusion check");
|
|
1111
|
+
isCorrect = false;
|
|
1112
|
+
queryResultErrors.nationality.commitment = {
|
|
1113
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1114
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1115
|
+
message: "Failed to check the link between the validity of the ID and the issuing country exclusion check",
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
const countryList = getCountryListFromExclusionProof(proofData);
|
|
1119
|
+
if (queryResult.issuing_country &&
|
|
1120
|
+
queryResult.issuing_country.out &&
|
|
1121
|
+
queryResult.issuing_country.out.result) {
|
|
1122
|
+
if (!queryResult.issuing_country.out.expected?.every((country) => countryList.includes(country))) {
|
|
1123
|
+
console.warn("Issuing country exclusion list does not match the one from the query results");
|
|
1124
|
+
isCorrect = false;
|
|
1125
|
+
queryResultErrors.issuing_country.out = {
|
|
1126
|
+
expected: queryResult.issuing_country.out.expected,
|
|
1127
|
+
received: countryList,
|
|
1128
|
+
message: "Issuing country exclusion list does not match the one from the query results",
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
else if (!queryResult.issuing_country || !queryResult.issuing_country.out) {
|
|
1133
|
+
console.warn("Issuing country exclusion is not set in the query result");
|
|
1134
|
+
isCorrect = false;
|
|
1135
|
+
queryResultErrors.issuing_country.out = {
|
|
1136
|
+
message: "Issuing country exclusion is not set in the query result",
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
// Check the countryList is in ascending order
|
|
1140
|
+
// If the prover doesn't use a sorted list then the proof cannot be trusted
|
|
1141
|
+
// as it is requirement in the circuit for the exclusion check to work
|
|
1142
|
+
for (let i = 1; i < countryList.length; i++) {
|
|
1143
|
+
if (countryList[i] < countryList[i - 1]) {
|
|
1144
|
+
console.warn("The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted");
|
|
1145
|
+
isCorrect = false;
|
|
1146
|
+
queryResultErrors.issuing_country.out = {
|
|
1147
|
+
message: "The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1152
|
+
}
|
|
1153
|
+
else if (proof.name === "inclusion_check_nationality") {
|
|
1098
1154
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1099
1155
|
if (commitmentIn !== commitmentOut) {
|
|
1100
|
-
console.warn("Failed to check the link between the validity of the ID and the
|
|
1156
|
+
console.warn("Failed to check the link between the validity of the ID and the nationality inclusion check");
|
|
1101
1157
|
isCorrect = false;
|
|
1102
1158
|
queryResultErrors.nationality.commitment = {
|
|
1103
1159
|
expected: `Commitment: ${commitmentOut}`,
|
|
1104
1160
|
received: `Commitment: ${commitmentIn}`,
|
|
1105
|
-
message: "Failed to check the link between the validity of the ID and the
|
|
1161
|
+
message: "Failed to check the link between the validity of the ID and the nationality inclusion check",
|
|
1106
1162
|
};
|
|
1107
1163
|
}
|
|
1108
1164
|
const countryList = getCountryListFromInclusionProof(proofData);
|
|
@@ -1110,12 +1166,12 @@ export class ZKPassport {
|
|
|
1110
1166
|
queryResult.nationality.in &&
|
|
1111
1167
|
queryResult.nationality.in.result) {
|
|
1112
1168
|
if (!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))) {
|
|
1113
|
-
console.warn("
|
|
1169
|
+
console.warn("Nationality inclusion list does not match the one from the query results");
|
|
1114
1170
|
isCorrect = false;
|
|
1115
1171
|
queryResultErrors.nationality.in = {
|
|
1116
1172
|
expected: queryResult.nationality.in.expected,
|
|
1117
1173
|
received: countryList,
|
|
1118
|
-
message: "
|
|
1174
|
+
message: "Nationality inclusion list does not match the one from the query results",
|
|
1119
1175
|
};
|
|
1120
1176
|
}
|
|
1121
1177
|
}
|
|
@@ -1128,40 +1184,64 @@ export class ZKPassport {
|
|
|
1128
1184
|
}
|
|
1129
1185
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1130
1186
|
}
|
|
1187
|
+
else if (proof.name === "inclusion_check_issuing_country") {
|
|
1188
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1189
|
+
if (commitmentIn !== commitmentOut) {
|
|
1190
|
+
console.warn("Failed to check the link between the validity of the ID and the issuing country inclusion check");
|
|
1191
|
+
isCorrect = false;
|
|
1192
|
+
queryResultErrors.nationality.commitment = {
|
|
1193
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1194
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1195
|
+
message: "Failed to check the link between the validity of the ID and the issuing country inclusion check",
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
const countryList = getCountryListFromInclusionProof(proofData);
|
|
1199
|
+
if (queryResult.issuing_country &&
|
|
1200
|
+
queryResult.issuing_country.in &&
|
|
1201
|
+
queryResult.issuing_country.in.result) {
|
|
1202
|
+
if (!queryResult.issuing_country.in.expected?.every((country) => countryList.includes(country))) {
|
|
1203
|
+
console.warn("Issuing country inclusion list does not match the one from the query results");
|
|
1204
|
+
isCorrect = false;
|
|
1205
|
+
queryResultErrors.issuing_country.in = {
|
|
1206
|
+
expected: queryResult.issuing_country.in.expected,
|
|
1207
|
+
received: countryList,
|
|
1208
|
+
message: "Issuing country inclusion list does not match the one from the query results",
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
else if (!queryResult.issuing_country || !queryResult.issuing_country.in) {
|
|
1213
|
+
console.warn("Issuing country inclusion is not set in the query result");
|
|
1214
|
+
isCorrect = false;
|
|
1215
|
+
queryResultErrors.issuing_country.in = {
|
|
1216
|
+
message: "Issuing country inclusion is not set in the query result",
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1220
|
+
}
|
|
1131
1221
|
}
|
|
1132
1222
|
return { isCorrect, uniqueIdentifier, queryResultErrors };
|
|
1133
1223
|
}
|
|
1134
1224
|
/**
|
|
1135
1225
|
* @notice Verify the proofs received from the mobile app.
|
|
1136
|
-
* @param requestId The request ID.
|
|
1137
1226
|
* @param proofs The proofs to verify.
|
|
1138
1227
|
* @param queryResult The query result to verify against
|
|
1228
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
1139
1229
|
* @returns An object containing the unique identifier associated to the user
|
|
1140
1230
|
* and a boolean indicating whether the proofs were successfully verified.
|
|
1141
1231
|
*/
|
|
1142
|
-
async verify(
|
|
1143
|
-
let proofsToVerify = proofs;
|
|
1144
|
-
// There is a minimum of 4 subproofs to make a complete proof
|
|
1145
|
-
if (!proofs || proofs.length < 4) {
|
|
1146
|
-
proofsToVerify = this.topicToProofs[requestId];
|
|
1147
|
-
}
|
|
1232
|
+
async verify({ proofs, queryResult, validity, }) {
|
|
1148
1233
|
const { BarretenbergVerifier } = await import("@aztec/bb.js");
|
|
1149
1234
|
const verifier = new BarretenbergVerifier();
|
|
1150
|
-
/*if (!this.wasmVerifierInit) {
|
|
1151
|
-
await this.initWasmVerifier()
|
|
1152
|
-
}*/
|
|
1153
1235
|
let verified = true;
|
|
1154
1236
|
let uniqueIdentifier;
|
|
1155
1237
|
let queryResultErrors;
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
|
|
1161
|
-
}
|
|
1238
|
+
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofs, queryResult, validity);
|
|
1239
|
+
uniqueIdentifier = uniqueIdentifierFromPublicInputs;
|
|
1240
|
+
verified = isCorrect;
|
|
1241
|
+
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
|
|
1162
1242
|
// Only proceed with the proof verification if the public inputs are correct
|
|
1163
|
-
if (verified
|
|
1164
|
-
for (const proof of
|
|
1243
|
+
if (verified) {
|
|
1244
|
+
for (const proof of proofs) {
|
|
1165
1245
|
const proofData = getProofData(proof.proof, true);
|
|
1166
1246
|
const hostedPackagedCircuit = await getHostedPackagedCircuitByName(proof.version, proof.name);
|
|
1167
1247
|
const vkeyBytes = Buffer.from(hostedPackagedCircuit.vkey, "base64");
|
|
@@ -1179,7 +1259,8 @@ export class ZKPassport {
|
|
|
1179
1259
|
}
|
|
1180
1260
|
}
|
|
1181
1261
|
}
|
|
1182
|
-
|
|
1262
|
+
// If the proofs are not verified, we don't return the unique identifier
|
|
1263
|
+
uniqueIdentifier = verified ? uniqueIdentifier : undefined;
|
|
1183
1264
|
return { uniqueIdentifier, verified, queryResultErrors };
|
|
1184
1265
|
}
|
|
1185
1266
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkpassport/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "Privacy-preserving identity verification using passports and ID cards",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"typescript": "^5.6.2"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@aztec/bb.js": "^0.
|
|
41
|
+
"@aztec/bb.js": "^0.76.4",
|
|
42
42
|
"@noble/ciphers": "^1.2.1",
|
|
43
43
|
"@noble/secp256k1": "^2.2.3",
|
|
44
|
-
"@zkpassport/utils": "^0.2.
|
|
44
|
+
"@zkpassport/utils": "^0.2.23",
|
|
45
45
|
"buffer": "^6.0.3",
|
|
46
46
|
"i18n-iso-countries": "^7.12.0",
|
|
47
47
|
"pako": "^2.1.0",
|