@zkpassport/sdk 0.4.0 → 0.4.1
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/assets/abi/ZKPassportVerifier.json +51 -9
- package/dist/cjs/index.d.ts +9 -2
- package/dist/cjs/index.js +116 -1
- package/dist/esm/assets/abi/ZKPassportVerifier.json +51 -9
- package/dist/esm/index.d.ts +9 -2
- package/dist/esm/index.js +117 -2
- package/package.json +2 -2
- package/src/assets/abi/ZKPassportVerifier.json +51 -9
- package/src/index.ts +136 -2
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type DisclosableIDCredential, type IDCredential, type IDCredentialValue, type NumericalIDCredential, type ProofResult, type QueryResult, ProofMode } from "@zkpassport/utils";
|
|
1
|
+
import { type DisclosableIDCredential, type IDCredential, type IDCredentialValue, type NumericalIDCredential, type ProofResult, type QueryResult, ProofMode, BoundData } from "@zkpassport/utils";
|
|
2
2
|
export type QueryResultError<T> = {
|
|
3
3
|
expected?: T;
|
|
4
4
|
received?: T;
|
|
5
5
|
message: string;
|
|
6
6
|
};
|
|
7
7
|
export type QueryResultErrors = {
|
|
8
|
-
[key in IDCredential | "sig_check_dsc" | "sig_check_id_data" | "data_check_integrity" | "outer" | "disclose"]: {
|
|
8
|
+
[key in IDCredential | "sig_check_dsc" | "sig_check_id_data" | "data_check_integrity" | "outer" | "disclose" | "bind"]: {
|
|
9
9
|
disclose?: QueryResultError<string | number | Date>;
|
|
10
10
|
gte?: QueryResultError<number | Date>;
|
|
11
11
|
lte?: QueryResultError<number | Date>;
|
|
@@ -150,6 +150,12 @@ export type QueryBuilder = {
|
|
|
150
150
|
* @param key The attribute to disclose.
|
|
151
151
|
*/
|
|
152
152
|
disclose: (key: DisclosableIDCredential) => QueryBuilder;
|
|
153
|
+
/**
|
|
154
|
+
* Binds a value to the request.
|
|
155
|
+
* @param key The key of the value to bind.
|
|
156
|
+
* @param value The value to bind the request to.
|
|
157
|
+
*/
|
|
158
|
+
bind: (key: keyof BoundData, value: BoundData[keyof BoundData]) => QueryBuilder;
|
|
153
159
|
/**
|
|
154
160
|
* Builds the request.
|
|
155
161
|
*
|
|
@@ -224,6 +230,7 @@ export declare class ZKPassport {
|
|
|
224
230
|
private checkIssuingCountryInclusionPublicInputs;
|
|
225
231
|
private checkScopeFromDisclosureProof;
|
|
226
232
|
private checkCertificateRegistryRoot;
|
|
233
|
+
private checkBindPublicInputs;
|
|
227
234
|
private checkPublicInputs;
|
|
228
235
|
/**
|
|
229
236
|
* @notice Verify the proofs received from the mobile app.
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getAlpha3Code, registerLocale } from "i18n-iso-countries";
|
|
2
|
-
import { getProofData, getCommitmentFromDSCProof, getCommitmentInFromIDDataProof, getCommitmentOutFromIDDataProof, getNullifierFromDisclosureProof, getCommitmentInFromIntegrityProof, getCommitmentOutFromIntegrityProof, getCommitmentInFromDisclosureProof, getMerkleRootFromDSCProof, getCurrentDateFromIntegrityProof, DisclosedData, formatName, getHostedPackagedCircuitByName, getNumberOfPublicInputs, getParameterCommitmentFromDisclosureProof, getCountryParameterCommitment, getDiscloseParameterCommitment, getDateParameterCommitment, getCertificateRegistryRootFromOuterProof, getParamCommitmentsFromOuterProof, getCurrentDateFromCommittedInputs, getMinAgeFromCommittedInputs, getMaxAgeFromCommittedInputs, getAgeParameterCommitment, getMinDateFromCommittedInputs, getMaxDateFromCommittedInputs, getCurrentDateFromOuterProof, getNullifierFromOuterProof, getAgeEVMParameterCommitment, getDateEVMParameterCommitment, getDiscloseEVMParameterCommitment, getCountryEVMParameterCommitment, rightPadArrayWithZeros, getCommittedInputCount, ProofType, getScopeHash, getScopeFromOuterProof, getSubscopeFromOuterProof, getServiceScopeHash, } from "@zkpassport/utils";
|
|
2
|
+
import { getProofData, getCommitmentFromDSCProof, getCommitmentInFromIDDataProof, getCommitmentOutFromIDDataProof, getNullifierFromDisclosureProof, getCommitmentInFromIntegrityProof, getCommitmentOutFromIntegrityProof, getCommitmentInFromDisclosureProof, getMerkleRootFromDSCProof, getCurrentDateFromIntegrityProof, DisclosedData, formatName, getHostedPackagedCircuitByName, getNumberOfPublicInputs, getParameterCommitmentFromDisclosureProof, getCountryParameterCommitment, getDiscloseParameterCommitment, getDateParameterCommitment, getCertificateRegistryRootFromOuterProof, getParamCommitmentsFromOuterProof, getCurrentDateFromCommittedInputs, getMinAgeFromCommittedInputs, getMaxAgeFromCommittedInputs, getAgeParameterCommitment, getMinDateFromCommittedInputs, getMaxDateFromCommittedInputs, getCurrentDateFromOuterProof, getNullifierFromOuterProof, getAgeEVMParameterCommitment, getDateEVMParameterCommitment, getDiscloseEVMParameterCommitment, getCountryEVMParameterCommitment, rightPadArrayWithZeros, getCommittedInputCount, ProofType, getScopeHash, getScopeFromOuterProof, getSubscopeFromOuterProof, getServiceScopeHash, getBindEVMParameterCommitment, getBindParameterCommitment, formatBoundData, } from "@zkpassport/utils";
|
|
3
3
|
import { bytesToHex } from "@noble/ciphers/utils";
|
|
4
4
|
import { noLogger as logger } from "./logger";
|
|
5
5
|
import i18en from "i18n-iso-countries/langs/en.json";
|
|
@@ -191,6 +191,9 @@ export class ZKPassport {
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
+
if (this.topicToConfig[topic].bind) {
|
|
195
|
+
neededCircuits.push("bind");
|
|
196
|
+
}
|
|
194
197
|
// From the circuits needed, determine the expected proof count
|
|
195
198
|
// There are at least 4 proofs, 3 base proofs and 1 disclosure proof minimum
|
|
196
199
|
// Each separate needed circuit adds 1 disclosure proof
|
|
@@ -313,6 +316,13 @@ export class ZKPassport {
|
|
|
313
316
|
};
|
|
314
317
|
return this.getZkPassportRequest(topic);
|
|
315
318
|
},
|
|
319
|
+
bind: (key, value) => {
|
|
320
|
+
this.topicToConfig[topic].bind = {
|
|
321
|
+
...this.topicToConfig[topic].bind,
|
|
322
|
+
[key]: value,
|
|
323
|
+
};
|
|
324
|
+
return this.getZkPassportRequest(topic);
|
|
325
|
+
},
|
|
316
326
|
done: () => {
|
|
317
327
|
const base64Config = Buffer.from(JSON.stringify(this.topicToConfig[topic])).toString("base64");
|
|
318
328
|
const base64Service = Buffer.from(JSON.stringify(this.topicToService[topic])).toString("base64");
|
|
@@ -409,6 +419,7 @@ export class ZKPassport {
|
|
|
409
419
|
fullname: {},
|
|
410
420
|
document_number: {},
|
|
411
421
|
outer: {},
|
|
422
|
+
bind: {},
|
|
412
423
|
};
|
|
413
424
|
let isCorrect = true;
|
|
414
425
|
// We can't be certain that the disclosed data is for a passport or an ID card
|
|
@@ -721,6 +732,7 @@ export class ZKPassport {
|
|
|
721
732
|
fullname: {},
|
|
722
733
|
document_number: {},
|
|
723
734
|
outer: {},
|
|
735
|
+
bind: {},
|
|
724
736
|
};
|
|
725
737
|
let isCorrect = true;
|
|
726
738
|
const currentTime = new Date();
|
|
@@ -830,6 +842,7 @@ export class ZKPassport {
|
|
|
830
842
|
fullname: {},
|
|
831
843
|
document_number: {},
|
|
832
844
|
outer: {},
|
|
845
|
+
bind: {},
|
|
833
846
|
};
|
|
834
847
|
let isCorrect = true;
|
|
835
848
|
const currentTime = new Date();
|
|
@@ -933,6 +946,7 @@ export class ZKPassport {
|
|
|
933
946
|
fullname: {},
|
|
934
947
|
document_number: {},
|
|
935
948
|
outer: {},
|
|
949
|
+
bind: {},
|
|
936
950
|
};
|
|
937
951
|
let isCorrect = true;
|
|
938
952
|
const currentTime = new Date();
|
|
@@ -1036,6 +1050,7 @@ export class ZKPassport {
|
|
|
1036
1050
|
fullname: {},
|
|
1037
1051
|
document_number: {},
|
|
1038
1052
|
outer: {},
|
|
1053
|
+
bind: {},
|
|
1039
1054
|
};
|
|
1040
1055
|
let isCorrect = true;
|
|
1041
1056
|
if (queryResult.nationality &&
|
|
@@ -1090,6 +1105,7 @@ export class ZKPassport {
|
|
|
1090
1105
|
fullname: {},
|
|
1091
1106
|
document_number: {},
|
|
1092
1107
|
outer: {},
|
|
1108
|
+
bind: {},
|
|
1093
1109
|
};
|
|
1094
1110
|
let isCorrect = true;
|
|
1095
1111
|
if (queryResult.issuing_country &&
|
|
@@ -1144,6 +1160,7 @@ export class ZKPassport {
|
|
|
1144
1160
|
fullname: {},
|
|
1145
1161
|
document_number: {},
|
|
1146
1162
|
outer: {},
|
|
1163
|
+
bind: {},
|
|
1147
1164
|
};
|
|
1148
1165
|
let isCorrect = true;
|
|
1149
1166
|
if (queryResult.nationality &&
|
|
@@ -1186,6 +1203,7 @@ export class ZKPassport {
|
|
|
1186
1203
|
fullname: {},
|
|
1187
1204
|
document_number: {},
|
|
1188
1205
|
outer: {},
|
|
1206
|
+
bind: {},
|
|
1189
1207
|
};
|
|
1190
1208
|
let isCorrect = true;
|
|
1191
1209
|
if (queryResult.issuing_country &&
|
|
@@ -1261,6 +1279,51 @@ export class ZKPassport {
|
|
|
1261
1279
|
}
|
|
1262
1280
|
return { isCorrect, queryResultErrors };
|
|
1263
1281
|
}
|
|
1282
|
+
checkBindPublicInputs(queryResult, boundData) {
|
|
1283
|
+
const queryResultErrors = {
|
|
1284
|
+
sig_check_dsc: {},
|
|
1285
|
+
sig_check_id_data: {},
|
|
1286
|
+
data_check_integrity: {},
|
|
1287
|
+
disclose: {},
|
|
1288
|
+
age: {},
|
|
1289
|
+
birthdate: {},
|
|
1290
|
+
expiry_date: {},
|
|
1291
|
+
document_type: {},
|
|
1292
|
+
issuing_country: {},
|
|
1293
|
+
gender: {},
|
|
1294
|
+
nationality: {},
|
|
1295
|
+
firstname: {},
|
|
1296
|
+
lastname: {},
|
|
1297
|
+
fullname: {},
|
|
1298
|
+
document_number: {},
|
|
1299
|
+
outer: {},
|
|
1300
|
+
bind: {},
|
|
1301
|
+
};
|
|
1302
|
+
let isCorrect = true;
|
|
1303
|
+
if (queryResult.bind) {
|
|
1304
|
+
if (queryResult.bind.user_address?.toLowerCase().replace("0x", "") !==
|
|
1305
|
+
boundData.user_address?.toLowerCase().replace("0x", "")) {
|
|
1306
|
+
console.warn("Bound user address does not match the one from the query results");
|
|
1307
|
+
isCorrect = false;
|
|
1308
|
+
queryResultErrors.bind.eq = {
|
|
1309
|
+
expected: queryResult.bind.user_address,
|
|
1310
|
+
received: boundData.user_address,
|
|
1311
|
+
message: "Bound user address does not match the one from the query results",
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
if (queryResult.bind.custom_data?.trim().toLowerCase() !==
|
|
1315
|
+
boundData.custom_data?.trim().toLowerCase()) {
|
|
1316
|
+
console.warn("Bound custom data does not match the one from the query results");
|
|
1317
|
+
isCorrect = false;
|
|
1318
|
+
queryResultErrors.bind.eq = {
|
|
1319
|
+
expected: queryResult.bind.custom_data,
|
|
1320
|
+
received: boundData.custom_data,
|
|
1321
|
+
message: "Bound custom data does not match the one from the query results",
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return { isCorrect, queryResultErrors };
|
|
1326
|
+
}
|
|
1264
1327
|
async checkPublicInputs(proofs, queryResult, validity, scope, chainId) {
|
|
1265
1328
|
let commitmentIn;
|
|
1266
1329
|
let commitmentOut;
|
|
@@ -1285,6 +1348,7 @@ export class ZKPassport {
|
|
|
1285
1348
|
fullname: {},
|
|
1286
1349
|
document_number: {},
|
|
1287
1350
|
outer: {},
|
|
1351
|
+
bind: {},
|
|
1288
1352
|
};
|
|
1289
1353
|
// Since the order is important for the commitments, we need to sort the proofs
|
|
1290
1354
|
// by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
|
|
@@ -1301,6 +1365,7 @@ export class ZKPassport {
|
|
|
1301
1365
|
"inclusion_check_nationality",
|
|
1302
1366
|
"exclusion_check_issuing_country",
|
|
1303
1367
|
"inclusion_check_issuing_country",
|
|
1368
|
+
"bind",
|
|
1304
1369
|
];
|
|
1305
1370
|
const getIndex = (proof) => {
|
|
1306
1371
|
const name = proof.name || "";
|
|
@@ -1537,6 +1602,27 @@ export class ZKPassport {
|
|
|
1537
1602
|
...queryResultErrorsIssuingCountryExclusion,
|
|
1538
1603
|
};
|
|
1539
1604
|
}
|
|
1605
|
+
else if (!!committedInputs?.bind) {
|
|
1606
|
+
const bindCommittedInputs = committedInputs?.bind;
|
|
1607
|
+
const bindParameterCommitment = isForEVM
|
|
1608
|
+
? await getBindEVMParameterCommitment(formatBoundData(bindCommittedInputs.data))
|
|
1609
|
+
: await getBindParameterCommitment(formatBoundData(bindCommittedInputs.data));
|
|
1610
|
+
if (!paramCommitments.includes(bindParameterCommitment)) {
|
|
1611
|
+
console.warn("This proof does not verify the bound data");
|
|
1612
|
+
isCorrect = false;
|
|
1613
|
+
queryResultErrors.bind.commitment = {
|
|
1614
|
+
expected: `Bind parameter commitment: ${bindParameterCommitment.toString()}`,
|
|
1615
|
+
received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
|
|
1616
|
+
message: "This proof does not verify the bound data",
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
|
|
1620
|
+
isCorrect = isCorrect && isCorrectBind;
|
|
1621
|
+
queryResultErrors = {
|
|
1622
|
+
...queryResultErrors,
|
|
1623
|
+
...queryResultErrorsBind,
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1540
1626
|
uniqueIdentifier = getNullifierFromOuterProof(proofData).toString(10);
|
|
1541
1627
|
}
|
|
1542
1628
|
else if (proof.name?.startsWith("sig_check_dsc")) {
|
|
@@ -1858,6 +1944,27 @@ export class ZKPassport {
|
|
|
1858
1944
|
};
|
|
1859
1945
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1860
1946
|
}
|
|
1947
|
+
else if (proof.name === "bind") {
|
|
1948
|
+
const bindCommittedInputs = proof.committedInputs?.bind;
|
|
1949
|
+
const paramCommittment = getParameterCommitmentFromDisclosureProof(proofData);
|
|
1950
|
+
const calculatedParamCommitment = await getBindParameterCommitment(formatBoundData(bindCommittedInputs.data));
|
|
1951
|
+
if (paramCommittment !== calculatedParamCommitment) {
|
|
1952
|
+
console.warn("The bound data does not match the one from the proof");
|
|
1953
|
+
isCorrect = false;
|
|
1954
|
+
queryResultErrors.bind.commitment = {
|
|
1955
|
+
expected: `Commitment: ${calculatedParamCommitment}`,
|
|
1956
|
+
received: `Commitment: ${paramCommittment}`,
|
|
1957
|
+
message: "The bound data does not match the one from the proof",
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
|
|
1961
|
+
isCorrect = isCorrect && isCorrectBind;
|
|
1962
|
+
queryResultErrors = {
|
|
1963
|
+
...queryResultErrors,
|
|
1964
|
+
...queryResultErrorsBind,
|
|
1965
|
+
};
|
|
1966
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1967
|
+
}
|
|
1861
1968
|
}
|
|
1862
1969
|
return { isCorrect, uniqueIdentifier, queryResultErrors };
|
|
1863
1970
|
}
|
|
@@ -1973,7 +2080,7 @@ export class ZKPassport {
|
|
|
1973
2080
|
if (network === "ethereum_sepolia") {
|
|
1974
2081
|
return {
|
|
1975
2082
|
...baseConfig,
|
|
1976
|
-
address: "
|
|
2083
|
+
address: "0x5e4B11F7B7995F5Cee0134692a422b045091112F",
|
|
1977
2084
|
};
|
|
1978
2085
|
}
|
|
1979
2086
|
else if (network === "local_anvil") {
|
|
@@ -2066,6 +2173,14 @@ export class ZKPassport {
|
|
|
2066
2173
|
value.discloseMask.map((x) => x.toString(16).padStart(2, "0")).join("") +
|
|
2067
2174
|
value.disclosedBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
2068
2175
|
}
|
|
2176
|
+
else if (circuitName === "bind_evm") {
|
|
2177
|
+
const value = proof.committedInputs[circuitName];
|
|
2178
|
+
compressedCommittedInputs =
|
|
2179
|
+
ProofType.BIND.toString(16).padStart(2, "0") +
|
|
2180
|
+
rightPadArrayWithZeros(formatBoundData(value.data), 500)
|
|
2181
|
+
.map((x) => x.toString(16).padStart(2, "0"))
|
|
2182
|
+
.join("");
|
|
2183
|
+
}
|
|
2069
2184
|
else {
|
|
2070
2185
|
throw new Error(`Unsupported circuit for EVM verification: ${circuitName}`);
|
|
2071
2186
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkpassport/sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@noble/secp256k1": "^2.2.3",
|
|
45
45
|
"@obsidion/bridge": "^0.9.0",
|
|
46
46
|
"@zkpassport/registry": "^0.1.9",
|
|
47
|
-
"@zkpassport/utils": "^0.
|
|
47
|
+
"@zkpassport/utils": "^0.9.4",
|
|
48
48
|
"buffer": "^6.0.3",
|
|
49
49
|
"i18n-iso-countries": "^7.12.0",
|
|
50
50
|
"pako": "^2.1.0",
|