@zkpassport/sdk 0.4.0 → 0.4.2
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 +13 -3
- package/dist/cjs/index.js +129 -10
- package/dist/esm/assets/abi/ZKPassportVerifier.json +51 -9
- package/dist/esm/index.d.ts +13 -3
- package/dist/esm/index.js +130 -11
- package/package.json +4 -4
- package/src/assets/abi/ZKPassportVerifier.json +51 -9
- package/src/index.ts +160 -23
package/dist/cjs/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
|
*
|
|
@@ -199,7 +205,7 @@ export declare class ZKPassport {
|
|
|
199
205
|
* @param evmChain The EVM chain to use for the request (if using the proof onchain)
|
|
200
206
|
* @returns The query builder object.
|
|
201
207
|
*/
|
|
202
|
-
request({ name, logo, purpose, scope, mode, evmChain, validity, devMode, topicOverride, keyPairOverride, }: {
|
|
208
|
+
request({ name, logo, purpose, scope, mode, evmChain, validity, devMode, topicOverride, keyPairOverride, cloudProverUrl, bridgeUrl, }: {
|
|
203
209
|
name: string;
|
|
204
210
|
logo: string;
|
|
205
211
|
purpose: string;
|
|
@@ -213,6 +219,8 @@ export declare class ZKPassport {
|
|
|
213
219
|
privateKey: Uint8Array;
|
|
214
220
|
publicKey: Uint8Array;
|
|
215
221
|
};
|
|
222
|
+
cloudProverUrl?: string;
|
|
223
|
+
bridgeUrl?: string;
|
|
216
224
|
}): Promise<QueryBuilder>;
|
|
217
225
|
private checkDiscloseBytesPublicInputs;
|
|
218
226
|
private checkAgePublicInputs;
|
|
@@ -224,6 +232,7 @@ export declare class ZKPassport {
|
|
|
224
232
|
private checkIssuingCountryInclusionPublicInputs;
|
|
225
233
|
private checkScopeFromDisclosureProof;
|
|
226
234
|
private checkCertificateRegistryRoot;
|
|
235
|
+
private checkBindPublicInputs;
|
|
227
236
|
private checkPublicInputs;
|
|
228
237
|
/**
|
|
229
238
|
* @notice Verify the proofs received from the mobile app.
|
|
@@ -273,6 +282,7 @@ export declare class ZKPassport {
|
|
|
273
282
|
scope?: string;
|
|
274
283
|
devMode?: boolean;
|
|
275
284
|
}): SolidityVerifierParameters;
|
|
285
|
+
private _getUrl;
|
|
276
286
|
/**
|
|
277
287
|
* @notice Returns the URL of the request.
|
|
278
288
|
* @param requestId The request ID.
|
package/dist/cjs/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const utils_3 = require("@noble/hashes/utils");
|
|
|
13
13
|
const ZKPassportVerifier_json_1 = tslib_1.__importDefault(require("./assets/abi/ZKPassportVerifier.json"));
|
|
14
14
|
const registry_1 = require("@zkpassport/registry");
|
|
15
15
|
const bridge_1 = require("@obsidion/bridge");
|
|
16
|
+
const VERSION = "0.4.2";
|
|
16
17
|
const DEFAULT_DATE_VALUE = new Date(1111, 10, 11);
|
|
17
18
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
18
19
|
if (typeof globalThis.Buffer === "undefined") {
|
|
@@ -201,6 +202,9 @@ class ZKPassport {
|
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
}
|
|
205
|
+
if (this.topicToConfig[topic].bind) {
|
|
206
|
+
neededCircuits.push("bind");
|
|
207
|
+
}
|
|
204
208
|
// From the circuits needed, determine the expected proof count
|
|
205
209
|
// There are at least 4 proofs, 3 base proofs and 1 disclosure proof minimum
|
|
206
210
|
// Each separate needed circuit adds 1 disclosure proof
|
|
@@ -323,13 +327,17 @@ class ZKPassport {
|
|
|
323
327
|
};
|
|
324
328
|
return this.getZkPassportRequest(topic);
|
|
325
329
|
},
|
|
330
|
+
bind: (key, value) => {
|
|
331
|
+
this.topicToConfig[topic].bind = {
|
|
332
|
+
...this.topicToConfig[topic].bind,
|
|
333
|
+
[key]: value,
|
|
334
|
+
};
|
|
335
|
+
return this.getZkPassportRequest(topic);
|
|
336
|
+
},
|
|
326
337
|
done: () => {
|
|
327
|
-
const base64Config = buffer_1.Buffer.from(JSON.stringify(this.topicToConfig[topic])).toString("base64");
|
|
328
|
-
const base64Service = buffer_1.Buffer.from(JSON.stringify(this.topicToService[topic])).toString("base64");
|
|
329
|
-
const pubkey = this.topicToPublicKey[topic];
|
|
330
338
|
this.setExpectedProofCount(topic);
|
|
331
339
|
return {
|
|
332
|
-
url:
|
|
340
|
+
url: this._getUrl(topic),
|
|
333
341
|
requestId: topic,
|
|
334
342
|
onRequestReceived: (callback) => this.onRequestReceivedCallbacks[topic].push(callback),
|
|
335
343
|
onGeneratingProof: (callback) => this.onGeneratingProofCallbacks[topic].push(callback),
|
|
@@ -355,10 +363,11 @@ class ZKPassport {
|
|
|
355
363
|
* @param evmChain The EVM chain to use for the request (if using the proof onchain)
|
|
356
364
|
* @returns The query builder object.
|
|
357
365
|
*/
|
|
358
|
-
async request({ name, logo, purpose, scope, mode, evmChain, validity, devMode, topicOverride, keyPairOverride, }) {
|
|
366
|
+
async request({ name, logo, purpose, scope, mode, evmChain, validity, devMode, topicOverride, keyPairOverride, cloudProverUrl, bridgeUrl, }) {
|
|
359
367
|
const bridge = await bridge_1.Bridge.create({
|
|
360
368
|
keyPair: keyPairOverride,
|
|
361
369
|
bridgeId: topicOverride,
|
|
370
|
+
bridgeUrl,
|
|
362
371
|
});
|
|
363
372
|
const topic = bridge.connection.getBridgeId();
|
|
364
373
|
this.topicToConfig[topic] = {};
|
|
@@ -368,6 +377,8 @@ class ZKPassport {
|
|
|
368
377
|
purpose,
|
|
369
378
|
scope,
|
|
370
379
|
chainId: evmChain ? getChainIdFromEVMChain(evmChain) : undefined,
|
|
380
|
+
cloudProverUrl,
|
|
381
|
+
bridgeUrl,
|
|
371
382
|
};
|
|
372
383
|
this.topicToProofs[topic] = [];
|
|
373
384
|
this.topicToExpectedProofCount[topic] = 0;
|
|
@@ -419,6 +430,7 @@ class ZKPassport {
|
|
|
419
430
|
fullname: {},
|
|
420
431
|
document_number: {},
|
|
421
432
|
outer: {},
|
|
433
|
+
bind: {},
|
|
422
434
|
};
|
|
423
435
|
let isCorrect = true;
|
|
424
436
|
// We can't be certain that the disclosed data is for a passport or an ID card
|
|
@@ -731,6 +743,7 @@ class ZKPassport {
|
|
|
731
743
|
fullname: {},
|
|
732
744
|
document_number: {},
|
|
733
745
|
outer: {},
|
|
746
|
+
bind: {},
|
|
734
747
|
};
|
|
735
748
|
let isCorrect = true;
|
|
736
749
|
const currentTime = new Date();
|
|
@@ -840,6 +853,7 @@ class ZKPassport {
|
|
|
840
853
|
fullname: {},
|
|
841
854
|
document_number: {},
|
|
842
855
|
outer: {},
|
|
856
|
+
bind: {},
|
|
843
857
|
};
|
|
844
858
|
let isCorrect = true;
|
|
845
859
|
const currentTime = new Date();
|
|
@@ -943,6 +957,7 @@ class ZKPassport {
|
|
|
943
957
|
fullname: {},
|
|
944
958
|
document_number: {},
|
|
945
959
|
outer: {},
|
|
960
|
+
bind: {},
|
|
946
961
|
};
|
|
947
962
|
let isCorrect = true;
|
|
948
963
|
const currentTime = new Date();
|
|
@@ -1046,6 +1061,7 @@ class ZKPassport {
|
|
|
1046
1061
|
fullname: {},
|
|
1047
1062
|
document_number: {},
|
|
1048
1063
|
outer: {},
|
|
1064
|
+
bind: {},
|
|
1049
1065
|
};
|
|
1050
1066
|
let isCorrect = true;
|
|
1051
1067
|
if (queryResult.nationality &&
|
|
@@ -1100,6 +1116,7 @@ class ZKPassport {
|
|
|
1100
1116
|
fullname: {},
|
|
1101
1117
|
document_number: {},
|
|
1102
1118
|
outer: {},
|
|
1119
|
+
bind: {},
|
|
1103
1120
|
};
|
|
1104
1121
|
let isCorrect = true;
|
|
1105
1122
|
if (queryResult.issuing_country &&
|
|
@@ -1154,6 +1171,7 @@ class ZKPassport {
|
|
|
1154
1171
|
fullname: {},
|
|
1155
1172
|
document_number: {},
|
|
1156
1173
|
outer: {},
|
|
1174
|
+
bind: {},
|
|
1157
1175
|
};
|
|
1158
1176
|
let isCorrect = true;
|
|
1159
1177
|
if (queryResult.nationality &&
|
|
@@ -1196,6 +1214,7 @@ class ZKPassport {
|
|
|
1196
1214
|
fullname: {},
|
|
1197
1215
|
document_number: {},
|
|
1198
1216
|
outer: {},
|
|
1217
|
+
bind: {},
|
|
1199
1218
|
};
|
|
1200
1219
|
let isCorrect = true;
|
|
1201
1220
|
if (queryResult.issuing_country &&
|
|
@@ -1271,6 +1290,51 @@ class ZKPassport {
|
|
|
1271
1290
|
}
|
|
1272
1291
|
return { isCorrect, queryResultErrors };
|
|
1273
1292
|
}
|
|
1293
|
+
checkBindPublicInputs(queryResult, boundData) {
|
|
1294
|
+
const queryResultErrors = {
|
|
1295
|
+
sig_check_dsc: {},
|
|
1296
|
+
sig_check_id_data: {},
|
|
1297
|
+
data_check_integrity: {},
|
|
1298
|
+
disclose: {},
|
|
1299
|
+
age: {},
|
|
1300
|
+
birthdate: {},
|
|
1301
|
+
expiry_date: {},
|
|
1302
|
+
document_type: {},
|
|
1303
|
+
issuing_country: {},
|
|
1304
|
+
gender: {},
|
|
1305
|
+
nationality: {},
|
|
1306
|
+
firstname: {},
|
|
1307
|
+
lastname: {},
|
|
1308
|
+
fullname: {},
|
|
1309
|
+
document_number: {},
|
|
1310
|
+
outer: {},
|
|
1311
|
+
bind: {},
|
|
1312
|
+
};
|
|
1313
|
+
let isCorrect = true;
|
|
1314
|
+
if (queryResult.bind) {
|
|
1315
|
+
if (queryResult.bind.user_address?.toLowerCase().replace("0x", "") !==
|
|
1316
|
+
boundData.user_address?.toLowerCase().replace("0x", "")) {
|
|
1317
|
+
console.warn("Bound user address does not match the one from the query results");
|
|
1318
|
+
isCorrect = false;
|
|
1319
|
+
queryResultErrors.bind.eq = {
|
|
1320
|
+
expected: queryResult.bind.user_address,
|
|
1321
|
+
received: boundData.user_address,
|
|
1322
|
+
message: "Bound user address does not match the one from the query results",
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
if (queryResult.bind.custom_data?.trim().toLowerCase() !==
|
|
1326
|
+
boundData.custom_data?.trim().toLowerCase()) {
|
|
1327
|
+
console.warn("Bound custom data does not match the one from the query results");
|
|
1328
|
+
isCorrect = false;
|
|
1329
|
+
queryResultErrors.bind.eq = {
|
|
1330
|
+
expected: queryResult.bind.custom_data,
|
|
1331
|
+
received: boundData.custom_data,
|
|
1332
|
+
message: "Bound custom data does not match the one from the query results",
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
return { isCorrect, queryResultErrors };
|
|
1337
|
+
}
|
|
1274
1338
|
async checkPublicInputs(proofs, queryResult, validity, scope, chainId) {
|
|
1275
1339
|
let commitmentIn;
|
|
1276
1340
|
let commitmentOut;
|
|
@@ -1295,6 +1359,7 @@ class ZKPassport {
|
|
|
1295
1359
|
fullname: {},
|
|
1296
1360
|
document_number: {},
|
|
1297
1361
|
outer: {},
|
|
1362
|
+
bind: {},
|
|
1298
1363
|
};
|
|
1299
1364
|
// Since the order is important for the commitments, we need to sort the proofs
|
|
1300
1365
|
// by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
|
|
@@ -1311,6 +1376,7 @@ class ZKPassport {
|
|
|
1311
1376
|
"inclusion_check_nationality",
|
|
1312
1377
|
"exclusion_check_issuing_country",
|
|
1313
1378
|
"inclusion_check_issuing_country",
|
|
1379
|
+
"bind",
|
|
1314
1380
|
];
|
|
1315
1381
|
const getIndex = (proof) => {
|
|
1316
1382
|
const name = proof.name || "";
|
|
@@ -1547,6 +1613,27 @@ class ZKPassport {
|
|
|
1547
1613
|
...queryResultErrorsIssuingCountryExclusion,
|
|
1548
1614
|
};
|
|
1549
1615
|
}
|
|
1616
|
+
else if (!!committedInputs?.bind) {
|
|
1617
|
+
const bindCommittedInputs = committedInputs?.bind;
|
|
1618
|
+
const bindParameterCommitment = isForEVM
|
|
1619
|
+
? await (0, utils_1.getBindEVMParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data))
|
|
1620
|
+
: await (0, utils_1.getBindParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data));
|
|
1621
|
+
if (!paramCommitments.includes(bindParameterCommitment)) {
|
|
1622
|
+
console.warn("This proof does not verify the bound data");
|
|
1623
|
+
isCorrect = false;
|
|
1624
|
+
queryResultErrors.bind.commitment = {
|
|
1625
|
+
expected: `Bind parameter commitment: ${bindParameterCommitment.toString()}`,
|
|
1626
|
+
received: `Parameter commitments included: ${paramCommitments.join(", ")}`,
|
|
1627
|
+
message: "This proof does not verify the bound data",
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
|
|
1631
|
+
isCorrect = isCorrect && isCorrectBind;
|
|
1632
|
+
queryResultErrors = {
|
|
1633
|
+
...queryResultErrors,
|
|
1634
|
+
...queryResultErrorsBind,
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1550
1637
|
uniqueIdentifier = (0, utils_1.getNullifierFromOuterProof)(proofData).toString(10);
|
|
1551
1638
|
}
|
|
1552
1639
|
else if (proof.name?.startsWith("sig_check_dsc")) {
|
|
@@ -1868,6 +1955,27 @@ class ZKPassport {
|
|
|
1868
1955
|
};
|
|
1869
1956
|
uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
|
|
1870
1957
|
}
|
|
1958
|
+
else if (proof.name === "bind") {
|
|
1959
|
+
const bindCommittedInputs = proof.committedInputs?.bind;
|
|
1960
|
+
const paramCommittment = (0, utils_1.getParameterCommitmentFromDisclosureProof)(proofData);
|
|
1961
|
+
const calculatedParamCommitment = await (0, utils_1.getBindParameterCommitment)((0, utils_1.formatBoundData)(bindCommittedInputs.data));
|
|
1962
|
+
if (paramCommittment !== calculatedParamCommitment) {
|
|
1963
|
+
console.warn("The bound data does not match the one from the proof");
|
|
1964
|
+
isCorrect = false;
|
|
1965
|
+
queryResultErrors.bind.commitment = {
|
|
1966
|
+
expected: `Commitment: ${calculatedParamCommitment}`,
|
|
1967
|
+
received: `Commitment: ${paramCommittment}`,
|
|
1968
|
+
message: "The bound data does not match the one from the proof",
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
const { isCorrect: isCorrectBind, queryResultErrors: queryResultErrorsBind } = this.checkBindPublicInputs(queryResult, bindCommittedInputs.data);
|
|
1972
|
+
isCorrect = isCorrect && isCorrectBind;
|
|
1973
|
+
queryResultErrors = {
|
|
1974
|
+
...queryResultErrors,
|
|
1975
|
+
...queryResultErrorsBind,
|
|
1976
|
+
};
|
|
1977
|
+
uniqueIdentifier = (0, utils_1.getNullifierFromDisclosureProof)(proofData).toString(10);
|
|
1978
|
+
}
|
|
1871
1979
|
}
|
|
1872
1980
|
return { isCorrect, uniqueIdentifier, queryResultErrors };
|
|
1873
1981
|
}
|
|
@@ -1983,7 +2091,7 @@ class ZKPassport {
|
|
|
1983
2091
|
if (network === "ethereum_sepolia") {
|
|
1984
2092
|
return {
|
|
1985
2093
|
...baseConfig,
|
|
1986
|
-
address: "
|
|
2094
|
+
address: "0x5e4B11F7B7995F5Cee0134692a422b045091112F",
|
|
1987
2095
|
};
|
|
1988
2096
|
}
|
|
1989
2097
|
else if (network === "local_anvil") {
|
|
@@ -2076,6 +2184,14 @@ class ZKPassport {
|
|
|
2076
2184
|
value.discloseMask.map((x) => x.toString(16).padStart(2, "0")).join("") +
|
|
2077
2185
|
value.disclosedBytes.map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
2078
2186
|
}
|
|
2187
|
+
else if (circuitName === "bind_evm") {
|
|
2188
|
+
const value = proof.committedInputs[circuitName];
|
|
2189
|
+
compressedCommittedInputs =
|
|
2190
|
+
utils_1.ProofType.BIND.toString(16).padStart(2, "0") +
|
|
2191
|
+
(0, utils_1.rightPadArrayWithZeros)((0, utils_1.formatBoundData)(value.data), 500)
|
|
2192
|
+
.map((x) => x.toString(16).padStart(2, "0"))
|
|
2193
|
+
.join("");
|
|
2194
|
+
}
|
|
2079
2195
|
else {
|
|
2080
2196
|
throw new Error(`Unsupported circuit for EVM verification: ${circuitName}`);
|
|
2081
2197
|
}
|
|
@@ -2126,16 +2242,19 @@ class ZKPassport {
|
|
|
2126
2242
|
};
|
|
2127
2243
|
return params;
|
|
2128
2244
|
}
|
|
2245
|
+
_getUrl(requestId) {
|
|
2246
|
+
const base64Config = buffer_1.Buffer.from(JSON.stringify(this.topicToConfig[requestId])).toString("base64");
|
|
2247
|
+
const base64Service = buffer_1.Buffer.from(JSON.stringify(this.topicToService[requestId])).toString("base64");
|
|
2248
|
+
const pubkey = this.topicToPublicKey[requestId];
|
|
2249
|
+
return `https://zkpassport.id/r?d=${this.domain}&t=${requestId}&c=${base64Config}&s=${base64Service}&p=${pubkey}&m=${this.topicToLocalConfig[requestId].mode}&v=${VERSION}`;
|
|
2250
|
+
}
|
|
2129
2251
|
/**
|
|
2130
2252
|
* @notice Returns the URL of the request.
|
|
2131
2253
|
* @param requestId The request ID.
|
|
2132
2254
|
* @returns The URL of the request.
|
|
2133
2255
|
*/
|
|
2134
2256
|
getUrl(requestId) {
|
|
2135
|
-
|
|
2136
|
-
const base64Config = buffer_1.Buffer.from(JSON.stringify(this.topicToConfig[requestId])).toString("base64");
|
|
2137
|
-
const base64Service = buffer_1.Buffer.from(JSON.stringify(this.topicToService[requestId])).toString("base64");
|
|
2138
|
-
return `https://zkpassport.id/r?d=${this.domain}&t=${requestId}&c=${base64Config}&s=${base64Service}&p=${pubkey}&m=${this.topicToLocalConfig[requestId].mode}`;
|
|
2257
|
+
return this._getUrl(requestId);
|
|
2139
2258
|
}
|
|
2140
2259
|
/**
|
|
2141
2260
|
* @notice Cancels a request by closing the WebSocket connection and deleting the associated data.
|