@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/src/index.ts
CHANGED
|
@@ -38,8 +38,6 @@ import { createEncryptedJsonRpcRequest } from "./json-rpc"
|
|
|
38
38
|
import { decrypt, generateECDHKeyPair, getSharedSecret } from "./encryption"
|
|
39
39
|
import { noLogger as logger } from "./logger"
|
|
40
40
|
import { inflate } from "pako"
|
|
41
|
-
//import initNoirC from '@noir-lang/noirc_abi'
|
|
42
|
-
//import initACVM from '@noir-lang/acvm_js'
|
|
43
41
|
import i18en from "i18n-iso-countries/langs/en.json"
|
|
44
42
|
import { Buffer } from "buffer/"
|
|
45
43
|
|
|
@@ -263,13 +261,19 @@ export type QueryBuilder = {
|
|
|
263
261
|
* @param key The attribute to compare.
|
|
264
262
|
* @param value The list of values to check inclusion against.
|
|
265
263
|
*/
|
|
266
|
-
in: <T extends "nationality"
|
|
264
|
+
in: <T extends "nationality" | "issuing_country">(
|
|
265
|
+
key: T,
|
|
266
|
+
value: IDCredentialValue<T>[],
|
|
267
|
+
) => QueryBuilder
|
|
267
268
|
/**
|
|
268
269
|
* Requires this attribute to be excluded from the provided list.
|
|
269
270
|
* @param key The attribute to compare.
|
|
270
271
|
* @param value The list of values to check exclusion against.
|
|
271
272
|
*/
|
|
272
|
-
out: <T extends "nationality"
|
|
273
|
+
out: <T extends "nationality" | "issuing_country">(
|
|
274
|
+
key: T,
|
|
275
|
+
value: IDCredentialValue<T>[],
|
|
276
|
+
) => QueryBuilder
|
|
273
277
|
/**
|
|
274
278
|
* Requires this attribute to be disclosed.
|
|
275
279
|
* @param key The attribute to disclose.
|
|
@@ -333,23 +337,17 @@ export class ZKPassport {
|
|
|
333
337
|
this.domain = _domain || window.location.hostname
|
|
334
338
|
}
|
|
335
339
|
|
|
336
|
-
/*private async initWasmVerifier() {
|
|
337
|
-
const acvm = await import('@noir-lang/acvm_js/web/acvm_js_bg.wasm')
|
|
338
|
-
const noirc = await import('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm')
|
|
339
|
-
await Promise.all([initACVM(acvm), initNoirC(noirc)])
|
|
340
|
-
this.wasmVerifierInit = true
|
|
341
|
-
}*/
|
|
342
|
-
|
|
343
340
|
private async handleResult(topic: string) {
|
|
344
341
|
const result = this.topicToResults[topic]
|
|
345
342
|
// Clear the results straight away to avoid concurrency issues
|
|
346
343
|
delete this.topicToResults[topic]
|
|
347
344
|
// Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
|
|
348
|
-
const { uniqueIdentifier, verified, queryResultErrors } = await this.verify(
|
|
349
|
-
topic,
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
345
|
+
const { uniqueIdentifier, verified, queryResultErrors } = await this.verify({
|
|
346
|
+
proofs: this.topicToProofs[topic],
|
|
347
|
+
queryResult: result,
|
|
348
|
+
validity: this.topicToLocalConfig[topic]?.validity,
|
|
349
|
+
})
|
|
350
|
+
delete this.topicToProofs[topic]
|
|
353
351
|
const hasFailedProofs = this.topicToFailedProofCount[topic] > 0
|
|
354
352
|
await Promise.all(
|
|
355
353
|
this.onResultCallbacks[topic].map((callback) =>
|
|
@@ -399,13 +397,29 @@ export class ZKPassport {
|
|
|
399
397
|
}
|
|
400
398
|
break
|
|
401
399
|
case "in":
|
|
402
|
-
if (
|
|
403
|
-
|
|
400
|
+
if (
|
|
401
|
+
field === "nationality" &&
|
|
402
|
+
!neededCircuits.includes("inclusion_check_nationality")
|
|
403
|
+
) {
|
|
404
|
+
neededCircuits.push("inclusion_check_nationality")
|
|
405
|
+
} else if (
|
|
406
|
+
field === "issuing_country" &&
|
|
407
|
+
!neededCircuits.includes("inclusion_check_issuing_country")
|
|
408
|
+
) {
|
|
409
|
+
neededCircuits.push("inclusion_check_issuing_country")
|
|
404
410
|
}
|
|
405
411
|
break
|
|
406
412
|
case "out":
|
|
407
|
-
if (
|
|
408
|
-
|
|
413
|
+
if (
|
|
414
|
+
field === "nationality" &&
|
|
415
|
+
!neededCircuits.includes("exclusion_check_nationality")
|
|
416
|
+
) {
|
|
417
|
+
neededCircuits.push("exclusion_check_nationality")
|
|
418
|
+
} else if (
|
|
419
|
+
field === "issuing_country" &&
|
|
420
|
+
!neededCircuits.includes("exclusion_check_issuing_country")
|
|
421
|
+
) {
|
|
422
|
+
neededCircuits.push("exclusion_check_issuing_country")
|
|
409
423
|
}
|
|
410
424
|
break
|
|
411
425
|
}
|
|
@@ -532,12 +546,12 @@ export class ZKPassport {
|
|
|
532
546
|
rangeCompare(key, [start, end], topic, this.topicToConfig)
|
|
533
547
|
return this.getZkPassportRequest(topic)
|
|
534
548
|
},
|
|
535
|
-
in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => {
|
|
549
|
+
in: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => {
|
|
536
550
|
value = value.map((v) => normalizeCountry(v as CountryName)) as IDCredentialValue<T>[]
|
|
537
551
|
generalCompare("in", key, value, topic, this.topicToConfig)
|
|
538
552
|
return this.getZkPassportRequest(topic)
|
|
539
553
|
},
|
|
540
|
-
out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => {
|
|
554
|
+
out: <T extends "nationality" | "issuing_country">(key: T, value: IDCredentialValue<T>[]) => {
|
|
541
555
|
value = value.map((v) => normalizeCountry(v as CountryName)) as IDCredentialValue<T>[]
|
|
542
556
|
generalCompare("out", key, value, topic, this.topicToConfig)
|
|
543
557
|
return this.getZkPassportRequest(topic)
|
|
@@ -706,7 +720,7 @@ export class ZKPassport {
|
|
|
706
720
|
private async checkPublicInputs(
|
|
707
721
|
proofs: Array<ProofResult>,
|
|
708
722
|
queryResult: QueryResult,
|
|
709
|
-
|
|
723
|
+
validity?: number,
|
|
710
724
|
) {
|
|
711
725
|
let commitmentIn: bigint | undefined
|
|
712
726
|
let commitmentOut: bigint | undefined
|
|
@@ -755,8 +769,10 @@ export class ZKPassport {
|
|
|
755
769
|
"compare_age",
|
|
756
770
|
"compare_birthdate",
|
|
757
771
|
"compare_expiry",
|
|
758
|
-
"
|
|
759
|
-
"
|
|
772
|
+
"exclusion_check_nationality",
|
|
773
|
+
"inclusion_check_nationality",
|
|
774
|
+
"exclusion_check_issuing_country",
|
|
775
|
+
"inclusion_check_issuing_country",
|
|
760
776
|
]
|
|
761
777
|
const getIndex = (proof: ProofResult) => {
|
|
762
778
|
const name = proof.name || ""
|
|
@@ -807,16 +823,17 @@ export class ZKPassport {
|
|
|
807
823
|
commitmentOut = getCommitmentOutFromIntegrityProof(proofData)
|
|
808
824
|
const currentDate = getCurrentDateFromIntegrityProof(proofData)
|
|
809
825
|
const todayToCurrentDate = today.getTime() - currentDate.getTime()
|
|
810
|
-
const
|
|
826
|
+
const differenceInDays = validity ?? 180
|
|
827
|
+
const expectedDifference = differenceInDays * 86400000
|
|
811
828
|
const actualDifference = today.getTime() - (today.getTime() - expectedDifference)
|
|
812
829
|
// The ID should not expire within the next 6 months (or whatever the custom value is)
|
|
813
830
|
if (todayToCurrentDate >= actualDifference) {
|
|
814
831
|
console.warn(
|
|
815
|
-
`The date used to check the validity of the ID is older than ${
|
|
832
|
+
`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`,
|
|
816
833
|
)
|
|
817
834
|
isCorrect = false
|
|
818
835
|
queryResultErrors.data_check_integrity.date = {
|
|
819
|
-
expected: `Difference: ${
|
|
836
|
+
expected: `Difference: ${differenceInDays} days`,
|
|
820
837
|
received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
|
|
821
838
|
message:
|
|
822
839
|
"The date used to check the validity of the ID is older than the validity period",
|
|
@@ -851,7 +868,7 @@ export class ZKPassport {
|
|
|
851
868
|
isCorrect = false
|
|
852
869
|
queryResultErrors.document_type.eq = {
|
|
853
870
|
expected: `${queryResult.document_type.eq.expected}`,
|
|
854
|
-
received: `${disclosedDataPassport.documentType}`,
|
|
871
|
+
received: `${disclosedDataPassport.documentType ?? disclosedDataIDCard.documentType}`,
|
|
855
872
|
message: "Document type does not match the expected document type",
|
|
856
873
|
}
|
|
857
874
|
}
|
|
@@ -860,7 +877,7 @@ export class ZKPassport {
|
|
|
860
877
|
isCorrect = false
|
|
861
878
|
queryResultErrors.document_type.disclose = {
|
|
862
879
|
expected: `${queryResult.document_type.disclose?.result}`,
|
|
863
|
-
received: `${disclosedDataIDCard.documentType}`,
|
|
880
|
+
received: `${disclosedDataIDCard.documentType ?? disclosedDataPassport.documentType}`,
|
|
864
881
|
message: "Document type does not match the disclosed document type in query result",
|
|
865
882
|
}
|
|
866
883
|
}
|
|
@@ -878,7 +895,7 @@ export class ZKPassport {
|
|
|
878
895
|
isCorrect = false
|
|
879
896
|
queryResultErrors.birthdate.eq = {
|
|
880
897
|
expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
|
|
881
|
-
received: `${birthdatePassport
|
|
898
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
882
899
|
message: "Birthdate does not match the expected birthdate",
|
|
883
900
|
}
|
|
884
901
|
}
|
|
@@ -891,7 +908,7 @@ export class ZKPassport {
|
|
|
891
908
|
isCorrect = false
|
|
892
909
|
queryResultErrors.birthdate.disclose = {
|
|
893
910
|
expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
|
|
894
|
-
received: `${birthdatePassport
|
|
911
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
895
912
|
message: "Birthdate does not match the disclosed birthdate in query result",
|
|
896
913
|
}
|
|
897
914
|
}
|
|
@@ -909,7 +926,7 @@ export class ZKPassport {
|
|
|
909
926
|
isCorrect = false
|
|
910
927
|
queryResultErrors.expiry_date.eq = {
|
|
911
928
|
expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
|
|
912
|
-
received: `${expiryDatePassport
|
|
929
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
913
930
|
message: "Expiry date does not match the expected expiry date",
|
|
914
931
|
}
|
|
915
932
|
}
|
|
@@ -922,7 +939,7 @@ export class ZKPassport {
|
|
|
922
939
|
isCorrect = false
|
|
923
940
|
queryResultErrors.expiry_date.disclose = {
|
|
924
941
|
expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
|
|
925
|
-
received: `${expiryDatePassport
|
|
942
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
926
943
|
message: "Expiry date does not match the disclosed expiry date in query result",
|
|
927
944
|
}
|
|
928
945
|
}
|
|
@@ -940,7 +957,7 @@ export class ZKPassport {
|
|
|
940
957
|
isCorrect = false
|
|
941
958
|
queryResultErrors.nationality.eq = {
|
|
942
959
|
expected: `${queryResult.nationality.eq.expected}`,
|
|
943
|
-
received: `${nationalityPassport}`,
|
|
960
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
944
961
|
message: "Nationality does not match the expected nationality",
|
|
945
962
|
}
|
|
946
963
|
}
|
|
@@ -953,7 +970,7 @@ export class ZKPassport {
|
|
|
953
970
|
isCorrect = false
|
|
954
971
|
queryResultErrors.nationality.disclose = {
|
|
955
972
|
expected: `${queryResult.nationality.disclose.result}`,
|
|
956
|
-
received: `${nationalityPassport}`,
|
|
973
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
957
974
|
message: "Nationality does not match the disclosed nationality in query result",
|
|
958
975
|
}
|
|
959
976
|
}
|
|
@@ -971,7 +988,7 @@ export class ZKPassport {
|
|
|
971
988
|
isCorrect = false
|
|
972
989
|
queryResultErrors.document_number.eq = {
|
|
973
990
|
expected: `${queryResult.document_number.eq.expected}`,
|
|
974
|
-
received: `${documentNumberPassport}`,
|
|
991
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
975
992
|
message: "Document number does not match the expected document number",
|
|
976
993
|
}
|
|
977
994
|
}
|
|
@@ -986,7 +1003,7 @@ export class ZKPassport {
|
|
|
986
1003
|
isCorrect = false
|
|
987
1004
|
queryResultErrors.document_number.disclose = {
|
|
988
1005
|
expected: `${queryResult.document_number.disclose.result}`,
|
|
989
|
-
received: `${documentNumberPassport}`,
|
|
1006
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
990
1007
|
message:
|
|
991
1008
|
"Document number does not match the disclosed document number in query result",
|
|
992
1009
|
}
|
|
@@ -1005,7 +1022,7 @@ export class ZKPassport {
|
|
|
1005
1022
|
isCorrect = false
|
|
1006
1023
|
queryResultErrors.gender.eq = {
|
|
1007
1024
|
expected: `${queryResult.gender.eq.expected}`,
|
|
1008
|
-
received: `${genderPassport}`,
|
|
1025
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
1009
1026
|
message: "Gender does not match the expected gender",
|
|
1010
1027
|
}
|
|
1011
1028
|
}
|
|
@@ -1018,7 +1035,7 @@ export class ZKPassport {
|
|
|
1018
1035
|
isCorrect = false
|
|
1019
1036
|
queryResultErrors.gender.disclose = {
|
|
1020
1037
|
expected: `${queryResult.gender.disclose.result}`,
|
|
1021
|
-
received: `${genderPassport}`,
|
|
1038
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
1022
1039
|
message: "Gender does not match the disclosed gender in query result",
|
|
1023
1040
|
}
|
|
1024
1041
|
}
|
|
@@ -1036,7 +1053,7 @@ export class ZKPassport {
|
|
|
1036
1053
|
isCorrect = false
|
|
1037
1054
|
queryResultErrors.issuing_country.eq = {
|
|
1038
1055
|
expected: `${queryResult.issuing_country.eq.expected}`,
|
|
1039
|
-
received: `${issuingCountryPassport}`,
|
|
1056
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
1040
1057
|
message: "Issuing country does not match the expected issuing country",
|
|
1041
1058
|
}
|
|
1042
1059
|
}
|
|
@@ -1051,7 +1068,7 @@ export class ZKPassport {
|
|
|
1051
1068
|
isCorrect = false
|
|
1052
1069
|
queryResultErrors.issuing_country.disclose = {
|
|
1053
1070
|
expected: `${queryResult.issuing_country.disclose.result}`,
|
|
1054
|
-
received: `${issuingCountryPassport}`,
|
|
1071
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
1055
1072
|
message:
|
|
1056
1073
|
"Issuing country does not match the disclosed issuing country in query result",
|
|
1057
1074
|
}
|
|
@@ -1072,7 +1089,7 @@ export class ZKPassport {
|
|
|
1072
1089
|
isCorrect = false
|
|
1073
1090
|
queryResultErrors.fullname.eq = {
|
|
1074
1091
|
expected: `${queryResult.fullname.eq.expected}`,
|
|
1075
|
-
received: `${fullnamePassport}`,
|
|
1092
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
1076
1093
|
message: "Fullname does not match the expected fullname",
|
|
1077
1094
|
}
|
|
1078
1095
|
}
|
|
@@ -1087,7 +1104,7 @@ export class ZKPassport {
|
|
|
1087
1104
|
isCorrect = false
|
|
1088
1105
|
queryResultErrors.fullname.disclose = {
|
|
1089
1106
|
expected: `${queryResult.fullname.disclose.result}`,
|
|
1090
|
-
received: `${fullnamePassport}`,
|
|
1107
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
1091
1108
|
message: "Fullname does not match the disclosed fullname in query result",
|
|
1092
1109
|
}
|
|
1093
1110
|
}
|
|
@@ -1114,7 +1131,7 @@ export class ZKPassport {
|
|
|
1114
1131
|
isCorrect = false
|
|
1115
1132
|
queryResultErrors.firstname.eq = {
|
|
1116
1133
|
expected: `${queryResult.firstname.eq.expected}`,
|
|
1117
|
-
received: `${firstnamePassport}`,
|
|
1134
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
1118
1135
|
message: "Firstname does not match the expected firstname",
|
|
1119
1136
|
}
|
|
1120
1137
|
}
|
|
@@ -1129,7 +1146,7 @@ export class ZKPassport {
|
|
|
1129
1146
|
isCorrect = false
|
|
1130
1147
|
queryResultErrors.firstname.disclose = {
|
|
1131
1148
|
expected: `${queryResult.firstname.disclose.result}`,
|
|
1132
|
-
received: `${firstnamePassport}`,
|
|
1149
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
1133
1150
|
message: "Firstname does not match the disclosed firstname in query result",
|
|
1134
1151
|
}
|
|
1135
1152
|
}
|
|
@@ -1156,7 +1173,7 @@ export class ZKPassport {
|
|
|
1156
1173
|
isCorrect = false
|
|
1157
1174
|
queryResultErrors.lastname.eq = {
|
|
1158
1175
|
expected: `${queryResult.lastname.eq.expected}`,
|
|
1159
|
-
received: `${lastnamePassport}`,
|
|
1176
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
1160
1177
|
message: "Lastname does not match the expected lastname",
|
|
1161
1178
|
}
|
|
1162
1179
|
}
|
|
@@ -1171,7 +1188,7 @@ export class ZKPassport {
|
|
|
1171
1188
|
isCorrect = false
|
|
1172
1189
|
queryResultErrors.lastname.disclose = {
|
|
1173
1190
|
expected: `${queryResult.lastname.disclose.result}`,
|
|
1174
|
-
received: `${lastnamePassport}`,
|
|
1191
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
1175
1192
|
message: "Lastname does not match the disclosed lastname in query result",
|
|
1176
1193
|
}
|
|
1177
1194
|
}
|
|
@@ -1286,7 +1303,7 @@ export class ZKPassport {
|
|
|
1286
1303
|
message: "Current date in the proof is too old",
|
|
1287
1304
|
}
|
|
1288
1305
|
}
|
|
1289
|
-
uniqueIdentifier =
|
|
1306
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1290
1307
|
} else if (proof.name === "compare_birthdate") {
|
|
1291
1308
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1292
1309
|
if (commitmentIn !== commitmentOut) {
|
|
@@ -1378,7 +1395,7 @@ export class ZKPassport {
|
|
|
1378
1395
|
message: "Birthdate is not set in the query result",
|
|
1379
1396
|
}
|
|
1380
1397
|
}
|
|
1381
|
-
uniqueIdentifier =
|
|
1398
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1382
1399
|
} else if (proof.name === "compare_expiry") {
|
|
1383
1400
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1384
1401
|
if (commitmentIn !== commitmentOut) {
|
|
@@ -1470,18 +1487,18 @@ export class ZKPassport {
|
|
|
1470
1487
|
}
|
|
1471
1488
|
}
|
|
1472
1489
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1473
|
-
} else if (proof.name === "
|
|
1490
|
+
} else if (proof.name === "exclusion_check_nationality") {
|
|
1474
1491
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1475
1492
|
if (commitmentIn !== commitmentOut) {
|
|
1476
1493
|
console.warn(
|
|
1477
|
-
"Failed to check the link between the validity of the ID and the
|
|
1494
|
+
"Failed to check the link between the validity of the ID and the nationality exclusion check",
|
|
1478
1495
|
)
|
|
1479
1496
|
isCorrect = false
|
|
1480
1497
|
queryResultErrors.nationality.commitment = {
|
|
1481
1498
|
expected: `Commitment: ${commitmentOut}`,
|
|
1482
1499
|
received: `Commitment: ${commitmentIn}`,
|
|
1483
1500
|
message:
|
|
1484
|
-
"Failed to check the link between the validity of the ID and the
|
|
1501
|
+
"Failed to check the link between the validity of the ID and the nationality exclusion check",
|
|
1485
1502
|
}
|
|
1486
1503
|
}
|
|
1487
1504
|
const countryList = getCountryListFromExclusionProof(proofData)
|
|
@@ -1493,12 +1510,12 @@ export class ZKPassport {
|
|
|
1493
1510
|
if (
|
|
1494
1511
|
!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))
|
|
1495
1512
|
) {
|
|
1496
|
-
console.warn("
|
|
1513
|
+
console.warn("Nationality exclusion list does not match the one from the query results")
|
|
1497
1514
|
isCorrect = false
|
|
1498
1515
|
queryResultErrors.nationality.out = {
|
|
1499
1516
|
expected: queryResult.nationality.out.expected,
|
|
1500
1517
|
received: countryList,
|
|
1501
|
-
message: "
|
|
1518
|
+
message: "Nationality exclusion list does not match the one from the query results",
|
|
1502
1519
|
}
|
|
1503
1520
|
}
|
|
1504
1521
|
} else if (!queryResult.nationality || !queryResult.nationality.out) {
|
|
@@ -1524,18 +1541,77 @@ export class ZKPassport {
|
|
|
1524
1541
|
}
|
|
1525
1542
|
}
|
|
1526
1543
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1527
|
-
} else if (proof.name === "
|
|
1544
|
+
} else if (proof.name === "exclusion_check_issuing_country") {
|
|
1528
1545
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1529
1546
|
if (commitmentIn !== commitmentOut) {
|
|
1530
1547
|
console.warn(
|
|
1531
|
-
"Failed to check the link between the validity of the ID and the country
|
|
1548
|
+
"Failed to check the link between the validity of the ID and the issuing country exclusion check",
|
|
1532
1549
|
)
|
|
1533
1550
|
isCorrect = false
|
|
1534
1551
|
queryResultErrors.nationality.commitment = {
|
|
1535
1552
|
expected: `Commitment: ${commitmentOut}`,
|
|
1536
1553
|
received: `Commitment: ${commitmentIn}`,
|
|
1537
1554
|
message:
|
|
1538
|
-
"Failed to check the link between the validity of the ID and the country
|
|
1555
|
+
"Failed to check the link between the validity of the ID and the issuing country exclusion check",
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
const countryList = getCountryListFromExclusionProof(proofData)
|
|
1559
|
+
if (
|
|
1560
|
+
queryResult.issuing_country &&
|
|
1561
|
+
queryResult.issuing_country.out &&
|
|
1562
|
+
queryResult.issuing_country.out.result
|
|
1563
|
+
) {
|
|
1564
|
+
if (
|
|
1565
|
+
!queryResult.issuing_country.out.expected?.every((country) =>
|
|
1566
|
+
countryList.includes(country),
|
|
1567
|
+
)
|
|
1568
|
+
) {
|
|
1569
|
+
console.warn(
|
|
1570
|
+
"Issuing country exclusion list does not match the one from the query results",
|
|
1571
|
+
)
|
|
1572
|
+
isCorrect = false
|
|
1573
|
+
queryResultErrors.issuing_country.out = {
|
|
1574
|
+
expected: queryResult.issuing_country.out.expected,
|
|
1575
|
+
received: countryList,
|
|
1576
|
+
message:
|
|
1577
|
+
"Issuing country exclusion list does not match the one from the query results",
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
} else if (!queryResult.issuing_country || !queryResult.issuing_country.out) {
|
|
1581
|
+
console.warn("Issuing country exclusion is not set in the query result")
|
|
1582
|
+
isCorrect = false
|
|
1583
|
+
queryResultErrors.issuing_country.out = {
|
|
1584
|
+
message: "Issuing country exclusion is not set in the query result",
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
// Check the countryList is in ascending order
|
|
1588
|
+
// If the prover doesn't use a sorted list then the proof cannot be trusted
|
|
1589
|
+
// as it is requirement in the circuit for the exclusion check to work
|
|
1590
|
+
for (let i = 1; i < countryList.length; i++) {
|
|
1591
|
+
if (countryList[i] < countryList[i - 1]) {
|
|
1592
|
+
console.warn(
|
|
1593
|
+
"The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
|
|
1594
|
+
)
|
|
1595
|
+
isCorrect = false
|
|
1596
|
+
queryResultErrors.issuing_country.out = {
|
|
1597
|
+
message:
|
|
1598
|
+
"The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1603
|
+
} else if (proof.name === "inclusion_check_nationality") {
|
|
1604
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1605
|
+
if (commitmentIn !== commitmentOut) {
|
|
1606
|
+
console.warn(
|
|
1607
|
+
"Failed to check the link between the validity of the ID and the nationality inclusion check",
|
|
1608
|
+
)
|
|
1609
|
+
isCorrect = false
|
|
1610
|
+
queryResultErrors.nationality.commitment = {
|
|
1611
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1612
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1613
|
+
message:
|
|
1614
|
+
"Failed to check the link between the validity of the ID and the nationality inclusion check",
|
|
1539
1615
|
}
|
|
1540
1616
|
}
|
|
1541
1617
|
const countryList = getCountryListFromInclusionProof(proofData)
|
|
@@ -1547,12 +1623,12 @@ export class ZKPassport {
|
|
|
1547
1623
|
if (
|
|
1548
1624
|
!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))
|
|
1549
1625
|
) {
|
|
1550
|
-
console.warn("
|
|
1626
|
+
console.warn("Nationality inclusion list does not match the one from the query results")
|
|
1551
1627
|
isCorrect = false
|
|
1552
1628
|
queryResultErrors.nationality.in = {
|
|
1553
1629
|
expected: queryResult.nationality.in.expected,
|
|
1554
1630
|
received: countryList,
|
|
1555
|
-
message: "
|
|
1631
|
+
message: "Nationality inclusion list does not match the one from the query results",
|
|
1556
1632
|
}
|
|
1557
1633
|
}
|
|
1558
1634
|
} else if (!queryResult.nationality || !queryResult.nationality.in) {
|
|
@@ -1563,6 +1639,50 @@ export class ZKPassport {
|
|
|
1563
1639
|
}
|
|
1564
1640
|
}
|
|
1565
1641
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1642
|
+
} else if (proof.name === "inclusion_check_issuing_country") {
|
|
1643
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData)
|
|
1644
|
+
if (commitmentIn !== commitmentOut) {
|
|
1645
|
+
console.warn(
|
|
1646
|
+
"Failed to check the link between the validity of the ID and the issuing country inclusion check",
|
|
1647
|
+
)
|
|
1648
|
+
isCorrect = false
|
|
1649
|
+
queryResultErrors.nationality.commitment = {
|
|
1650
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1651
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1652
|
+
message:
|
|
1653
|
+
"Failed to check the link between the validity of the ID and the issuing country inclusion check",
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
const countryList = getCountryListFromInclusionProof(proofData)
|
|
1657
|
+
if (
|
|
1658
|
+
queryResult.issuing_country &&
|
|
1659
|
+
queryResult.issuing_country.in &&
|
|
1660
|
+
queryResult.issuing_country.in.result
|
|
1661
|
+
) {
|
|
1662
|
+
if (
|
|
1663
|
+
!queryResult.issuing_country.in.expected?.every((country) =>
|
|
1664
|
+
countryList.includes(country),
|
|
1665
|
+
)
|
|
1666
|
+
) {
|
|
1667
|
+
console.warn(
|
|
1668
|
+
"Issuing country inclusion list does not match the one from the query results",
|
|
1669
|
+
)
|
|
1670
|
+
isCorrect = false
|
|
1671
|
+
queryResultErrors.issuing_country.in = {
|
|
1672
|
+
expected: queryResult.issuing_country.in.expected,
|
|
1673
|
+
received: countryList,
|
|
1674
|
+
message:
|
|
1675
|
+
"Issuing country inclusion list does not match the one from the query results",
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
} else if (!queryResult.issuing_country || !queryResult.issuing_country.in) {
|
|
1679
|
+
console.warn("Issuing country inclusion is not set in the query result")
|
|
1680
|
+
isCorrect = false
|
|
1681
|
+
queryResultErrors.issuing_country.in = {
|
|
1682
|
+
message: "Issuing country inclusion is not set in the query result",
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10)
|
|
1566
1686
|
}
|
|
1567
1687
|
}
|
|
1568
1688
|
return { isCorrect, uniqueIdentifier, queryResultErrors }
|
|
@@ -1570,47 +1690,41 @@ export class ZKPassport {
|
|
|
1570
1690
|
|
|
1571
1691
|
/**
|
|
1572
1692
|
* @notice Verify the proofs received from the mobile app.
|
|
1573
|
-
* @param requestId The request ID.
|
|
1574
1693
|
* @param proofs The proofs to verify.
|
|
1575
1694
|
* @param queryResult The query result to verify against
|
|
1695
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
1576
1696
|
* @returns An object containing the unique identifier associated to the user
|
|
1577
1697
|
* and a boolean indicating whether the proofs were successfully verified.
|
|
1578
1698
|
*/
|
|
1579
|
-
public async verify(
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1699
|
+
public async verify({
|
|
1700
|
+
proofs,
|
|
1701
|
+
queryResult,
|
|
1702
|
+
validity,
|
|
1703
|
+
}: {
|
|
1704
|
+
proofs: Array<ProofResult>
|
|
1705
|
+
queryResult: QueryResult
|
|
1706
|
+
validity?: number
|
|
1707
|
+
}): Promise<{
|
|
1584
1708
|
uniqueIdentifier: string | undefined
|
|
1585
1709
|
verified: boolean
|
|
1586
1710
|
queryResultErrors?: QueryResultErrors
|
|
1587
1711
|
}> {
|
|
1588
|
-
let proofsToVerify = proofs
|
|
1589
|
-
// There is a minimum of 4 subproofs to make a complete proof
|
|
1590
|
-
if (!proofs || proofs.length < 4) {
|
|
1591
|
-
proofsToVerify = this.topicToProofs[requestId]
|
|
1592
|
-
}
|
|
1593
1712
|
const { BarretenbergVerifier } = await import("@aztec/bb.js")
|
|
1594
1713
|
const verifier = new BarretenbergVerifier()
|
|
1595
|
-
/*if (!this.wasmVerifierInit) {
|
|
1596
|
-
await this.initWasmVerifier()
|
|
1597
|
-
}*/
|
|
1598
1714
|
let verified = true
|
|
1599
1715
|
let uniqueIdentifier: string | undefined
|
|
1600
1716
|
let queryResultErrors: QueryResultErrors | undefined
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs
|
|
1610
|
-
}
|
|
1717
|
+
const {
|
|
1718
|
+
isCorrect,
|
|
1719
|
+
uniqueIdentifier: uniqueIdentifierFromPublicInputs,
|
|
1720
|
+
queryResultErrors: queryResultErrorsFromPublicInputs,
|
|
1721
|
+
} = await this.checkPublicInputs(proofs, queryResult, validity)
|
|
1722
|
+
uniqueIdentifier = uniqueIdentifierFromPublicInputs
|
|
1723
|
+
verified = isCorrect
|
|
1724
|
+
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs
|
|
1611
1725
|
// Only proceed with the proof verification if the public inputs are correct
|
|
1612
|
-
if (verified
|
|
1613
|
-
for (const proof of
|
|
1726
|
+
if (verified) {
|
|
1727
|
+
for (const proof of proofs) {
|
|
1614
1728
|
const proofData = getProofData(proof.proof as string, true)
|
|
1615
1729
|
const hostedPackagedCircuit = await getHostedPackagedCircuitByName(
|
|
1616
1730
|
proof.version as any,
|
|
@@ -1630,7 +1744,8 @@ export class ZKPassport {
|
|
|
1630
1744
|
}
|
|
1631
1745
|
}
|
|
1632
1746
|
}
|
|
1633
|
-
|
|
1747
|
+
// If the proofs are not verified, we don't return the unique identifier
|
|
1748
|
+
uniqueIdentifier = verified ? uniqueIdentifier : undefined
|
|
1634
1749
|
return { uniqueIdentifier, verified, queryResultErrors }
|
|
1635
1750
|
}
|
|
1636
1751
|
|