Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
eb674c2
update credential expiration to passport expire date value
volodymyr-basiuk Oct 28, 2025
faf4ab0
upd
volodymyr-basiuk Oct 28, 2025
cb9d455
fix unit-test.yaml
volodymyr-basiuk Oct 28, 2025
ca74389
use pnpm
volodymyr-basiuk Oct 28, 2025
67adc8a
undo package.json scripts changes
volodymyr-basiuk Oct 28, 2025
5f39527
unit test setup
volodymyr-basiuk Oct 28, 2025
9fa6cde
Enable Corepack (pnpm)
volodymyr-basiuk Oct 28, 2025
b8cd973
npm ci
volodymyr-basiuk Oct 28, 2025
324b237
yarn install
volodymyr-basiuk Oct 28, 2025
b505747
fix corepack
volodymyr-basiuk Oct 28, 2025
bcd7489
add yarnrc.yml
volodymyr-basiuk Oct 28, 2025
4883881
Install Yarn classic
volodymyr-basiuk Oct 28, 2025
622c52c
rm yarnrc
volodymyr-basiuk Oct 28, 2025
2aa029c
yarn install --frozen-lockfile
volodymyr-basiuk Oct 28, 2025
c8d33d0
"packageManager": "yarn@4.6.0"
volodymyr-basiuk Oct 28, 2025
78c7338
circom_tester
volodymyr-basiuk Oct 28, 2025
6c08a17
undo yarn.lock
volodymyr-basiuk Oct 28, 2025
f376d87
Enable Corepack
volodymyr-basiuk Oct 28, 2025
9f1c2e4
pnpm
volodymyr-basiuk Oct 28, 2025
8cca268
"ts-mocha": "^10.1.0",
volodymyr-basiuk Oct 28, 2025
b383e6c
fix version of dev deps
volodymyr-basiuk Oct 28, 2025
f79c24b
"mocha": "10.7.3",
volodymyr-basiuk Oct 28, 2025
fa165c8
fix
volodymyr-basiuk Oct 28, 2025
d9173cb
undo
volodymyr-basiuk Oct 28, 2025
0be27dc
"@types/node": "^22.13.10",
volodymyr-basiuk Oct 28, 2025
859a049
fix unit-test
volodymyr-basiuk Oct 29, 2025
89bde71
register ts-node
volodymyr-basiuk Oct 29, 2025
dfca379
--extension ts
volodymyr-basiuk Oct 29, 2025
d9b68e3
try with "type": "module",
volodymyr-basiuk Oct 29, 2025
a35fd25
try node
volodymyr-basiuk Oct 29, 2025
90bf071
claenup
volodymyr-basiuk Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/unit-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20.16.0
node-version: 22.15.0

- name: Enable Corepack
run: |
npm i -g corepack@latest
corepack enable
corepack prepare yarn@4.6.0 --activate
corepack prepare pnpm@9.12.0 --activate

- name: Install circom 2.1.9
run: |
Expand Down
6 changes: 2 additions & 4 deletions circuits/credential/credential.circom
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ include "../utils/iden3/constants.circom";
include "../utils/iden3/numbers.circom";
include "../utils/iden3/strings.circom";
include "../utils/passport/parser/extractors.circom";
include "../utils/passport/date/dateDiffGreaterThanYear.circom";

