@zkpassport/sdk 0.2.6 → 0.2.8
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/README.md +1 -1
- package/dist/cjs/index.d.ts +9 -2
- package/dist/cjs/index.js +26 -11
- package/dist/esm/index.d.ts +9 -2
- package/dist/esm/index.js +26 -11
- package/package.json +3 -3
- package/src/index.ts +38 -12
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Privacy-preserving identity verification using passports and ID cards.
|
|
|
4
4
|
|
|
5
5
|
_⚠️ Warning ⚠️_
|
|
6
6
|
|
|
7
|
-
_This
|
|
7
|
+
_This is experimental software that has not been audited yet. Use at your own risk._
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -128,6 +128,7 @@ export type QueryBuilder = {
|
|
|
128
128
|
export declare class ZKPassport {
|
|
129
129
|
private domain;
|
|
130
130
|
private topicToConfig;
|
|
131
|
+
private topicToLocalConfig;
|
|
131
132
|
private topicToKeyPair;
|
|
132
133
|
private topicToWebSocketClient;
|
|
133
134
|
private topicToSharedSecret;
|
|
@@ -154,14 +155,20 @@ export declare class ZKPassport {
|
|
|
154
155
|
private handleEncryptedMessage;
|
|
155
156
|
private getZkPassportRequest;
|
|
156
157
|
/**
|
|
157
|
-
* @notice Create a new request
|
|
158
|
+
* @notice Create a new request
|
|
159
|
+
* @param name Your service name
|
|
160
|
+
* @param logo The logo of your service
|
|
161
|
+
* @param purpose To explain what you want to do with the user's data
|
|
162
|
+
* @param scope Scope this request to a specific use case
|
|
163
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
158
164
|
* @returns The query builder object.
|
|
159
165
|
*/
|
|
160
|
-
request({ name, logo, purpose, scope, topicOverride, keyPairOverride, }: {
|
|
166
|
+
request({ name, logo, purpose, scope, validity, topicOverride, keyPairOverride, }: {
|
|
161
167
|
name: string;
|
|
162
168
|
logo: string;
|
|
163
169
|
purpose: string;
|
|
164
170
|
scope?: string;
|
|
171
|
+
validity?: number;
|
|
165
172
|
topicOverride?: string;
|
|
166
173
|
keyPairOverride?: {
|
|
167
174
|
privateKey: Uint8Array;
|
package/dist/cjs/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const websocket_1 = require("./websocket");
|
|
|
10
10
|
const json_rpc_1 = require("./json-rpc");
|
|
11
11
|
const encryption_1 = require("./encryption");
|
|
12
12
|
const logger_1 = require("./logger");
|
|
13
|
-
const
|
|
13
|
+
const pako_1 = require("pako");
|
|
14
14
|
//import initNoirC from '@noir-lang/noirc_abi'
|
|
15
15
|
//import initACVM from '@noir-lang/acvm_js'
|
|
16
16
|
const en_json_1 = tslib_1.__importDefault(require("i18n-iso-countries/langs/en.json"));
|
|
@@ -18,6 +18,9 @@ const buffer_1 = require("buffer/");
|
|
|
18
18
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
19
19
|
if (typeof globalThis.Buffer === "undefined") {
|
|
20
20
|
globalThis.Buffer = buffer_1.Buffer;
|
|
21
|
+
if (typeof window !== "undefined") {
|
|
22
|
+
window.Buffer = buffer_1.Buffer;
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
(0, i18n_iso_countries_1.registerLocale)(en_json_1.default);
|
|
23
26
|
function hasRequestedAccessToField(credentialsRequest, field) {
|
|
@@ -69,6 +72,7 @@ class ZKPassport {
|
|
|
69
72
|
//private wasmVerifierInit: boolean = false
|
|
70
73
|
constructor(_domain) {
|
|
71
74
|
this.topicToConfig = {};
|
|
75
|
+
this.topicToLocalConfig = {};
|
|
72
76
|
this.topicToKeyPair = {};
|
|
73
77
|
this.topicToWebSocketClient = {};
|
|
74
78
|
this.topicToSharedSecret = {};
|
|
@@ -178,7 +182,7 @@ class ZKPassport {
|
|
|
178
182
|
logger_1.noLogger.debug(`User generated proof`);
|
|
179
183
|
// Uncompress the proof and convert it to a hex string
|
|
180
184
|
const bytesProof = buffer_1.Buffer.from(request.params.proof, "base64");
|
|
181
|
-
const uncompressedProof =
|
|
185
|
+
const uncompressedProof = (0, pako_1.inflate)(bytesProof);
|
|
182
186
|
// The gzip lib in the app compress the proof as ASCII
|
|
183
187
|
// and since the app passes the proof as a hex string, we can
|
|
184
188
|
// just decode the bytes as hex characters using the TextDecoder
|
|
@@ -302,10 +306,15 @@ class ZKPassport {
|
|
|
302
306
|
};
|
|
303
307
|
}
|
|
304
308
|
/**
|
|
305
|
-
* @notice Create a new request
|
|
309
|
+
* @notice Create a new request
|
|
310
|
+
* @param name Your service name
|
|
311
|
+
* @param logo The logo of your service
|
|
312
|
+
* @param purpose To explain what you want to do with the user's data
|
|
313
|
+
* @param scope Scope this request to a specific use case
|
|
314
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
306
315
|
* @returns The query builder object.
|
|
307
316
|
*/
|
|
308
|
-
async request({ name, logo, purpose, scope, topicOverride, keyPairOverride, }) {
|
|
317
|
+
async request({ name, logo, purpose, scope, validity, topicOverride, keyPairOverride, }) {
|
|
309
318
|
const topic = topicOverride || (0, crypto_1.randomBytes)(16).toString("hex");
|
|
310
319
|
const keyPair = keyPairOverride || (await (0, encryption_1.generateECDHKeyPair)());
|
|
311
320
|
this.topicToKeyPair[topic] = {
|
|
@@ -316,6 +325,10 @@ class ZKPassport {
|
|
|
316
325
|
this.topicToService[topic] = { name, logo, purpose, scope };
|
|
317
326
|
this.topicToProofs[topic] = [];
|
|
318
327
|
this.topicToExpectedProofCount[topic] = 0;
|
|
328
|
+
this.topicToLocalConfig[topic] = {
|
|
329
|
+
// Default to 6 months
|
|
330
|
+
validity: validity || 6 * 30,
|
|
331
|
+
};
|
|
319
332
|
this.onRequestReceivedCallbacks[topic] = [];
|
|
320
333
|
this.onGeneratingProofCallbacks[topic] = [];
|
|
321
334
|
this.onBridgeConnectCallbacks[topic] = [];
|
|
@@ -372,7 +385,7 @@ class ZKPassport {
|
|
|
372
385
|
};
|
|
373
386
|
return this.getZkPassportRequest(topic);
|
|
374
387
|
}
|
|
375
|
-
async checkPublicInputs(proofs, queryResult) {
|
|
388
|
+
async checkPublicInputs(proofs, queryResult, topic) {
|
|
376
389
|
let commitmentIn;
|
|
377
390
|
let commitmentOut;
|
|
378
391
|
let isCorrect = true;
|
|
@@ -430,11 +443,12 @@ class ZKPassport {
|
|
|
430
443
|
}
|
|
431
444
|
commitmentOut = (0, utils_1.getCommitmentOutFromIntegrityProof)(proofData);
|
|
432
445
|
const currentDate = (0, utils_1.getCurrentDateFromIntegrityProof)(proofData);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
446
|
+
const todayToCurrentDate = today.getTime() - currentDate.getTime();
|
|
447
|
+
const expectedDifference = this.topicToLocalConfig[topic]?.validity * 86400000;
|
|
448
|
+
const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
|
|
449
|
+
// The ID should not expire within the next 6 months (or whatever the custom value is)
|
|
450
|
+
if (todayToCurrentDate >= actualDifference) {
|
|
451
|
+
console.warn(`The date used to check the validity of the ID is older than ${this.topicToLocalConfig[topic]?.validity} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
|
|
438
452
|
isCorrect = false;
|
|
439
453
|
break;
|
|
440
454
|
}
|
|
@@ -924,7 +938,7 @@ class ZKPassport {
|
|
|
924
938
|
let verified = true;
|
|
925
939
|
let uniqueIdentifier;
|
|
926
940
|
if (queryResult) {
|
|
927
|
-
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult);
|
|
941
|
+
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
|
|
928
942
|
uniqueIdentifier = uniqueIdentifierFromPublicInputs;
|
|
929
943
|
verified = isCorrect;
|
|
930
944
|
}
|
|
@@ -971,6 +985,7 @@ class ZKPassport {
|
|
|
971
985
|
delete this.topicToWebSocketClient[requestId];
|
|
972
986
|
delete this.topicToKeyPair[requestId];
|
|
973
987
|
delete this.topicToConfig[requestId];
|
|
988
|
+
delete this.topicToLocalConfig[requestId];
|
|
974
989
|
delete this.topicToSharedSecret[requestId];
|
|
975
990
|
delete this.topicToProofs[requestId];
|
|
976
991
|
delete this.topicToExpectedProofCount[requestId];
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -128,6 +128,7 @@ export type QueryBuilder = {
|
|
|
128
128
|
export declare class ZKPassport {
|
|
129
129
|
private domain;
|
|
130
130
|
private topicToConfig;
|
|
131
|
+
private topicToLocalConfig;
|
|
131
132
|
private topicToKeyPair;
|
|
132
133
|
private topicToWebSocketClient;
|
|
133
134
|
private topicToSharedSecret;
|
|
@@ -154,14 +155,20 @@ export declare class ZKPassport {
|
|
|
154
155
|
private handleEncryptedMessage;
|
|
155
156
|
private getZkPassportRequest;
|
|
156
157
|
/**
|
|
157
|
-
* @notice Create a new request
|
|
158
|
+
* @notice Create a new request
|
|
159
|
+
* @param name Your service name
|
|
160
|
+
* @param logo The logo of your service
|
|
161
|
+
* @param purpose To explain what you want to do with the user's data
|
|
162
|
+
* @param scope Scope this request to a specific use case
|
|
163
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
158
164
|
* @returns The query builder object.
|
|
159
165
|
*/
|
|
160
|
-
request({ name, logo, purpose, scope, topicOverride, keyPairOverride, }: {
|
|
166
|
+
request({ name, logo, purpose, scope, validity, topicOverride, keyPairOverride, }: {
|
|
161
167
|
name: string;
|
|
162
168
|
logo: string;
|
|
163
169
|
purpose: string;
|
|
164
170
|
scope?: string;
|
|
171
|
+
validity?: number;
|
|
165
172
|
topicOverride?: string;
|
|
166
173
|
keyPairOverride?: {
|
|
167
174
|
privateKey: Uint8Array;
|
package/dist/esm/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { getWebSocketClient } from "./websocket";
|
|
|
6
6
|
import { createEncryptedJsonRpcRequest } from "./json-rpc";
|
|
7
7
|
import { decrypt, generateECDHKeyPair, getSharedSecret } from "./encryption";
|
|
8
8
|
import { noLogger as logger } from "./logger";
|
|
9
|
-
import {
|
|
9
|
+
import { inflate } from "pako";
|
|
10
10
|
//import initNoirC from '@noir-lang/noirc_abi'
|
|
11
11
|
//import initACVM from '@noir-lang/acvm_js'
|
|
12
12
|
import i18en from "i18n-iso-countries/langs/en.json";
|
|
@@ -14,6 +14,9 @@ import { Buffer } from "buffer/";
|
|
|
14
14
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
15
15
|
if (typeof globalThis.Buffer === "undefined") {
|
|
16
16
|
globalThis.Buffer = Buffer;
|
|
17
|
+
if (typeof window !== "undefined") {
|
|
18
|
+
window.Buffer = Buffer;
|
|
19
|
+
}
|
|
17
20
|
}
|
|
18
21
|
registerLocale(i18en);
|
|
19
22
|
function hasRequestedAccessToField(credentialsRequest, field) {
|
|
@@ -59,6 +62,7 @@ export class ZKPassport {
|
|
|
59
62
|
//private wasmVerifierInit: boolean = false
|
|
60
63
|
constructor(_domain) {
|
|
61
64
|
this.topicToConfig = {};
|
|
65
|
+
this.topicToLocalConfig = {};
|
|
62
66
|
this.topicToKeyPair = {};
|
|
63
67
|
this.topicToWebSocketClient = {};
|
|
64
68
|
this.topicToSharedSecret = {};
|
|
@@ -168,7 +172,7 @@ export class ZKPassport {
|
|
|
168
172
|
logger.debug(`User generated proof`);
|
|
169
173
|
// Uncompress the proof and convert it to a hex string
|
|
170
174
|
const bytesProof = Buffer.from(request.params.proof, "base64");
|
|
171
|
-
const uncompressedProof =
|
|
175
|
+
const uncompressedProof = inflate(bytesProof);
|
|
172
176
|
// The gzip lib in the app compress the proof as ASCII
|
|
173
177
|
// and since the app passes the proof as a hex string, we can
|
|
174
178
|
// just decode the bytes as hex characters using the TextDecoder
|
|
@@ -292,10 +296,15 @@ export class ZKPassport {
|
|
|
292
296
|
};
|
|
293
297
|
}
|
|
294
298
|
/**
|
|
295
|
-
* @notice Create a new request
|
|
299
|
+
* @notice Create a new request
|
|
300
|
+
* @param name Your service name
|
|
301
|
+
* @param logo The logo of your service
|
|
302
|
+
* @param purpose To explain what you want to do with the user's data
|
|
303
|
+
* @param scope Scope this request to a specific use case
|
|
304
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
296
305
|
* @returns The query builder object.
|
|
297
306
|
*/
|
|
298
|
-
async request({ name, logo, purpose, scope, topicOverride, keyPairOverride, }) {
|
|
307
|
+
async request({ name, logo, purpose, scope, validity, topicOverride, keyPairOverride, }) {
|
|
299
308
|
const topic = topicOverride || randomBytes(16).toString("hex");
|
|
300
309
|
const keyPair = keyPairOverride || (await generateECDHKeyPair());
|
|
301
310
|
this.topicToKeyPair[topic] = {
|
|
@@ -306,6 +315,10 @@ export class ZKPassport {
|
|
|
306
315
|
this.topicToService[topic] = { name, logo, purpose, scope };
|
|
307
316
|
this.topicToProofs[topic] = [];
|
|
308
317
|
this.topicToExpectedProofCount[topic] = 0;
|
|
318
|
+
this.topicToLocalConfig[topic] = {
|
|
319
|
+
// Default to 6 months
|
|
320
|
+
validity: validity || 6 * 30,
|
|
321
|
+
};
|
|
309
322
|
this.onRequestReceivedCallbacks[topic] = [];
|
|
310
323
|
this.onGeneratingProofCallbacks[topic] = [];
|
|
311
324
|
this.onBridgeConnectCallbacks[topic] = [];
|
|
@@ -362,7 +375,7 @@ export class ZKPassport {
|
|
|
362
375
|
};
|
|
363
376
|
return this.getZkPassportRequest(topic);
|
|
364
377
|
}
|
|
365
|
-
async checkPublicInputs(proofs, queryResult) {
|
|
378
|
+
async checkPublicInputs(proofs, queryResult, topic) {
|
|
366
379
|
let commitmentIn;
|
|
367
380
|
let commitmentOut;
|
|
368
381
|
let isCorrect = true;
|
|
@@ -420,11 +433,12 @@ export class ZKPassport {
|
|
|
420
433
|
}
|
|
421
434
|
commitmentOut = getCommitmentOutFromIntegrityProof(proofData);
|
|
422
435
|
const currentDate = getCurrentDateFromIntegrityProof(proofData);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
436
|
+
const todayToCurrentDate = today.getTime() - currentDate.getTime();
|
|
437
|
+
const expectedDifference = this.topicToLocalConfig[topic]?.validity * 86400000;
|
|
438
|
+
const actualDifference = today.getTime() - (today.getTime() - expectedDifference);
|
|
439
|
+
// The ID should not expire within the next 6 months (or whatever the custom value is)
|
|
440
|
+
if (todayToCurrentDate >= actualDifference) {
|
|
441
|
+
console.warn(`The date used to check the validity of the ID is older than ${this.topicToLocalConfig[topic]?.validity} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
|
|
428
442
|
isCorrect = false;
|
|
429
443
|
break;
|
|
430
444
|
}
|
|
@@ -914,7 +928,7 @@ export class ZKPassport {
|
|
|
914
928
|
let verified = true;
|
|
915
929
|
let uniqueIdentifier;
|
|
916
930
|
if (queryResult) {
|
|
917
|
-
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult);
|
|
931
|
+
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
|
|
918
932
|
uniqueIdentifier = uniqueIdentifierFromPublicInputs;
|
|
919
933
|
verified = isCorrect;
|
|
920
934
|
}
|
|
@@ -961,6 +975,7 @@ export class ZKPassport {
|
|
|
961
975
|
delete this.topicToWebSocketClient[requestId];
|
|
962
976
|
delete this.topicToKeyPair[requestId];
|
|
963
977
|
delete this.topicToConfig[requestId];
|
|
978
|
+
delete this.topicToLocalConfig[requestId];
|
|
964
979
|
delete this.topicToSharedSecret[requestId];
|
|
965
980
|
delete this.topicToProofs[requestId];
|
|
966
981
|
delete this.topicToExpectedProofCount[requestId];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkpassport/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@jest/globals": "^29.7.0",
|
|
32
32
|
"@types/jest": "^29.5.14",
|
|
33
33
|
"@types/node": "^22.10.9",
|
|
34
|
-
"@types/
|
|
34
|
+
"@types/pako": "^2.0.3",
|
|
35
35
|
"@types/ws": "^8.5.12",
|
|
36
36
|
"jest": "^29.7.0",
|
|
37
37
|
"ts-node": "^10.9.2",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@zkpassport/utils": "^0.2.16",
|
|
45
45
|
"buffer": "^6.0.3",
|
|
46
46
|
"i18n-iso-countries": "^7.12.0",
|
|
47
|
-
"
|
|
47
|
+
"pako": "^2.1.0",
|
|
48
48
|
"ws": "^8.18.0"
|
|
49
49
|
},
|
|
50
50
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
package/src/index.ts
CHANGED
|
@@ -37,7 +37,7 @@ import { getWebSocketClient, WebSocketClient } from "./websocket"
|
|
|
37
37
|
import { createEncryptedJsonRpcRequest } from "./json-rpc"
|
|
38
38
|
import { decrypt, generateECDHKeyPair, getSharedSecret } from "./encryption"
|
|
39
39
|
import { noLogger as logger } from "./logger"
|
|
40
|
-
import {
|
|
40
|
+
import { inflate } from "pako"
|
|
41
41
|
//import initNoirC from '@noir-lang/noirc_abi'
|
|
42
42
|
//import initACVM from '@noir-lang/acvm_js'
|
|
43
43
|
import i18en from "i18n-iso-countries/langs/en.json"
|
|
@@ -46,6 +46,9 @@ import { Buffer } from "buffer/"
|
|
|
46
46
|
// If Buffer is not defined, then we use the Buffer from the buffer package
|
|
47
47
|
if (typeof globalThis.Buffer === "undefined") {
|
|
48
48
|
globalThis.Buffer = Buffer as any
|
|
49
|
+
if (typeof window !== "undefined") {
|
|
50
|
+
window.Buffer = Buffer as any
|
|
51
|
+
}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
registerLocale(i18en)
|
|
@@ -257,6 +260,12 @@ export type QueryBuilder = {
|
|
|
257
260
|
export class ZKPassport {
|
|
258
261
|
private domain: string
|
|
259
262
|
private topicToConfig: Record<string, Record<string, IDCredentialConfig>> = {}
|
|
263
|
+
private topicToLocalConfig: Record<
|
|
264
|
+
string,
|
|
265
|
+
{
|
|
266
|
+
validity: number
|
|
267
|
+
}
|
|
268
|
+
> = {}
|
|
260
269
|
private topicToKeyPair: Record<string, { privateKey: Uint8Array; publicKey: Uint8Array }> = {}
|
|
261
270
|
private topicToWebSocketClient: Record<string, WebSocketClient> = {}
|
|
262
271
|
private topicToSharedSecret: Record<string, Uint8Array> = {}
|
|
@@ -395,7 +404,7 @@ export class ZKPassport {
|
|
|
395
404
|
logger.debug(`User generated proof`)
|
|
396
405
|
// Uncompress the proof and convert it to a hex string
|
|
397
406
|
const bytesProof = Buffer.from(request.params.proof, "base64")
|
|
398
|
-
const uncompressedProof =
|
|
407
|
+
const uncompressedProof = inflate(bytesProof)
|
|
399
408
|
// The gzip lib in the app compress the proof as ASCII
|
|
400
409
|
// and since the app passes the proof as a hex string, we can
|
|
401
410
|
// just decode the bytes as hex characters using the TextDecoder
|
|
@@ -543,7 +552,12 @@ export class ZKPassport {
|
|
|
543
552
|
}
|
|
544
553
|
|
|
545
554
|
/**
|
|
546
|
-
* @notice Create a new request
|
|
555
|
+
* @notice Create a new request
|
|
556
|
+
* @param name Your service name
|
|
557
|
+
* @param logo The logo of your service
|
|
558
|
+
* @param purpose To explain what you want to do with the user's data
|
|
559
|
+
* @param scope Scope this request to a specific use case
|
|
560
|
+
* @param validity How many days ago should have the ID been last scanned by the user?
|
|
547
561
|
* @returns The query builder object.
|
|
548
562
|
*/
|
|
549
563
|
public async request({
|
|
@@ -551,6 +565,7 @@ export class ZKPassport {
|
|
|
551
565
|
logo,
|
|
552
566
|
purpose,
|
|
553
567
|
scope,
|
|
568
|
+
validity,
|
|
554
569
|
topicOverride,
|
|
555
570
|
keyPairOverride,
|
|
556
571
|
}: {
|
|
@@ -558,6 +573,7 @@ export class ZKPassport {
|
|
|
558
573
|
logo: string
|
|
559
574
|
purpose: string
|
|
560
575
|
scope?: string
|
|
576
|
+
validity?: number
|
|
561
577
|
topicOverride?: string
|
|
562
578
|
keyPairOverride?: { privateKey: Uint8Array; publicKey: Uint8Array }
|
|
563
579
|
}): Promise<QueryBuilder> {
|
|
@@ -573,6 +589,10 @@ export class ZKPassport {
|
|
|
573
589
|
this.topicToService[topic] = { name, logo, purpose, scope }
|
|
574
590
|
this.topicToProofs[topic] = []
|
|
575
591
|
this.topicToExpectedProofCount[topic] = 0
|
|
592
|
+
this.topicToLocalConfig[topic] = {
|
|
593
|
+
// Default to 6 months
|
|
594
|
+
validity: validity || 6 * 30,
|
|
595
|
+
}
|
|
576
596
|
|
|
577
597
|
this.onRequestReceivedCallbacks[topic] = []
|
|
578
598
|
this.onGeneratingProofCallbacks[topic] = []
|
|
@@ -647,7 +667,11 @@ export class ZKPassport {
|
|
|
647
667
|
return this.getZkPassportRequest(topic)
|
|
648
668
|
}
|
|
649
669
|
|
|
650
|
-
private async checkPublicInputs(
|
|
670
|
+
private async checkPublicInputs(
|
|
671
|
+
proofs: Array<ProofResult>,
|
|
672
|
+
queryResult: QueryResult,
|
|
673
|
+
topic: string,
|
|
674
|
+
) {
|
|
651
675
|
let commitmentIn: bigint | undefined
|
|
652
676
|
let commitmentOut: bigint | undefined
|
|
653
677
|
let isCorrect = true
|
|
@@ -717,13 +741,14 @@ export class ZKPassport {
|
|
|
717
741
|
}
|
|
718
742
|
commitmentOut = getCommitmentOutFromIntegrityProof(proofData)
|
|
719
743
|
const currentDate = getCurrentDateFromIntegrityProof(proofData)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
744
|
+
const todayToCurrentDate = today.getTime() - currentDate.getTime()
|
|
745
|
+
const expectedDifference = this.topicToLocalConfig[topic]?.validity * 86400000
|
|
746
|
+
const actualDifference = today.getTime() - (today.getTime() - expectedDifference)
|
|
747
|
+
// The ID should not expire within the next 6 months (or whatever the custom value is)
|
|
748
|
+
if (todayToCurrentDate >= actualDifference) {
|
|
749
|
+
console.warn(
|
|
750
|
+
`The date used to check the validity of the ID is older than ${this.topicToLocalConfig[topic]?.validity} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`,
|
|
751
|
+
)
|
|
727
752
|
isCorrect = false
|
|
728
753
|
break
|
|
729
754
|
}
|
|
@@ -1306,7 +1331,7 @@ export class ZKPassport {
|
|
|
1306
1331
|
let uniqueIdentifier: string | undefined
|
|
1307
1332
|
if (queryResult) {
|
|
1308
1333
|
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } =
|
|
1309
|
-
await this.checkPublicInputs(proofsToVerify!, queryResult
|
|
1334
|
+
await this.checkPublicInputs(proofsToVerify!, queryResult!, requestId)
|
|
1310
1335
|
uniqueIdentifier = uniqueIdentifierFromPublicInputs
|
|
1311
1336
|
verified = isCorrect
|
|
1312
1337
|
}
|
|
@@ -1361,6 +1386,7 @@ export class ZKPassport {
|
|
|
1361
1386
|
delete this.topicToWebSocketClient[requestId]
|
|
1362
1387
|
delete this.topicToKeyPair[requestId]
|
|
1363
1388
|
delete this.topicToConfig[requestId]
|
|
1389
|
+
delete this.topicToLocalConfig[requestId]
|
|
1364
1390
|
delete this.topicToSharedSecret[requestId]
|
|
1365
1391
|
delete this.topicToProofs[requestId]
|
|
1366
1392
|
delete this.topicToExpectedProofCount[requestId]
|