@zkpassport/sdk 0.3.1 → 0.3.3
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 +110 -16
- package/dist/cjs/index.d.ts +9 -3
- package/dist/cjs/index.js +64 -31
- package/dist/esm/assets/abi/ZKPassportVerifier.json +110 -16
- package/dist/esm/index.d.ts +9 -3
- package/dist/esm/index.js +63 -30
- package/package.json +3 -2
- package/src/assets/abi/ZKPassportVerifier.json +110 -16
- package/src/index.ts +88 -27
package/dist/esm/index.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export type SolidityVerifierParameters = {
|
|
|
29
29
|
validityPeriodInDays: number;
|
|
30
30
|
scope: string;
|
|
31
31
|
subscope: string;
|
|
32
|
+
devMode: boolean;
|
|
32
33
|
};
|
|
33
34
|
export type EVMChain = "ethereum_sepolia" | "local_anvil";
|
|
34
35
|
export type * from "@zkpassport/utils";
|
|
@@ -195,15 +196,17 @@ export declare class ZKPassport {
|
|
|
195
196
|
* @param purpose To explain what you want to do with the user's data
|
|
196
197
|
* @param scope Scope this request to a specific use case
|
|
197
198
|
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
199
|
+
* @param devMode Whether to enable dev mode. This will allow you to verify mock proofs (i.e. from ZKR)
|
|
198
200
|
* @returns The query builder object.
|
|
199
201
|
*/
|
|
200
|
-
request({ name, logo, purpose, scope, mode, validity, topicOverride, keyPairOverride, }: {
|
|
202
|
+
request({ name, logo, purpose, scope, mode, validity, devMode, topicOverride, keyPairOverride, }: {
|
|
201
203
|
name: string;
|
|
202
204
|
logo: string;
|
|
203
205
|
purpose: string;
|
|
204
206
|
scope?: string;
|
|
205
207
|
mode?: ProofMode;
|
|
206
208
|
validity?: number;
|
|
209
|
+
devMode?: boolean;
|
|
207
210
|
topicOverride?: string;
|
|
208
211
|
keyPairOverride?: {
|
|
209
212
|
privateKey: Uint8Array;
|
|
@@ -219,6 +222,7 @@ export declare class ZKPassport {
|
|
|
219
222
|
private checkNationalityInclusionPublicInputs;
|
|
220
223
|
private checkIssuingCountryInclusionPublicInputs;
|
|
221
224
|
private checkScopeFromDisclosureProof;
|
|
225
|
+
private checkCertificateRegistryRoot;
|
|
222
226
|
private checkPublicInputs;
|
|
223
227
|
/**
|
|
224
228
|
* @notice Verify the proofs received from the mobile app.
|
|
@@ -228,11 +232,12 @@ export declare class ZKPassport {
|
|
|
228
232
|
* @returns An object containing the unique identifier associated to the user
|
|
229
233
|
* and a boolean indicating whether the proofs were successfully verified.
|
|
230
234
|
*/
|
|
231
|
-
verify({ proofs, queryResult, validity, scope, }: {
|
|
235
|
+
verify({ proofs, queryResult, validity, scope, devMode, }: {
|
|
232
236
|
proofs: Array<ProofResult>;
|
|
233
237
|
queryResult: QueryResult;
|
|
234
238
|
validity?: number;
|
|
235
239
|
scope?: string;
|
|
240
|
+
devMode?: boolean;
|
|
236
241
|
}): Promise<{
|
|
237
242
|
uniqueIdentifier: string | undefined;
|
|
238
243
|
verified: boolean;
|
|
@@ -256,11 +261,12 @@ export declare class ZKPassport {
|
|
|
256
261
|
}[];
|
|
257
262
|
}[];
|
|
258
263
|
};
|
|
259
|
-
getSolidityVerifierParameters({ proof, validityPeriodInDays, domain, scope, }: {
|
|
264
|
+
getSolidityVerifierParameters({ proof, validityPeriodInDays, domain, scope, devMode, }: {
|
|
260
265
|
proof: ProofResult;
|
|
261
266
|
validityPeriodInDays?: number;
|
|
262
267
|
domain?: string;
|
|
263
268
|
scope?: string;
|
|
269
|
+
devMode?: boolean;
|
|
264
270
|
}): SolidityVerifierParameters;
|
|
265
271
|
/**
|
|
266
272
|
* @notice Returns the URL of the request.
|
package/dist/esm/index.js
CHANGED
|
@@ -9,9 +9,10 @@ import { noLogger as logger } from "./logger";
|
|
|
9
9
|
import { inflate } from "pako";
|
|
10
10
|
import i18en from "i18n-iso-countries/langs/en.json";
|
|
11
11
|
import { Buffer } from "buffer/";
|
|
12
|
-
import { sha256 } from "@noble/hashes/
|
|
12
|
+
import { sha256 } from "@noble/hashes/sha2";
|
|
13
13
|
import { hexToBytes } from "@noble/hashes/utils";
|
|
14
14
|
import ZKPassportVerifierAbi from "./assets/abi/ZKPassportVerifier.json";
|
|
15
|
+
import { RegistryClient } from "@zkpassport/registry";
|
|
15
16
|
const DEFAULT_DATE_VALUE = new Date(1111, 10, 11);
|
|
16
17
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
17
18
|
if (typeof globalThis.Buffer === "undefined") {
|
|
@@ -36,9 +37,12 @@ function hasRequestedAccessToField(credentialsRequest, field) {
|
|
|
36
37
|
return false;
|
|
37
38
|
}
|
|
38
39
|
function normalizeCountry(country) {
|
|
40
|
+
if (country === "Zero Knowledge Republic") {
|
|
41
|
+
return "ZKR";
|
|
42
|
+
}
|
|
39
43
|
let normalizedCountry;
|
|
40
44
|
const alpha3 = getAlpha3Code(country, "en");
|
|
41
|
-
normalizedCountry = alpha3 || country;
|
|
45
|
+
normalizedCountry = alpha3 || country || "ZKR";
|
|
42
46
|
return normalizedCountry;
|
|
43
47
|
}
|
|
44
48
|
function numericalCompare(fnName, key, value, requestId, requestIdToConfig) {
|
|
@@ -96,6 +100,7 @@ export class ZKPassport {
|
|
|
96
100
|
queryResult: result,
|
|
97
101
|
validity: this.topicToLocalConfig[topic]?.validity,
|
|
98
102
|
scope: this.topicToService[topic]?.scope,
|
|
103
|
+
devMode: this.topicToLocalConfig[topic]?.devMode,
|
|
99
104
|
});
|
|
100
105
|
delete this.topicToProofs[topic];
|
|
101
106
|
const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
|
|
@@ -342,9 +347,10 @@ export class ZKPassport {
|
|
|
342
347
|
* @param purpose To explain what you want to do with the user's data
|
|
343
348
|
* @param scope Scope this request to a specific use case
|
|
344
349
|
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
350
|
+
* @param devMode Whether to enable dev mode. This will allow you to verify mock proofs (i.e. from ZKR)
|
|
345
351
|
* @returns The query builder object.
|
|
346
352
|
*/
|
|
347
|
-
async request({ name, logo, purpose, scope, mode, validity, topicOverride, keyPairOverride, }) {
|
|
353
|
+
async request({ name, logo, purpose, scope, mode, validity, devMode, topicOverride, keyPairOverride, }) {
|
|
348
354
|
const topic = topicOverride || randomBytes(16).toString("hex");
|
|
349
355
|
const keyPair = keyPairOverride || (await generateECDHKeyPair());
|
|
350
356
|
this.topicToKeyPair[topic] = {
|
|
@@ -359,6 +365,7 @@ export class ZKPassport {
|
|
|
359
365
|
// Default to 6 months
|
|
360
366
|
validity: validity || 6 * 30,
|
|
361
367
|
mode: mode || "fast",
|
|
368
|
+
devMode: devMode || false,
|
|
362
369
|
};
|
|
363
370
|
this.onRequestReceivedCallbacks[topic] = [];
|
|
364
371
|
this.onGeneratingProofCallbacks[topic] = [];
|
|
@@ -1257,16 +1264,39 @@ export class ZKPassport {
|
|
|
1257
1264
|
}
|
|
1258
1265
|
return { isCorrect, queryResultErrors };
|
|
1259
1266
|
}
|
|
1267
|
+
async checkCertificateRegistryRoot(root, queryResultErrors, outer) {
|
|
1268
|
+
let isCorrect = true;
|
|
1269
|
+
try {
|
|
1270
|
+
// Maintained certificate registry settled onchain
|
|
1271
|
+
// Here we use Ethereum Sepolia
|
|
1272
|
+
const registryClient = new RegistryClient({ chainId: 11155111 });
|
|
1273
|
+
await registryClient.getCertificates(`0x${root}`);
|
|
1274
|
+
}
|
|
1275
|
+
catch (error) {
|
|
1276
|
+
console.warn(error);
|
|
1277
|
+
// Check the legacy static roots that were used before the registry was deployed onchain
|
|
1278
|
+
const VALID_CERTIFICATE_REGISTRY_ROOT = [
|
|
1279
|
+
BigInt("20192042006788880778219739574377003123593792072535937278552252195461520776494"),
|
|
1280
|
+
BigInt("21301853597069384763054217328384418971999152625381818922211526730996340553696"),
|
|
1281
|
+
BigInt("10839898448097753834842514286432152806152415606387598803678317315409344029817"),
|
|
1282
|
+
];
|
|
1283
|
+
if (!VALID_CERTIFICATE_REGISTRY_ROOT.includes(BigInt(root))) {
|
|
1284
|
+
console.warn("The ID was signed by an unrecognized root certificate");
|
|
1285
|
+
isCorrect = false;
|
|
1286
|
+
queryResultErrors[outer ? "outer" : "sig_check_dsc"].certificate = {
|
|
1287
|
+
expected: `A valid root from ZKPassport Registry`,
|
|
1288
|
+
received: `Got invalid certificate registry root: ${root}`,
|
|
1289
|
+
message: "The ID was signed by an unrecognized root certificate",
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
return { isCorrect, queryResultErrors };
|
|
1294
|
+
}
|
|
1260
1295
|
async checkPublicInputs(proofs, queryResult, validity, scope) {
|
|
1261
1296
|
let commitmentIn;
|
|
1262
1297
|
let commitmentOut;
|
|
1263
1298
|
let isCorrect = true;
|
|
1264
1299
|
let uniqueIdentifier;
|
|
1265
|
-
const VALID_CERTIFICATE_REGISTRY_ROOT = [
|
|
1266
|
-
BigInt("20192042006788880778219739574377003123593792072535937278552252195461520776494"),
|
|
1267
|
-
BigInt("21301853597069384763054217328384418971999152625381818922211526730996340553696"),
|
|
1268
|
-
BigInt("10839898448097753834842514286432152806152415606387598803678317315409344029817"),
|
|
1269
|
-
];
|
|
1270
1300
|
const currentTime = new Date();
|
|
1271
1301
|
const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0, 0);
|
|
1272
1302
|
let queryResultErrors = {
|
|
@@ -1314,15 +1344,12 @@ export class ZKPassport {
|
|
|
1314
1344
|
if (proof.name?.startsWith("outer")) {
|
|
1315
1345
|
const isForEVM = proof.name?.startsWith("outer_evm");
|
|
1316
1346
|
const certificateRegistryRoot = getCertificateRegistryRootFromOuterProof(proofData);
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
queryResultErrors
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
message: "The ID was signed by an unrecognized root certificate",
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1347
|
+
const { isCorrect: isCorrectCertificateRegistryRoot, queryResultErrors: queryResultErrorsCertificateRegistryRoot, } = await this.checkCertificateRegistryRoot(certificateRegistryRoot.toString(16), queryResultErrors, true);
|
|
1348
|
+
isCorrect = isCorrect && isCorrectCertificateRegistryRoot;
|
|
1349
|
+
queryResultErrors = {
|
|
1350
|
+
...queryResultErrors,
|
|
1351
|
+
...queryResultErrorsCertificateRegistryRoot,
|
|
1352
|
+
};
|
|
1326
1353
|
const currentDate = getCurrentDateFromOuterProof(proofData);
|
|
1327
1354
|
const todayToCurrentDate = today.getTime() - currentDate.getTime();
|
|
1328
1355
|
const differenceInDays = validity ?? 180;
|
|
@@ -1545,15 +1572,12 @@ export class ZKPassport {
|
|
|
1545
1572
|
else if (proof.name?.startsWith("sig_check_dsc")) {
|
|
1546
1573
|
commitmentOut = getCommitmentFromDSCProof(proofData);
|
|
1547
1574
|
const merkleRoot = getMerkleRootFromDSCProof(proofData);
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
queryResultErrors
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
message: "The ID was signed by an unrecognized root certificate",
|
|
1555
|
-
};
|
|
1556
|
-
}
|
|
1575
|
+
const { isCorrect: isCorrectCertificateRegistryRoot, queryResultErrors: queryResultErrorsCertificateRegistryRoot, } = await this.checkCertificateRegistryRoot(merkleRoot.toString(16), queryResultErrors, false);
|
|
1576
|
+
isCorrect = isCorrect && isCorrectCertificateRegistryRoot;
|
|
1577
|
+
queryResultErrors = {
|
|
1578
|
+
...queryResultErrors,
|
|
1579
|
+
...queryResultErrorsCertificateRegistryRoot,
|
|
1580
|
+
};
|
|
1557
1581
|
}
|
|
1558
1582
|
else if (proof.name?.startsWith("sig_check_id_data")) {
|
|
1559
1583
|
commitmentIn = getCommitmentInFromIDDataProof(proofData);
|
|
@@ -1875,7 +1899,7 @@ export class ZKPassport {
|
|
|
1875
1899
|
* @returns An object containing the unique identifier associated to the user
|
|
1876
1900
|
* and a boolean indicating whether the proofs were successfully verified.
|
|
1877
1901
|
*/
|
|
1878
|
-
async verify({ proofs, queryResult, validity, scope, }) {
|
|
1902
|
+
async verify({ proofs, queryResult, validity, scope, devMode = false, }) {
|
|
1879
1903
|
const formattedResult = queryResult;
|
|
1880
1904
|
// Make sure to reconvert the dates to Date objects
|
|
1881
1905
|
if (formattedResult.birthdate && formattedResult.birthdate.disclose) {
|
|
@@ -1893,6 +1917,13 @@ export class ZKPassport {
|
|
|
1893
1917
|
uniqueIdentifier = uniqueIdentifierFromPublicInputs;
|
|
1894
1918
|
verified = isCorrect;
|
|
1895
1919
|
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
|
|
1920
|
+
if (uniqueIdentifier && BigInt(uniqueIdentifier) === BigInt(0) && !devMode) {
|
|
1921
|
+
// If the unique identifier is 0 and it is not in dev mode,
|
|
1922
|
+
// the proofs are considered invalid as these are mock proofs only meant
|
|
1923
|
+
// for testing purposes
|
|
1924
|
+
verified = false;
|
|
1925
|
+
console.warn("You are trying to verify a mock proof. This is only allowed in dev mode. To enable dev mode, set the `devMode` parameter to `true` in the request function parameters.");
|
|
1926
|
+
}
|
|
1896
1927
|
// Only proceed with the proof verification if the public inputs are correct
|
|
1897
1928
|
if (verified) {
|
|
1898
1929
|
for (const proof of proofs) {
|
|
@@ -1912,6 +1943,7 @@ export class ZKPassport {
|
|
|
1912
1943
|
validityPeriodInDays: validity,
|
|
1913
1944
|
domain: this.domain,
|
|
1914
1945
|
scope,
|
|
1946
|
+
devMode,
|
|
1915
1947
|
});
|
|
1916
1948
|
const result = await client.readContract({
|
|
1917
1949
|
address,
|
|
@@ -1959,18 +1991,18 @@ export class ZKPassport {
|
|
|
1959
1991
|
if (network === "ethereum_sepolia") {
|
|
1960
1992
|
return {
|
|
1961
1993
|
...baseConfig,
|
|
1962
|
-
address: "
|
|
1994
|
+
address: "0x8c6982D77f7a8f60aE3133cA9b2FAA6f3e78c394",
|
|
1963
1995
|
};
|
|
1964
1996
|
}
|
|
1965
1997
|
else if (network === "local_anvil") {
|
|
1966
1998
|
return {
|
|
1967
1999
|
...baseConfig,
|
|
1968
|
-
address: "
|
|
2000
|
+
address: "0x0",
|
|
1969
2001
|
};
|
|
1970
2002
|
}
|
|
1971
2003
|
throw new Error(`Unsupported network: ${network}`);
|
|
1972
2004
|
}
|
|
1973
|
-
getSolidityVerifierParameters({ proof, validityPeriodInDays = 7, domain, scope, }) {
|
|
2005
|
+
getSolidityVerifierParameters({ proof, validityPeriodInDays = 7, domain, scope, devMode = false, }) {
|
|
1974
2006
|
if (!proof.name?.startsWith("outer_evm")) {
|
|
1975
2007
|
throw new Error("This proof cannot be verified on an EVM chain. Please make sure to use the `compressed-evm` mode.");
|
|
1976
2008
|
}
|
|
@@ -2098,6 +2130,7 @@ export class ZKPassport {
|
|
|
2098
2130
|
validityPeriodInDays,
|
|
2099
2131
|
scope: domain ?? this.domain,
|
|
2100
2132
|
subscope: scope ?? "",
|
|
2133
|
+
devMode,
|
|
2101
2134
|
};
|
|
2102
2135
|
return params;
|
|
2103
2136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkpassport/sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
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",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"@noble/ciphers": "^1.2.1",
|
|
43
43
|
"@noble/hashes": "^1.7.2",
|
|
44
44
|
"@noble/secp256k1": "^2.2.3",
|
|
45
|
-
"@zkpassport/
|
|
45
|
+
"@zkpassport/registry": "^0.1.9",
|
|
46
|
+
"@zkpassport/utils": "^0.7.4",
|
|
46
47
|
"buffer": "^6.0.3",
|
|
47
48
|
"i18n-iso-countries": "^7.12.0",
|
|
48
49
|
"pako": "^2.1.0",
|