include "self/circuits/circuits/utils/crypto/bitify/bytes.circom";
include "self/circuits/circuits/utils/crypto/hasher/hash.circom";
Expand Down Expand Up @@ -119,7 +118,6 @@ template DG1FieldParser(hashAlgo, nLevels, smtChanges) {
documentDOEExtractor.dg1 <== dg1;
documentDOEExtractor.currentDate <== currentDate;
signal documentDOE <== documentDOEExtractor.out;
signal documentDOETimestamp <== documentDOEExtractor.timestamp;

var keysToUpdate[smtChanges] = [
GetDateOfBirth(), // credentialSubject.dateOfBirth
Expand All @@ -143,8 +141,8 @@ template DG1FieldParser(hashAlgo, nLevels, smtChanges) {
component issuanceDateFitsTo64Bits = CheckMaxBits(64);
issuanceDateFitsTo64Bits.inputInteger <== issuanceDate;

// issuanceDate and documentDOETimestamp are in UnixTimestamp format
signal credentialExpiration <== DateDiffGreaterThanYear()(issuanceDate, documentDOETimestamp);
// documentDOEExtractor.timestamp is in UnixTimestamp format
signal credentialExpiration <== documentDOEExtractor.timestamp;

/*
// For debuging mt update
Expand Down
36 changes: 0 additions & 36 deletions circuits/utils/passport/date/dateDiffGreaterThanYear.circom

This file was deleted.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@
"@zk-email/zk-regex-circom": "^2.3.2",
"@zk-kit/binary-merkle-root.circom": "^1.0.0",
"@zk-kit/circuits": "^1.0.0-beta",
"anon-aadhaar": "git+https://github.com/anon-aadhaar/anon-aadhaar.git",
"asn1": "^0.2.6",
"asn1.js": "^5.4.1",
"asn1js": "^3.0.5",
"circom_tester": "github:remicolin/circom_tester#main",
"circom-bigint": "https://github.com/0xbok/circom-bigint",
"circom-dl": "https://github.com/distributed-lab/circom-dl",
"circom_tester": "0.0.22",
"circomlib": "^2.0.5",
"circomlibjs": "^0.1.7",
"dotenv": "^16.4.7",
Expand All @@ -65,8 +66,7 @@
"js-sha512": "^0.9.0",
"node-forge": "^1.3.1",
"pkijs": "^3.2.5",
"snarkjs": "^0.7.5",
"anon-aadhaar": "git+https://github.com/anon-aadhaar/anon-aadhaar.git",
"self": "git+https://github.com/selfxyz/self.git"
"self": "git+https://github.com/selfxyz/self.git",
"snarkjs": "^0.7.5"
}
}
}
7 changes: 3 additions & 4 deletions tests/credential/credential.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,20 @@ testSuite.forEach(({ shaAlg, shaLength }) => {
);
const inputs = await generateCircuitInputsCredential(passportData, {
currentDate: new Date('2024-01-01'),
issuanceDate: 1742578132000000000n,
expirationDate: 1774114132000000000n
issuanceDate: 1742578132000000000n
});

const w = await circuit.calculateWitness(inputs, true);
await circuit.checkConstraints(w);
// Hash Index
assert(
w[1] === 21746881643302549454056364807195696746352973338897115776686822385268131050953n,
w[1] === 19292235858276444384280114997827871641118146185714873530023364159040018023263n,
`Hash Index: ${w[1]}`
);

// Hash Value
assert(
w[2] === 20008859012517445819901041236908823100073815023181291226591238728478957482360n,
w[2] === 20661880459224054680311568334655353588113926319608771155576598304028828385849n,
`Hash Value: ${w[2]}`
);

Expand Down
5 changes: 0 additions & 5 deletions tests/utils/circuits/dateDiffGreaterThanYear.circom

This file was deleted.

72 changes: 68 additions & 4 deletions utils/circuits/generateInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ export function generateCircuitInputsSignature(
interface Options {
currentDate: Date;
issuanceDate: bigint;
expirationDate: bigint;
}

export async function generateCircuitInputsCredential(passportData: PassportData, opts?: Options) {
Expand Down Expand Up @@ -217,9 +216,7 @@ export async function generateCircuitInputsCredential(passportData: PassportData
const issuerDateTimestamp = opts?.issuanceDate
? opts.issuanceDate / 1000000000n
: BigInt(Math.round(+new Date() / 1000));
const expirationDate = opts?.expirationDate
? opts.expirationDate / 1000000000n
: issuerDateTimestamp + BigInt(365 * 24 * 60 * 60);
const expirationDate = BigInt(new Date(extractExpirationFromMrz(passportData.mrz)).getTime() / 1000)

const updateTemplate = [
'4817156672888655522763064392525239094511187154831557262772815264540847425378',
Expand Down Expand Up @@ -336,3 +333,70 @@ export function formatInput(input: any) {
return [BigInt(input).toString()];
}
}

/**
* Extract expiration date from MRZ (passport / TD3).
*
* Supports TD3 (2 lines × 44 chars) MRZs. If you pass the two-line MRZ
* either as a single string with `\n` between lines, or as a single 88-char
* string (concatenated lines), the function will try to parse it.
*
* Returns ISO date "YYYY-MM-DD" or null if parsing fails.
*/
export function extractExpirationFromMrz(mrz: string): string | null {
if (!mrz || typeof mrz !== "string") return null;

const cleaned = mrz.replace(/\r/g, "").trim();

let lines = cleaned.split("\n").map((l) => l.trim());

// If user passed a single-line 88-char MRZ (two lines concatenated), split it
if (lines.length === 1 && lines[0].length === 88) {
lines = [lines[0].slice(0, 44), lines[0].slice(44, 88)];
}

if (lines.length >= 2) {
const line1 = lines[0];
const line2 = lines[1];

if (line1.length >= 44 && line2.length >= 44) {
const expiryYYMMDD = line2.slice(21, 27); // 6 chars, YYMMDD
const iso = parseMrzDateYYMMDD(expiryYYMMDD);
return iso;
}
}
return null;
}

/**
* Parse YYMMDD (from MRZ) into ISO YYYY-MM-DD.
* Heuristic to choose century:
* - prefer 2000+YY if it results in a year <= (currentYear + 20)
* - otherwise fallback to 1900+YY
*
* Returns ISO date string or null on failure.
*/
function parseMrzDateYYMMDD(yyMMdd: string): string | null {
if (!/^\d{6}$/.test(yyMMdd)) return null;
const yy = parseInt(yyMMdd.slice(0, 2), 10);
const mm = parseInt(yyMMdd.slice(2, 4), 10);
const dd = parseInt(yyMMdd.slice(4, 6), 10);

if (mm < 1 || mm > 12) return null;
if (dd < 1 || dd > 31) return null;

const now = new Date();
const currentYear = now.getUTCFullYear();
const cand2000 = 2000 + yy;
const cand1900 = 1900 + yy;
const year = cand2000 <= currentYear + 20 ? cand2000 : cand1900;

const d = new Date(Date.UTC(year, mm - 1, dd, 0, 0, 0));
if (d.getUTCFullYear() !== year || d.getUTCMonth() !== mm - 1 || d.getUTCDate() !== dd) {
return null;
}
const YYYY = d.getUTCFullYear().toString().padStart(4, "0");
const MM = String(d.getUTCMonth() + 1).padStart(2, "0");
const DD = String(d.getUTCDate()).padStart(2, "0");
return `${YYYY}-${MM}-${DD}`;
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2606,4 +2606,4 @@ yn@^2.0.0:
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==