fix common test

This commit is contained in:
motemotech
2024-12-03 00:23:35 +09:00
parent 194b367f80
commit 3a43dc372a
38 changed files with 47151 additions and 4489 deletions

View File

@@ -1,30 +1,35 @@
# How we process OFAC lists # How we process OFAC lists
## Data Collection ## Data Collection
- We collect the data from the official website of the U.S. Department of the Treasury's Office of Foreign Assets Control (OFAC) and download the data in the form of a CSV file from [here](https://sanctionslist.ofac.treas.gov/Home/SdnList) - We collect the data from the official website of the U.S. Department of the Treasury's Office of Foreign Assets Control (OFAC) and download the data in the form of a CSV file from [here](https://sanctionslist.ofac.treas.gov/Home/SdnList)
- The SDN list contains the names of individuals, entities and groups designated by OFAC as well as the listing of maritime vessels and aircraft that are blocked by OFAC. - The SDN list contains the names of individuals, entities and groups designated by OFAC as well as the listing of maritime vessels and aircraft that are blocked by OFAC.
### ofacdata/original ### ofacdata/original
- The data is stored in the form of 2 CSV files named `sdn.csv` and `add.csv`. `dataspec.txt` explains the data specification for the CSV data files. - The data is stored in the form of 2 CSV files named `sdn.csv` and `add.csv`. `dataspec.txt` explains the data specification for the CSV data files.
- The data is cleaned to obtain the required information for individuals from sdn.csv file. - The data is cleaned to obtain the required information for individuals from sdn.csv file.
A ballpark number of 6917 individuals (at the time of writing this document) entries are present in sdn.csv. Remaining entries are entities, vessels, and aircrafts. A ballpark number of 6917 individuals (at the time of writing this document) entries are present in sdn.csv. Remaining entries are entities, vessels, and aircrafts.
## Data Processing ## Data Processing
### ofacdata/scripts ### ofacdata/scripts
- The `ofac.ipynb` script extracts the data from both the csv's and parses them in json format. - The `ofac.ipynb` script extracts the data from both the csv's and parses them in json format.
- We parse all ethereum addresses, regardless of individual or entity in eth_addresses.json. - We parse all ethereum addresses, regardless of individual or entity in eth_addresses.json.
- For individuals, we parse: - For individuals, we parse:
- full name (first name, last name), dob(day, month, year) in names.json - full name (first name, last name), dob(day, month, year) in names.json
- passports and passport issuing country in passport.json - passports and passport issuing country in passport.json
- The jsons are stored at ofacdata/inputs to be used by SMT's. - The jsons are stored at ofacdata/inputs to be used by SMT's.
## Data Usage ## Data Usage
These jsons are later used to create sparse merkle trees for non-membership proofs. We provide 3 levels of proofs. These jsons are later used to create sparse merkle trees for non-membership proofs. We provide 3 levels of proofs.
- Match through Passport Number: level 3 (Absolute Match) - Match through Passport Number: level 3 (Absolute Match)
- Match through Names and Dob combo tree: level 2 (High Probability Match) - Match through Names and Dob combo tree: level 2 (High Probability Match)
- Match only through Names: level 1 (Partial Match) - Match only through Names: level 1 (Partial Match)
The merkle tree is also exported as json in ofacdata/outputs for time constrained export and import. The merkle tree is also exported as json in ofacdata/outputs for time constrained export and import.
Check out src/utils/smtTree.ts for more details.<br> Check out src/utils/smtTree.ts for more details.<br>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -139391,4 +139391,4 @@
"modulus": "27570890475572156639097623287856775344836252466001838829939036352542925065165961866608001981694334142427166393850202303938965031539138349041940985451272192932917255129033750171058334284262340405798716036258332598943701848757768379165108213023999908375628463308133920742714647194743125516607759412642152196479626108859508107615878099330811114979410920063060013012747400383086275611823457511174768910702059255959955529987050986423961804377001771564313140288755521128325084208639079990434512210328105642000081984169212229143792608985168528834146678403600894638087975271020445992778399449890220397957143415388052709250927", "modulus": "27570890475572156639097623287856775344836252466001838829939036352542925065165961866608001981694334142427166393850202303938965031539138349041940985451272192932917255129033750171058334284262340405798716036258332598943701848757768379165108213023999908375628463308133920742714647194743125516607759412642152196479626108859508107615878099330811114979410920063060013012747400383086275611823457511174768910702059255959955529987050986423961804377001771564313140288755521128325084208639079990434512210328105642000081984169212229143792608985168528834146678403600894638087975271020445992778399449890220397957143415388052709250927",
"exponent": "3" "exponent": "3"
} }
] ]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
"{\n \"root\": [\n \"3723637226454477754871887669092418649720258478086593147152748419758535491072\"\n ],\n \"15584704709027935251733542063227384620511214043307855217534257467792961762417\": [\n \"19105920019330168892048899546191661354446505464368653727052939891020020275805\",\n \"1\",\n \"1\"\n ],\n \"18660127412526139205442115732162973083822266226117299577691589365706228334840\": [\n \"9448785635477331140743014311625361873815551652589535216017416724761959711291\",\n \"1\",\n \"1\"\n ],\n \"6456797921795517597175320242797568338817508339820025997566327150812886169644\": [\n \"14982919419908718594292521020497589548367376867145867222119625916862338523919\",\n \"1\",\n \"1\"\n ],\n \"21448462431008449284508867604706680324695645797406411405909844675752621808583\": [\n \"19703102596598777350706899773704131970636100221024882112358056973375460525180\",\n \"1\",\n \"1\"\n ],\n \"5024298347975147207679629214514067739258346797557077798207564337243614431430\": [\n \"19108373860471292952366838274441500593871822896624734072180780733162956119803\",\n \"1\",\n \"1\"\n ],\n \"11013395557703037597623586619744322870431075171468871030732965621931984693994\": [\n \"18660127412526139205442115732162973083822266226117299577691589365706228334840\",\n \"5024298347975147207679629214514067739258346797557077798207564337243614431430\"\n ],\n \"1729831065139275692261226127032356110526626871751953239635881482684604271822\": [\n \"0\",\n \"11013395557703037597623586619744322870431075171468871030732965621931984693994\"\n ],\n \"1060322943212037380481743131272466461955448453252154411090793429054484697732\": [\n \"0\",\n \"1729831065139275692261226127032356110526626871751953239635881482684604271822\"\n ],\n \"4523419834360633541482415417662748375261328391821173313737837007860212171539\": [\n \"0\",\n \"1060322943212037380481743131272466461955448453252154411090793429054484697732\"\n ],\n \"19887871187824837566992234296328341457952969870292718848038094811162715245761\": [\n \"4523419834360633541482415417662748375261328391821173313737837007860212171539\",\n \"6456797921795517597175320242797568338817508339820025997566327150812886169644\"\n ],\n \"9542848240727884374847323764079677465913066007318782214708529655666364212993\": [\n \"6650657343958618931288105236526996870436425613563673941121571293984874538981\",\n \"1\",\n \"1\"\n ],\n \"9835458972075797025360226408971611448813740733903931664856327566250151778594\": [\n \"9542848240727884374847323764079677465913066007318782214708529655666364212993\",\n \"15584704709027935251733542063227384620511214043307855217534257467792961762417\"\n ],\n \"616896535221117079626842921265491818591744884527738215520950956841510794832\": [\n \"0\",\n \"9835458972075797025360226408971611448813740733903931664856327566250151778594\"\n ],\n \"11054445757535822137133873921702131557138890133764722473542676008237036974196\": [\n \"616896535221117079626842921265491818591744884527738215520950956841510794832\",\n \"19887871187824837566992234296328341457952969870292718848038094811162715245761\"\n ],\n \"3723637226454477754871887669092418649720258478086593147152748419758535491072\": [\n \"21448462431008449284508867604706680324695645797406411405909844675752621808583\",\n \"11054445757535822137133873921702131557138890133764722473542676008237036974196\"\n ]\n}" "{\n \"root\": [\n \"3723637226454477754871887669092418649720258478086593147152748419758535491072\"\n ],\n \"15584704709027935251733542063227384620511214043307855217534257467792961762417\": [\n \"19105920019330168892048899546191661354446505464368653727052939891020020275805\",\n \"1\",\n \"1\"\n ],\n \"18660127412526139205442115732162973083822266226117299577691589365706228334840\": [\n \"9448785635477331140743014311625361873815551652589535216017416724761959711291\",\n \"1\",\n \"1\"\n ],\n \"6456797921795517597175320242797568338817508339820025997566327150812886169644\": [\n \"14982919419908718594292521020497589548367376867145867222119625916862338523919\",\n \"1\",\n \"1\"\n ],\n \"21448462431008449284508867604706680324695645797406411405909844675752621808583\": [\n \"19703102596598777350706899773704131970636100221024882112358056973375460525180\",\n \"1\",\n \"1\"\n ],\n \"5024298347975147207679629214514067739258346797557077798207564337243614431430\": [\n \"19108373860471292952366838274441500593871822896624734072180780733162956119803\",\n \"1\",\n \"1\"\n ],\n \"11013395557703037597623586619744322870431075171468871030732965621931984693994\": [\n \"18660127412526139205442115732162973083822266226117299577691589365706228334840\",\n \"5024298347975147207679629214514067739258346797557077798207564337243614431430\"\n ],\n \"1729831065139275692261226127032356110526626871751953239635881482684604271822\": [\n \"0\",\n \"11013395557703037597623586619744322870431075171468871030732965621931984693994\"\n ],\n \"1060322943212037380481743131272466461955448453252154411090793429054484697732\": [\n \"0\",\n \"1729831065139275692261226127032356110526626871751953239635881482684604271822\"\n ],\n \"4523419834360633541482415417662748375261328391821173313737837007860212171539\": [\n \"0\",\n \"1060322943212037380481743131272466461955448453252154411090793429054484697732\"\n ],\n \"19887871187824837566992234296328341457952969870292718848038094811162715245761\": [\n \"4523419834360633541482415417662748375261328391821173313737837007860212171539\",\n \"6456797921795517597175320242797568338817508339820025997566327150812886169644\"\n ],\n \"9542848240727884374847323764079677465913066007318782214708529655666364212993\": [\n \"6650657343958618931288105236526996870436425613563673941121571293984874538981\",\n \"1\",\n \"1\"\n ],\n \"9835458972075797025360226408971611448813740733903931664856327566250151778594\": [\n \"9542848240727884374847323764079677465913066007318782214708529655666364212993\",\n \"15584704709027935251733542063227384620511214043307855217534257467792961762417\"\n ],\n \"616896535221117079626842921265491818591744884527738215520950956841510794832\": [\n \"0\",\n \"9835458972075797025360226408971611448813740733903931664856327566250151778594\"\n ],\n \"11054445757535822137133873921702131557138890133764722473542676008237036974196\": [\n \"616896535221117079626842921265491818591744884527738215520950956841510794832\",\n \"19887871187824837566992234296328341457952969870292718848038094811162715245761\"\n ],\n \"3723637226454477754871887669092418649720258478086593147152748419758535491072\": [\n \"21448462431008449284508867604706680324695645797406411405909844675752621808583\",\n \"11054445757535822137133873921702131557138890133764722473542676008237036974196\"\n ]\n}"

View File

@@ -5,43 +5,43 @@ const srcDir = path.join(__dirname, '..', '..', 'src', 'mock_certificates');
const outputFile = path.join(__dirname, '..', '..', 'src', 'constants', 'mockCertificates.ts'); const outputFile = path.join(__dirname, '..', '..', 'src', 'constants', 'mockCertificates.ts');
const algorithms = [ const algorithms = [
'sha1_rsa_2048', 'sha1_rsa_2048',
'sha1_rsa_4096', 'sha1_rsa_4096',
'sha256_rsa_2048', 'sha256_rsa_2048',
'sha256_rsa_4096', 'sha256_rsa_4096',
'sha256_rsapss_2048', 'sha256_rsapss_2048',
'sha256_rsapss_4096', 'sha256_rsapss_4096',
]; ];
function readFile(dir: string, filename: string): string | null { function readFile(dir: string, filename: string): string | null {
const filePath = path.join(dir, filename); const filePath = path.join(dir, filename);
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
return fs.readFileSync(filePath, 'utf-8').trim(); return fs.readFileSync(filePath, 'utf-8').trim();
} }
return null; return null;
} }
let output = ''; let output = '';
algorithms.forEach((algo) => { algorithms.forEach((algo) => {
const algoDir = path.join(srcDir, algo); const algoDir = path.join(srcDir, algo);
const cscaCert = readFile(algoDir, 'mock_csca.crt') || readFile(algoDir, 'mock_csca.pem'); const cscaCert = readFile(algoDir, 'mock_csca.crt') || readFile(algoDir, 'mock_csca.pem');
const dscCert = readFile(algoDir, 'mock_dsc.crt') || readFile(algoDir, 'mock_dsc.pem'); const dscCert = readFile(algoDir, 'mock_dsc.crt') || readFile(algoDir, 'mock_dsc.pem');
const dscKey = readFile(algoDir, 'mock_dsc.key'); const dscKey = readFile(algoDir, 'mock_dsc.key');
if (cscaCert) { if (cscaCert) {
output += `export const mock_csca_${algo} = \`${cscaCert}\`\n\n`; output += `export const mock_csca_${algo} = \`${cscaCert}\`\n\n`;
} }
if (dscCert) { if (dscCert) {
output += `export const mock_dsc_${algo} = \`${dscCert}\`\n\n`; output += `export const mock_dsc_${algo} = \`${dscCert}\`\n\n`;
} }
if (dscKey) { if (dscKey) {
output += `export const mock_dsc_key_${algo} = \`${dscKey}\`\n\n`; output += `export const mock_dsc_key_${algo} = \`${dscKey}\`\n\n`;
} }
}); });
fs.writeFileSync(outputFile, output); fs.writeFileSync(outputFile, output);
console.log(`Certificates and keys have been written to ${outputFile}`); console.log(`Certificates and keys have been written to ${outputFile}`);

File diff suppressed because it is too large Load Diff

View File

@@ -24,4 +24,4 @@ export const DSC_BLINDED_DSC_COMMITMENT_INDEX = 0;
// Enum in VerifiersManager.sol // Enum in VerifiersManager.sol
export const VERIFICATION_TYPE_ENUM_PROVE = 0; export const VERIFICATION_TYPE_ENUM_PROVE = 0;
export const VERIFICATION_TYPE_ENUM_DSC = 1; export const VERIFICATION_TYPE_ENUM_DSC = 1;

View File

@@ -15,7 +15,7 @@ Tg9gkA98zvV1jbokPL23UXRWufv7L44HIFr3bLeikdOmpf6Lvp1ORiUXjbMi9o+c
ty+gWrxsV+825W3LGD/71DFSD4yS8wK9M9KLZb/21bt6tq4D/E3njnYbXID+1dTL ty+gWrxsV+825W3LGD/71DFSD4yS8wK9M9KLZb/21bt6tq4D/E3njnYbXID+1dTL
WC/4nCtzhd5n6cq1wKl6VnZ6bcyYb8MSQ6Kd6vbew1UnRae8KmFsjr2tJ50ESTj4 WC/4nCtzhd5n6cq1wKl6VnZ6bcyYb8MSQ6Kd6vbew1UnRae8KmFsjr2tJ50ESTj4
jQwzIZELkOP+EAE= jQwzIZELkOP+EAE=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha1_rsa_2048 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha1_rsa_2048 = `-----BEGIN CERTIFICATE-----
MIIC9zCCAd+gAwIBAgIUTwHaCSG0zF1Qc7zH9crP0SpqSIMwDQYJKoZIhvcNAQEF MIIC9zCCAd+gAwIBAgIUTwHaCSG0zF1Qc7zH9crP0SpqSIMwDQYJKoZIhvcNAQEF
@@ -34,7 +34,7 @@ ZOL+iNt1vNugU2Ur8FbdpbaMrNDkabWSnOiXVKJ6exXYTvdghaF3P4LkZoiutMXz
/VJ+tmeWZzhVhTQnrN0FBxvh0wfdbbdbosVaJsyB0xTD6C3aBlUTVtxdLdf3B2CA /VJ+tmeWZzhVhTQnrN0FBxvh0wfdbbdbosVaJsyB0xTD6C3aBlUTVtxdLdf3B2CA
N0/RDh6kwOOv9mcyF9u/z/YxiZB23csSJyLMmUl9WV2xPCgSZi3A1sZqOU5IIqO3 N0/RDh6kwOOv9mcyF9u/z/YxiZB23csSJyLMmUl9WV2xPCgSZi3A1sZqOU5IIqO3
U4o97Nxcwj51Bm6x5Km/6/CbnXXRo+x+nHgAgYwMn42r4BrLFoDLUn9YRw== U4o97Nxcwj51Bm6x5Km/6/CbnXXRo+x+nHgAgYwMn42r4BrLFoDLUn9YRw==
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_key_sha1_rsa_2048 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha1_rsa_2048 = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNAbRAvBrCOUcQ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNAbRAvBrCOUcQ
@@ -63,7 +63,7 @@ Mt8oOSrL/umhcLnBzjQnWBeRe7frD4+a7COxmW71AoGBAO0yhYXOeHpGTnHzDzTs
qu3rNhvQKy/8f25wvqn/xR5NfbcQv/Z63PgmDoq9VLrmeektwY4zTE9wO+n7WPQU qu3rNhvQKy/8f25wvqn/xR5NfbcQv/Z63PgmDoq9VLrmeektwY4zTE9wO+n7WPQU
D2BiW2DQjX4OJsOPNs63+wCE71xj08ZxipFuxFWhbjtO/A82h6QMXYwfj9do1WGD D2BiW2DQjX4OJsOPNs63+wCE71xj08ZxipFuxFWhbjtO/A82h6QMXYwfj9do1WGD
oouEG7wJwn8++cuiivyeTWf1 oouEG7wJwn8++cuiivyeTWf1
-----END PRIVATE KEY-----` -----END PRIVATE KEY-----`;
export const mock_csca_sha1_rsa_4096 = `-----BEGIN CERTIFICATE----- export const mock_csca_sha1_rsa_4096 = `-----BEGIN CERTIFICATE-----
MIIFCTCCAvGgAwIBAgIUPfIaBL/H++x5cwbWjRnVae1VV3owDQYJKoZIhvcNAQEF MIIFCTCCAvGgAwIBAgIUPfIaBL/H++x5cwbWjRnVae1VV3owDQYJKoZIhvcNAQEF
@@ -93,7 +93,7 @@ uMGxRcwP+pPD0lApldU1uEq317cE1gtnZVjNRiZRuVTzaOA0PH98ExjZrmNgbf5o
iIUrC81FHCcvGJmzJdHosAOLRkFZMZS+7ZQ6+dTE4sQwrmSdSVWxNQTRMDjlHgXR iIUrC81FHCcvGJmzJdHosAOLRkFZMZS+7ZQ6+dTE4sQwrmSdSVWxNQTRMDjlHgXR
Nqlr+Uj3X+gds1fa0UO6QvCQUmEnRZxXv57HPKobdPJxGtHBUS+2s/3CdFy0KSHB Nqlr+Uj3X+gds1fa0UO6QvCQUmEnRZxXv57HPKobdPJxGtHBUS+2s/3CdFy0KSHB
DeNeFcCggkhoeQqG9D3EXjGz4gre+XjGaH1wPVW0oQoV5BvKsBsMBz2oaZEX DeNeFcCggkhoeQqG9D3EXjGz4gre+XjGaH1wPVW0oQoV5BvKsBsMBz2oaZEX
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha1_rsa_4096 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha1_rsa_4096 = `-----BEGIN CERTIFICATE-----
MIID9zCCAd+gAwIBAgIUOUB6xleW+ZGTlubYVAXbnjcaBWkwDQYJKoZIhvcNAQEF MIID9zCCAd+gAwIBAgIUOUB6xleW+ZGTlubYVAXbnjcaBWkwDQYJKoZIhvcNAQEF
@@ -118,7 +118,7 @@ hi2vmJ/bxS/Ka3mTbaM/3N3T1pLJnSn3vX4IrRH+wb6iQXzGu0Kc7zdYhWBJsv1e
vK/Cc6gkv9LGCBE4m3qfuK0FTuTUTjq2cZgJObDii3oK36Is9MdOPlGhWU1mamlI vK/Cc6gkv9LGCBE4m3qfuK0FTuTUTjq2cZgJObDii3oK36Is9MdOPlGhWU1mamlI
wneTF59va2XHfVHmfEv9nPCDBD7YIOxYiQADJ+CJlbq/oe/l0vXvNq+5ikbUus2E wneTF59va2XHfVHmfEv9nPCDBD7YIOxYiQADJ+CJlbq/oe/l0vXvNq+5ikbUus2E
VeMUAwXpTAUekrk= VeMUAwXpTAUekrk=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_key_sha1_rsa_4096 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha1_rsa_4096 = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyFWWOPc09c5/t MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyFWWOPc09c5/t
@@ -147,7 +147,7 @@ fhKFSY14PT560FMvl2GTnolAtzyl3h5xnCks3iAzAoGBAO432byCx+qpdPST9/Vc
T6d6bpNA4Ozcs0nFSfuBbHyUXP2M7j26QrEVOlPqdnp7oHRUIqJTNEiQK2avSSgl T6d6bpNA4Ozcs0nFSfuBbHyUXP2M7j26QrEVOlPqdnp7oHRUIqJTNEiQK2avSSgl
kA4pOhZnWoSso9huxc2ookVVvuWWSZeOhqheOVL4cxTwTjLXQzUa+cjVuVaE1+iD kA4pOhZnWoSso9huxc2ookVVvuWWSZeOhqheOVL4cxTwTjLXQzUa+cjVuVaE1+iD
hxoG8r16SNNAZudx/NDpx1hO hxoG8r16SNNAZudx/NDpx1hO
-----END PRIVATE KEY-----` -----END PRIVATE KEY-----`;
export const mock_csca_sha256_rsa_2048 = `-----BEGIN CERTIFICATE----- export const mock_csca_sha256_rsa_2048 = `-----BEGIN CERTIFICATE-----
MIID2TCCAsGgAwIBAgIUZJXTESdl0B2qGCUUzv50dNl4VwEwDQYJKoZIhvcNAQEL MIID2TCCAsGgAwIBAgIUZJXTESdl0B2qGCUUzv50dNl4VwEwDQYJKoZIhvcNAQEL
@@ -171,7 +171,7 @@ em+yZOTcNKaebx7h6Zokw7+dFKcDV5TjbkB7WYNoejp1bbCo0kNcd6C5N+WmTJkI
0rcRlUErjhIhL3DweERauQnkIltElAwV7Hiwei2cpVl6tLiWO4GydliwxxFod8AW 0rcRlUErjhIhL3DweERauQnkIltElAwV7Hiwei2cpVl6tLiWO4GydliwxxFod8AW
h88UCDvQ5BjuDnIEW1pER9MbEa5TcQa97D1ads0Unt16E86QIelLxAgdBFvd+4ip h88UCDvQ5BjuDnIEW1pER9MbEa5TcQa97D1ads0Unt16E86QIelLxAgdBFvd+4ip
BgA3N9B0gIhmwTvjrGT3WSG+GpQmmokIx+1bRNI= BgA3N9B0gIhmwTvjrGT3WSG+GpQmmokIx+1bRNI=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha256_rsa_2048 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_rsa_2048 = `-----BEGIN CERTIFICATE-----
MIIDzzCCAregAwIBAgIURN604AIW+1RhbYMsyVJsuzSSrqkwDQYJKoZIhvcNAQEL MIIDzzCCAregAwIBAgIURN604AIW+1RhbYMsyVJsuzSSrqkwDQYJKoZIhvcNAQEL
@@ -195,7 +195,7 @@ LkYTkJCu1UhFWM08NS/JCyjoNEN7JUHD46MzV1Q8yf8UB55jlvRpfqXM+0wUkWtO
Fv00AEvS6Tdui1MbZ/HJAkFsV83ZkYb+wOZAqmh0+Ea46dzMlwuYweKl596fwozo Fv00AEvS6Tdui1MbZ/HJAkFsV83ZkYb+wOZAqmh0+Ea46dzMlwuYweKl596fwozo
ZFFNG/h2wwkcakWW1fW980jyvj+Gm6k45YworZ+bT8uoWZTloo1MUFMjdsVRI8FL ZFFNG/h2wwkcakWW1fW980jyvj+Gm6k45YworZ+bT8uoWZTloo1MUFMjdsVRI8FL
M68d6u5tbDtdO8mMPeMIRMq/ug== M68d6u5tbDtdO8mMPeMIRMq/ug==
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_csca_sha256_rsa_4096 = `-----BEGIN CERTIFICATE----- export const mock_csca_sha256_rsa_4096 = `-----BEGIN CERTIFICATE-----
MIIFpzCCA4+gAwIBAgIUVGoAk38qsh7YYIE2eANMIeZkr+IwDQYJKoZIhvcNAQEL MIIFpzCCA4+gAwIBAgIUVGoAk38qsh7YYIE2eANMIeZkr+IwDQYJKoZIhvcNAQEL
@@ -229,7 +229,7 @@ v9tNSlP4Tyzr2b1VoQcgmpQ987afINJG39lq2OsSrlK87p9bB4yoFSZwOfqok0nM
IICRxBuTUHLqP3Nhvo+tAl+iK848LDJVf87ZVQHl72JX4lkVvOo5LCXnOQPyowaP IICRxBuTUHLqP3Nhvo+tAl+iK848LDJVf87ZVQHl72JX4lkVvOo5LCXnOQPyowaP
D++J2c6tUj6gs9HAKVX7fH06m/2T5fJHae/OYx36O242yBXPQdHx6qloF/DNvGyM D++J2c6tUj6gs9HAKVX7fH06m/2T5fJHae/OYx36O242yBXPQdHx6qloF/DNvGyM
EHC3NCCjLG5m6G0= EHC3NCCjLG5m6G0=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha256_rsa_4096 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_rsa_4096 = `-----BEGIN CERTIFICATE-----
MIIEkDCCAnigAwIBAgIUVWuy5jJJ5sj+QZfD5gWs3rESlFswDQYJKoZIhvcNAQEL MIIEkDCCAnigAwIBAgIUVWuy5jJJ5sj+QZfD5gWs3rESlFswDQYJKoZIhvcNAQEL
@@ -257,7 +257,7 @@ WatGH8+eROdlpTfF/xaAUbCJ2UYjRUupGkrpU5KkS9FxrJSVS44PO3xuJwQJN1fC
x2clYiqOEhyESrTp6c5XAGK78S0dwBP2R9o7GqY5xNI+kXBJakqyVpwIPRDq4HVo x2clYiqOEhyESrTp6c5XAGK78S0dwBP2R9o7GqY5xNI+kXBJakqyVpwIPRDq4HVo
y9QRS1jM1G/2Y1XAE9pMdMjdhfYCCp/lO48swOQDty137gzfffo0Bn0039VKzhgi y9QRS1jM1G/2Y1XAE9pMdMjdhfYCCp/lO48swOQDty137gzfffo0Bn0039VKzhgi
nUCb8Z7CclWppvFAVjnJruJbGp4= nUCb8Z7CclWppvFAVjnJruJbGp4=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_key_sha256_rsa_4096 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha256_rsa_4096 = `-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDbmfvDt6mQHKcW MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDbmfvDt6mQHKcW
@@ -286,7 +286,7 @@ GudUJ9vK1QUulK21It6mF68mysnvifLmAqFm3FhW+QKBgQDVSCw1x3QAtkSswJRX
NFGvIdBSeGBqPpyn4XVU8eQav/uZcjcrB77AemaCG/BwGDQA/nU0eUam0cJn3MP2 NFGvIdBSeGBqPpyn4XVU8eQav/uZcjcrB77AemaCG/BwGDQA/nU0eUam0cJn3MP2
NDxMDWR56waCH8Ug/iC0ickLaev1lwj9FvwRpmDLxbmJM4aQgbQw/I1KkSP4ZOAO NDxMDWR56waCH8Ug/iC0ickLaev1lwj9FvwRpmDLxbmJM4aQgbQw/I1KkSP4ZOAO
2+/QeO6/dvQ2u8OvYn6l0Ls41g== 2+/QeO6/dvQ2u8OvYn6l0Ls41g==
-----END PRIVATE KEY-----` -----END PRIVATE KEY-----`;
export const mock_csca_sha256_rsapss_2048 = `-----BEGIN CERTIFICATE----- export const mock_csca_sha256_rsapss_2048 = `-----BEGIN CERTIFICATE-----
MIIDbzCCAiOgAwIBAgIUOXPStXBBfo+yy5ooXC8RB8EeoXMwQQYJKoZIhvcNAQEK MIIDbzCCAiOgAwIBAgIUOXPStXBBfo+yy5ooXC8RB8EeoXMwQQYJKoZIhvcNAQEK
@@ -308,7 +308,7 @@ Mh6+zaJVfiWJoaW/G43j6b4Iarzhiu+hl4WXiQJFQ6Ya3o/MwEQmBV/RnmKHcEq4
tmmZDfBnFxY3RfSPliR81niP0EWD0pxIDI6CzuuqmI+vXnRRob3MAa8mfefof34T tmmZDfBnFxY3RfSPliR81niP0EWD0pxIDI6CzuuqmI+vXnRRob3MAa8mfefof34T
rA0kQqEcklmJFh95bOODC7UjOZlDDTEt7Mxg8CGKwrBxaEN79XCfpDH6kPnNqnfl rA0kQqEcklmJFh95bOODC7UjOZlDDTEt7Mxg8CGKwrBxaEN79XCfpDH6kPnNqnfl
W3IkvjmEJJY6dZOOrjyYZ+2ReA== W3IkvjmEJJY6dZOOrjyYZ+2ReA==
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha256_rsapss_2048 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_rsapss_2048 = `-----BEGIN CERTIFICATE-----
MIIDXTCCAhGgAwIBAgIUbOJrpiPFgnwWkNUmues/B8JMbf8wQQYJKoZIhvcNAQEK MIIDXTCCAhGgAwIBAgIUbOJrpiPFgnwWkNUmues/B8JMbf8wQQYJKoZIhvcNAQEK
@@ -330,7 +330,7 @@ CgJQjLO9n2Ek7IWj1yy0BBTl5UWCsCBdv8CSDorBI+UlOyzbFMvl2wxp8MMOw8oZ
Z3WWH5U/MDtSFDQFTJLRTIlPHl5wtoqCLgZC+fqqmnY1oHPj7KCv2lIFHuTdCbrD Z3WWH5U/MDtSFDQFTJLRTIlPHl5wtoqCLgZC+fqqmnY1oHPj7KCv2lIFHuTdCbrD
QVmOLpEmz/j8CpSgXpMqBp9A5KTjfZaW5FvBw4O3I7JapyZold9gt50G33ky35S0 QVmOLpEmz/j8CpSgXpMqBp9A5KTjfZaW5FvBw4O3I7JapyZold9gt50G33ky35S0
gQ== gQ==
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_key_sha256_rsapss_2048 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha256_rsapss_2048 = `-----BEGIN PRIVATE KEY-----
MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEAwcchJBbCnUPAeMSu MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEAwcchJBbCnUPAeMSu
@@ -359,7 +359,7 @@ nUT+0WKQYT6ie+WMN+ryiRjyTzIKCzQHPGBlcQKBgQDFP00AGgLW8yQYj5rxNdif
ok4FOnU5hQHaDwDGqc51Xpl1SqTUc8sNYDqauMIupoq9c37lCzljUakLpFra1DK1 ok4FOnU5hQHaDwDGqc51Xpl1SqTUc8sNYDqauMIupoq9c37lCzljUakLpFra1DK1
i4UYRl1inWp3BqGVE5V0GN/NYAtQiKUNM5iXf+10UUNrlsJujD6DQL0tttnAFsWl i4UYRl1inWp3BqGVE5V0GN/NYAtQiKUNM5iXf+10UUNrlsJujD6DQL0tttnAFsWl
gR8ctVfp/DLstUdwl54qiQ== gR8ctVfp/DLstUdwl54qiQ==
-----END PRIVATE KEY-----` -----END PRIVATE KEY-----`;
export const mock_csca_sha256_rsapss_4096 = `-----BEGIN CERTIFICATE----- export const mock_csca_sha256_rsapss_4096 = `-----BEGIN CERTIFICATE-----
MIIFbzCCAyOgAwIBAgIUcPyz9NNu9cv8bmvhreKdo5w6JhcwQQYJKoZIhvcNAQEK MIIFbzCCAyOgAwIBAgIUcPyz9NNu9cv8bmvhreKdo5w6JhcwQQYJKoZIhvcNAQEK
@@ -392,7 +392,7 @@ JrurbPjiZ+f+ie/WAI730Mo3OOKnv6z+6qIPr4KqM9MOpECp9u8J0VcWhIDCrYhe
ZOhjTvvbwLrq4Smh8iH6C20IZFK5Je//SOkolBvsRh6ToQoJerR1lWGVlX4ljN8o ZOhjTvvbwLrq4Smh8iH6C20IZFK5Je//SOkolBvsRh6ToQoJerR1lWGVlX4ljN8o
9g5hp1KC7Fe25/7Ga14YFAjrXIeRp59zpNCkX4swvUQiSYM4BQTsaNmBEvQQnlT+ 9g5hp1KC7Fe25/7Ga14YFAjrXIeRp59zpNCkX4swvUQiSYM4BQTsaNmBEvQQnlT+
9OCw 9OCw
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_sha256_rsapss_4096 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_rsapss_4096 = `-----BEGIN CERTIFICATE-----
MIIEXTCCAhGgAwIBAgIUdS5K/Y5Ty0C8hDFibjmvBeQr4SgwQQYJKoZIhvcNAQEK MIIEXTCCAhGgAwIBAgIUdS5K/Y5Ty0C8hDFibjmvBeQr4SgwQQYJKoZIhvcNAQEK
@@ -419,7 +419,7 @@ pCrZG4WfUY8ifggReHLoLWSFF8S4JqBKykRu67fbkXLe52VgnYSv6GVxvf1N7mhD
O50iFYNDXId0SgL+adTylqIsr5l5BQw84vf2m+PO8xX2PPFTO6kUsivr9d5cUgVh O50iFYNDXId0SgL+adTylqIsr5l5BQw84vf2m+PO8xX2PPFTO6kUsivr9d5cUgVh
duDfJWPas4d3FKdmuSqnUUh7tGWZctzXnA0kBVXa1j5OtU5w+1qp9pbtv/kci2OH duDfJWPas4d3FKdmuSqnUUh7tGWZctzXnA0kBVXa1j5OtU5w+1qp9pbtv/kci2OH
FnvLWs1nzkj58FcjpVG0+ZM= FnvLWs1nzkj58FcjpVG0+ZM=
-----END CERTIFICATE-----` -----END CERTIFICATE-----`;
export const mock_dsc_key_sha256_rsapss_4096 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha256_rsapss_4096 = `-----BEGIN PRIVATE KEY-----
MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEA8De9Voa/OjiMqyxU MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEA8De9Voa/OjiMqyxU
@@ -448,14 +448,14 @@ auVZ0ifaBx68dHXkVr6TUNpGnoZ6C4TtLqvPaQKBgQDm66dlLxat1KDfEMXmpOMq
MNaFmxLFgtNngCKgGxHcjOtaMYonPGXVO1uBn+aM4Bcj3Kx21zm8DJBLQmUyIzjc MNaFmxLFgtNngCKgGxHcjOtaMYonPGXVO1uBn+aM4Bcj3Kx21zm8DJBLQmUyIzjc
bUTICRnwWI2dWQz/K5VQuMdEDhxpzDw4uhBun97HlwEZnQnMxrf4whDby1yEnMrk bUTICRnwWI2dWQz/K5VQuMdEDhxpzDw4uhBun97HlwEZnQnMxrf4whDby1yEnMrk
jXtnkq7Exo0bOsVwH7VNkw== jXtnkq7Exo0bOsVwH7VNkw==
-----END PRIVATE KEY-----` -----END PRIVATE KEY-----`;
export const mock_dsc_key_sha256_ecdsa = `-----BEGIN EC PRIVATE KEY----- export const mock_dsc_key_sha256_ecdsa = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILM+tyrOADmGjsoNiF/MBuvIscs80M4i1QjVnDy/VBJkoAoGCCqGSM49 MHcCAQEEILM+tyrOADmGjsoNiF/MBuvIscs80M4i1QjVnDy/VBJkoAoGCCqGSM49
AwEHoUQDQgAEQGjDJAD3r/b7oRH2TrgidhLtX+ThLntgul4cdoSEb1fmFcrTgXr4 AwEHoUQDQgAEQGjDJAD3r/b7oRH2TrgidhLtX+ThLntgul4cdoSEb1fmFcrTgXr4
utAT4/K3aMZ3GrVtCMb5e94lwOlhuOdPdw== utAT4/K3aMZ3GrVtCMb5e94lwOlhuOdPdw==
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----
` `;
export const mock_dsc_sha256_ecdsa = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_ecdsa = `-----BEGIN CERTIFICATE-----
MIICBzCCAa2gAwIBAgIUepk5fECPtH8DJL55fJcGsPCHHowwCgYIKoZIzj0EAwIw MIICBzCCAa2gAwIBAgIUepk5fECPtH8DJL55fJcGsPCHHowwCgYIKoZIzj0EAwIw
@@ -470,14 +470,14 @@ xncatW0Ixvl73iXA6WG45093oyEwHzAdBgNVHQ4EFgQUUa6p5iCBqbhslwC79LHX
EyYTiP0wCgYIKoZIzj0EAwIDSAAwRQIhAP6XA1AWr8v6f7EJz3u5GuudyCKqiuBY EyYTiP0wCgYIKoZIzj0EAwIDSAAwRQIhAP6XA1AWr8v6f7EJz3u5GuudyCKqiuBY
mDhB0W8OhhR2AiAMTm++57YJkbQNxzL75nypXSdZmBfiQXSNM0NFpHEuIQ== mDhB0W8OhhR2AiAMTm++57YJkbQNxzL75nypXSdZmBfiQXSNM0NFpHEuIQ==
-----END CERTIFICATE----- -----END CERTIFICATE-----
` `;
export const mock_dsc_key_sha1_ecdsa = `-----BEGIN EC PRIVATE KEY----- export const mock_dsc_key_sha1_ecdsa = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIK2wRGm6xnmTnHhOtyUxp/PFPTySoaD+f2JNXy9JAmRVoAoGCCqGSM49 MHcCAQEEIK2wRGm6xnmTnHhOtyUxp/PFPTySoaD+f2JNXy9JAmRVoAoGCCqGSM49
AwEHoUQDQgAEzqM5vQEv7vhD7ZXecfkSvC/vfDffjuEyUK3DLlvjbxUIXeaJ+dUg AwEHoUQDQgAEzqM5vQEv7vhD7ZXecfkSvC/vfDffjuEyUK3DLlvjbxUIXeaJ+dUg
zb8+rYwVh+Ai/DDxCLuSy2wn4gbOFwzOGA== zb8+rYwVh+Ai/DDxCLuSy2wn4gbOFwzOGA==
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----
` `;
export const mock_dsc_sha1_ecdsa = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha1_ecdsa = `-----BEGIN CERTIFICATE-----
MIICBDCCAaygAwIBAgIULaL4N+BRrqV1D8UeefZegXfkWogwCQYHKoZIzj0EATBy MIICBDCCAaygAwIBAgIULaL4N+BRrqV1D8UeefZegXfkWogwCQYHKoZIzj0EATBy
@@ -492,7 +492,7 @@ Ivww8Qi7kstsJ+IGzhcMzhijITAfMB0GA1UdDgQWBBTRmLBSAQr3AAI4didYznX/
mEvuzDAJBgcqhkjOPQQBA0cAMEQCIB25iNcA7Y3D3E0fv8GIaV0Ei8Ydu4AVuTJW mEvuzDAJBgcqhkjOPQQBA0cAMEQCIB25iNcA7Y3D3E0fv8GIaV0Ei8Ydu4AVuTJW
C8tZvjhWAiBqAuBYm104bRLWaT2uSZexQJgvTPB6j6SdUi0SmR0acw== C8tZvjhWAiBqAuBYm104bRLWaT2uSZexQJgvTPB6j6SdUi0SmR0acw==
-----END CERTIFICATE----- -----END CERTIFICATE-----
` `;
export const mock_dsc_key_sha384_ecdsa = `-----BEGIN EC PRIVATE KEY----- export const mock_dsc_key_sha384_ecdsa = `-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAw/8AnnGTU8TWWt+SDVr2Gi3TEruQ5tkZ9PObCFtW1nQZaId/f/UFk MIGkAgEBBDAw/8AnnGTU8TWWt+SDVr2Gi3TEruQ5tkZ9PObCFtW1nQZaId/f/UFk
@@ -500,7 +500,7 @@ nJgnT7zm72qgBwYFK4EEACKhZANiAARBQCmC0UscKfL8KkVMtO69SU17NIrpLsw5
ibVLxHqcnKMm0FLy0gwU3DFqFF9gPD64EmyoxyE+mo+I3l5rEZPWMqVZOoxCRSww ibVLxHqcnKMm0FLy0gwU3DFqFF9gPD64EmyoxyE+mo+I3l5rEZPWMqVZOoxCRSww
f6GeHkgco/zGFxnEaklZL7g6gwyUNp8= f6GeHkgco/zGFxnEaklZL7g6gwyUNp8=
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----
` `;
export const mock_dsc_sha384_ecdsa = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha384_ecdsa = `-----BEGIN CERTIFICATE-----
MIICRDCCAcqgAwIBAgIUDWqj4BMk0L+D4RpvoSSyc6Lz3mswCgYIKoZIzj0EAwMw MIICRDCCAcqgAwIBAgIUDWqj4BMk0L+D4RpvoSSyc6Lz3mswCgYIKoZIzj0EAwMw
@@ -517,7 +517,7 @@ ADBlAjAu9tM+LZ8PB90F3Wd+mg//Eia6oTM9APo2+E9isiV/sgRwy3HFfAbYnH7c
xy29Ef4CMQCiGvLgkcYMSx3J1bWcq8nuxPBywf440ruiFf95wzm/erjDRFG3u7Dh xy29Ef4CMQCiGvLgkcYMSx3J1bWcq8nuxPBywf440ruiFf95wzm/erjDRFG3u7Dh
d+9Msdsovrc= d+9Msdsovrc=
-----END CERTIFICATE----- -----END CERTIFICATE-----
` `;
export const mock_dsc_key_sha256_brainpoolP256r1 = `-----BEGIN EC PRIVATE KEY----- export const mock_dsc_key_sha256_brainpoolP256r1 = `-----BEGIN EC PRIVATE KEY-----
MHgCAQEEICM/qGkSEYZJeejSAl3to/52G9Vw+GDKdvw2BA4Hq4TRoAsGCSskAwMC MHgCAQEEICM/qGkSEYZJeejSAl3to/52G9Vw+GDKdvw2BA4Hq4TRoAsGCSskAwMC
@@ -525,7 +525,7 @@ CAEBB6FEA0IABCga+ftPaAL6Bljws48myO1IDRDjaBkyFR3W/esrhP2pb3poTpqd
KDjKkI9hUU1t3cllGYBP4UzL9IUhe4J7I6s= KDjKkI9hUU1t3cllGYBP4UzL9IUhe4J7I6s=
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----
` `;
export const mock_dsc_sha256_brainpoolP256r1 = `-----BEGIN CERTIFICATE----- export const mock_dsc_sha256_brainpoolP256r1 = `-----BEGIN CERTIFICATE-----
MIICDzCCAbagAwIBAgIUcNlflnEgBabRuI8TtmhfuXeBDxAwCgYIKoZIzj0EAwIw MIICDzCCAbagAwIBAgIUcNlflnEgBabRuI8TtmhfuXeBDxAwCgYIKoZIzj0EAwIw
@@ -541,7 +541,7 @@ BgNVHQ4EFgQUQE/6d9aMviaMEi9k91hdsVguoekwHwYDVR0jBBgwFoAUXOj0kKh6
hlAwf+ljOVwK1ZhDh5lJLicCIEJdrWnH+dUOBL+NecPbLmcFVBCelST9iNCUXTKD hlAwf+ljOVwK1ZhDh5lJLicCIEJdrWnH+dUOBL+NecPbLmcFVBCelST9iNCUXTKD
CLpT CLpT
-----END CERTIFICATE----- -----END CERTIFICATE-----
` `;
export const mock_dsc_key_sha256_rsa_65537_3072 = `-----BEGIN PRIVATE KEY----- export const mock_dsc_key_sha256_rsa_65537_3072 = `-----BEGIN PRIVATE KEY-----
MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQCxoTQRUOf0mU86 MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQCxoTQRUOf0mU86
@@ -675,4 +675,4 @@ cIlCXtLAlhwxvkvq6fXlDHODihiBrcmRBxz08o+IXvjgBYlfHWP5iDS4RO0lzId4
JYSWvyeHGutMDlIMuw5KEE1kVxR2XXcZypc9dWHGaI6MrYwpmmvTB6oZg11FEZzm JYSWvyeHGutMDlIMuw5KEE1kVxR2XXcZypc9dWHGaI6MrYwpmmvTB6oZg11FEZzm
S8w23130L6pAB1EjCC8lUQubEkgDZ0bfy4UxpkOiqctzYdakvgo+zOwpORhN/Wxp S8w23130L6pAB1EjCC8lUQubEkgDZ0bfy4UxpkOiqctzYdakvgo+zOwpORhN/Wxp
Vnmv Vnmv
-----END CERTIFICATE-----`; -----END CERTIFICATE-----`;

View File

@@ -1,41 +1,59 @@
export const sampleDataHashes_small = [ export const sampleDataHashes_small = [
[
2,
[ [
2, -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128,
[-66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128, -8] -8,
], ],
[ ],
3, [3, [0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26, 87, 17, 89, 110, -57, 108, -6]],
[0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26, 87, 17, 89, 110, -57, 108, -6] [
], 14,
[ [76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59],
14, ],
[76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59] ] as [number, number[]][];
]
] as [number, number[]][]
export const sampleDataHashes_large = [ export const sampleDataHashes_large = [
[
2,
[ [
2, -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128,
[-66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128, -8, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38] -8, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38,
], ],
],
[
3,
[ [
3, 0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26, 87, 17, 89, 110, -57, 108, -6, 36,
[0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26, 87, 17, 89, 110, -57, 108, -6, 36, 21, 39, 87, 110, 102, -6, -43, -82, -125, -85, -82] 21, 39, 87, 110, 102, -6, -43, -82, -125, -85, -82,
], ],
],
[
11,
[ [
11, -120, -101, 87, -112, 111, 15, -104, 127, 85, 25, -102, 81, 20, 58, 51, 75, -63, 116, -22, 0,
[-120, -101, 87, -112, 111, 15, -104, 127, 85, 25, -102, 81, 20, 58, 51, 75, -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124] 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124,
], ],
],
[
12,
[ [
12, 41, -22, 106, 78, 31, 11, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -42,
[41, -22, 106, 78, 31, 11, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -42, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114] 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114,
], ],
],
[
13,
[ [
13, 91, -34, -46, -63, 62, -34, 104, 82, 36, 41, -118, -3, 70, 15, -108, -48, -100, 45, 105, -85,
[91, -34, -46, -63, 62, -34, 104, 82, 36, 41, -118, -3, 70, 15, -108, -48, -100, 45, 105, -85, -15, -61, -71, 43, -39, -94, -110, -55, -34, 89, -18, 38] -15, -61, -71, 43, -39, -94, -110, -55, -34, 89, -18, 38,
], ],
],
[
14,
[ [
14, 76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59,
[76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38] -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38,
] ],
] as [number, number[]][] ],
] as [number, number[]][];

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
import { countryCodes } from '../constants/constants'; import { countryCodes } from '../constants/constants';
import getCountryISO2 from "country-iso-3-to-2"; import getCountryISO2 from 'country-iso-3-to-2';
import { flag } from 'country-emoji'; import { flag } from 'country-emoji';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
try { try {
console.log('Generating country options...'); console.log('Generating country options...');
const countryOptions = Object.keys(countryCodes).map((countryCode, index) => ({ const countryOptions = Object.keys(countryCodes).map((countryCode, index) => ({
countryCode, countryCode,
countryName: countryCodes[countryCode as keyof typeof countryCodes], countryName: countryCodes[countryCode as keyof typeof countryCodes],
flagEmoji: flag(getCountryISO2(countryCode)), flagEmoji: flag(getCountryISO2(countryCode)),
index, index,
})); }));
const outputPath = path.join(__dirname, './countryOptions.json'); const outputPath = path.join(__dirname, './countryOptions.json');
fs.writeFileSync(outputPath, JSON.stringify(countryOptions, null, 2)); fs.writeFileSync(outputPath, JSON.stringify(countryOptions, null, 2));
console.log(`Generated country options at ${outputPath}`); console.log(`Generated country options at ${outputPath}`);
} catch (error) { } catch (error) {
console.error('Error generating country options:', error); console.error('Error generating country options:', error);
process.exit(1); process.exit(1);
} }

View File

@@ -1,9 +1,9 @@
import { DEFAULT_USER_ID_TYPE, WEBSOCKET_URL } from "../constants/constants"; import { DEFAULT_USER_ID_TYPE, WEBSOCKET_URL } from '../constants/constants';
import { UserIdType } from "./utils"; import { UserIdType } from './utils';
export type CircuitName = "prove" | "disclose"; export type CircuitName = 'prove' | 'disclose';
export type CircuitMode = "prove_onchain" | "register" | 'prove_offchain'; export type CircuitMode = 'prove_onchain' | 'register' | 'prove_offchain';
export type Mode = "prove_offchain" | "prove_onchain" | "register" | "vc_and_disclose"; export type Mode = 'prove_offchain' | 'prove_onchain' | 'register' | 'vc_and_disclose';
// OpenPassportAppType // OpenPassportAppType
export interface OpenPassportAppPartial { export interface OpenPassportAppPartial {
@@ -18,35 +18,33 @@ export interface OpenPassportAppPartial {
} }
export interface OpenPassportApp extends OpenPassportAppPartial { export interface OpenPassportApp extends OpenPassportAppPartial {
args: ArgumentsProveOffChain | ArgumentsProveOnChain | ArgumentsRegister | ArgumentsDisclose args: ArgumentsProveOffChain | ArgumentsProveOnChain | ArgumentsRegister | ArgumentsDisclose;
} }
export interface ArgumentsProveOffChain { export interface ArgumentsProveOffChain {
disclosureOptions: DisclosureOptions, disclosureOptions: DisclosureOptions;
} }
export interface ArgumentsProveOnChain { export interface ArgumentsProveOnChain {
disclosureOptions: DisclosureOptions, disclosureOptions: DisclosureOptions;
modalServerUrl: string, modalServerUrl: string;
merkleTreeUrl: string, merkleTreeUrl: string;
} }
export interface ArgumentsRegister { export interface ArgumentsRegister {
cscaMerkleTreeUrl: string, cscaMerkleTreeUrl: string;
commitmentMerkleTreeUrl: string, commitmentMerkleTreeUrl: string;
modalServerUrl: string, modalServerUrl: string;
} }
export interface ArgumentsDisclose { export interface ArgumentsDisclose {
disclosureOptions: DisclosureOptions, disclosureOptions: DisclosureOptions;
commitmentMerkleTreeUrl: string, commitmentMerkleTreeUrl: string;
} }
export interface DisclosureOptions { export interface DisclosureOptions {
minimumAge: { enabled: boolean; value: string } minimumAge: { enabled: boolean; value: string };
nationality: { enabled: boolean; value: string } nationality: { enabled: boolean; value: string };
excludedCountries: { enabled: boolean; value: string[] } excludedCountries: { enabled: boolean; value: string[] };
ofac: boolean ofac: boolean;
} }

View File

@@ -3,114 +3,109 @@ import jsrsasign from 'jsrsasign';
import * as asn1 from 'asn1.js'; import * as asn1 from 'asn1.js';
import fs from 'fs'; import fs from 'fs';
export const RSAPublicKey = asn1.define('RSAPublicKey', function () { export const RSAPublicKey = asn1.define('RSAPublicKey', function () {
this.seq().obj( this.seq().obj(this.key('n').int(), this.key('e').int());
this.key('n').int(),
this.key('e').int()
);
}); });
export function isRsaPublicKey(key) { export function isRsaPublicKey(key) {
return key.type === 'RSA' || key.type === 'RSA-PSS'; return key.type === 'RSA' || key.type === 'RSA-PSS';
} }
export function getPublicKey(certificate) { export function getPublicKey(certificate) {
const publicKeyInfo = certificate.getPublicKeyHex(); const publicKeyInfo = certificate.getPublicKeyHex();
try { try {
// Try to parse the public key as ASN.1 // Try to parse the public key as ASN.1
const publicKeyAsn1 = asn1.define('PublicKey', function () { const publicKeyAsn1 = asn1.define('PublicKey', function () {
this.seq().obj( this.seq().obj(
this.key('algorithm').seq().obj( this.key('algorithm')
this.key('algorithmId').objid(), .seq()
this.key('parameters').optional().any() .obj(this.key('algorithmId').objid(), this.key('parameters').optional().any()),
), this.key('publicKey').bitstr()
this.key('publicKey').bitstr() );
); });
});
const parsed = publicKeyAsn1.decode(Buffer.from(publicKeyInfo, 'hex'), 'der'); const parsed = publicKeyAsn1.decode(Buffer.from(publicKeyInfo, 'hex'), 'der');
const publicKeyBuffer = parsed.publicKey.data; const publicKeyBuffer = parsed.publicKey.data;
// Parse the RSA public key // Parse the RSA public key
const rsaPublicKey = RSAPublicKey.decode(publicKeyBuffer, 'der'); const rsaPublicKey = RSAPublicKey.decode(publicKeyBuffer, 'der');
return { return {
n: new jsrsasign.BigInteger(rsaPublicKey.n.toString('hex'), 16), n: new jsrsasign.BigInteger(rsaPublicKey.n.toString('hex'), 16),
e: new jsrsasign.BigInteger(rsaPublicKey.e.toString('hex'), 16), e: new jsrsasign.BigInteger(rsaPublicKey.e.toString('hex'), 16),
type: 'RSA' type: 'RSA',
}; };
} catch (e) { } catch (e) {
console.error("Error parsing public key:", e); console.error('Error parsing public key:', e);
} }
// If parsing fails, fall back to manual extraction // If parsing fails, fall back to manual extraction
const modulus = extractModulus(publicKeyInfo); const modulus = extractModulus(publicKeyInfo);
if (modulus) { if (modulus) {
return { n: new jsrsasign.BigInteger(modulus, 16), type: 'RSA' }; return { n: new jsrsasign.BigInteger(modulus, 16), type: 'RSA' };
} }
throw new Error("Unable to extract public key"); throw new Error('Unable to extract public key');
} }
function extractModulus(publicKeyInfo: string): string | null { function extractModulus(publicKeyInfo: string): string | null {
// RSA OID // RSA OID
const rsaOid = '2a864886f70d010101'; const rsaOid = '2a864886f70d010101';
// RSA-PSS OID // RSA-PSS OID
const rsaPssOid = '2a864886f70d01010a'; const rsaPssOid = '2a864886f70d01010a';
let offset = publicKeyInfo.indexOf(rsaOid); let offset = publicKeyInfo.indexOf(rsaOid);
if (offset === -1) { if (offset === -1) {
offset = publicKeyInfo.indexOf(rsaPssOid); offset = publicKeyInfo.indexOf(rsaPssOid);
} }
if (offset === -1) { if (offset === -1) {
return null; return null;
} }
// Skip OID and move to the bit string // Skip OID and move to the bit string
offset = publicKeyInfo.indexOf('03', offset); offset = publicKeyInfo.indexOf('03', offset);
if (offset === -1) { if (offset === -1) {
return null; return null;
} }
// Skip bit string tag and length // Skip bit string tag and length
offset += 4; offset += 4;
// Extract modulus // Extract modulus
const modulusStart = publicKeyInfo.indexOf('02', offset) + 2; const modulusStart = publicKeyInfo.indexOf('02', offset) + 2;
const modulusLength = parseInt(publicKeyInfo.substr(modulusStart, 2), 16) * 2; const modulusLength = parseInt(publicKeyInfo.substr(modulusStart, 2), 16) * 2;
const modulus = publicKeyInfo.substr(modulusStart + 2, modulusLength); const modulus = publicKeyInfo.substr(modulusStart + 2, modulusLength);
return modulus; return modulus;
} }
export function readCertificate(filePath: string): jsrsasign.X509 { export function readCertificate(filePath: string): jsrsasign.X509 {
const certPem = fs.readFileSync(filePath, 'utf8'); const certPem = fs.readFileSync(filePath, 'utf8');
const certificate = new jsrsasign.X509(); const certificate = new jsrsasign.X509();
certificate.readCertPEM(certPem); certificate.readCertPEM(certPem);
return certificate; return certificate;
} }
export function getTBSCertificate(certificate: jsrsasign.X509): Buffer { export function getTBSCertificate(certificate: jsrsasign.X509): Buffer {
// console.log("Certificate:", certificate); // console.log("Certificate:", certificate);
const certASN1 = certificate.getParam(); const certASN1 = certificate.getParam();
// console.log("certASN1:", certASN1); // console.log("certASN1:", certASN1);
if (!certASN1) { if (!certASN1) {
console.error("Failed to get certificate parameters"); console.error('Failed to get certificate parameters');
throw new Error("Invalid certificate structure"); throw new Error('Invalid certificate structure');
} }
// Extract the TBS part directly from the certificate's hex representation // Extract the TBS part directly from the certificate's hex representation
const certHex = certificate.hex; const certHex = certificate.hex;
const tbsStartIndex = certHex.indexOf('30') + 2; // Start after the first sequence tag const tbsStartIndex = certHex.indexOf('30') + 2; // Start after the first sequence tag
const tbsLength = parseInt(certHex.substr(tbsStartIndex, 2), 16) * 2 + 2; // Length in bytes * 2 for hex + 2 for length field const tbsLength = parseInt(certHex.substr(tbsStartIndex, 2), 16) * 2 + 2; // Length in bytes * 2 for hex + 2 for length field
const tbsHex = certHex.substr(tbsStartIndex - 2, tbsLength); // Include the sequence tag const tbsHex = certHex.substr(tbsStartIndex - 2, tbsLength); // Include the sequence tag
// console.log("TBS Hex:", tbsHex); // console.log("TBS Hex:", tbsHex);
return Buffer.from(tbsHex, 'hex'); return Buffer.from(tbsHex, 'hex');
} }

View File

@@ -1,127 +1,123 @@
export interface StandardCurve { export interface StandardCurve {
name: string; name: string;
p: string; p: string;
a: string; a: string;
b: string; b: string;
G: string; G: string;
n: string; n: string;
h: string; h: string;
} }
export const standardCurves: StandardCurve[] = [ export const standardCurves: StandardCurve[] = [
{ {
name: "secp256r1", name: 'secp256r1',
p: "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", p: 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF',
a: "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", a: 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC',
b: "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", b: '5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B',
G: "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", G: '046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5',
n: "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", n: 'FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551',
h: "01" h: '01',
}, },
{ {
name: "secp384r1", name: 'secp384r1',
p: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", p: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF',
a: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", a: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC',
b: "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", b: 'B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF',
G: "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", G: '04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F',
n: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", n: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973',
h: "01" h: '01',
}, },
{ {
name: "secp521r1", name: 'secp521r1',
p: "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", p: '01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
a: "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", a: '01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC',
b: "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", b: '0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00',
G: "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", G: '0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650',
n: "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", n: '01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409',
h: "01" h: '01',
} },
, {
{ name: 'brainpoolP256r1',
name: "brainpoolP256r1", p: 'A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377',
p: "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", a: '7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9',
a: "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", b: '26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6',
b: "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", G: '048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997',
G: "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", n: 'A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7',
n: "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", h: '01',
h: "01" },
}, {
{ name: 'brainpoolP384r1',
name: "brainpoolP384r1", p: '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53',
p: "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", a: '7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826',
a: "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", b: '04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11',
b: "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", G: '041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315',
G: "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", n: '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565',
n: "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", h: '01',
h: "01" },
}, {
{ name: 'brainpoolP512r1',
name: "brainpoolP512r1", p: 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3',
p: "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", a: '7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA',
a: "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", b: '3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723',
b: "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", G: '0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892',
G: "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", n: 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069',
n: "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", h: '01',
h: "01" },
}
]; ];
export function normalizeHex(hex: string): string { export function normalizeHex(hex: string): string {
return hex.toLowerCase().replace(/^0x/, '').replace(/^00/, ''); return hex.toLowerCase().replace(/^0x/, '').replace(/^00/, '');
} }
export function identifyCurve(params: any): string { export function identifyCurve(params: any): string {
const normalizedParams = { const normalizedParams = {
p: normalizeHex(params.p), p: normalizeHex(params.p),
a: normalizeHex(params.a), a: normalizeHex(params.a),
b: normalizeHex(params.b), b: normalizeHex(params.b),
G: normalizeHex(params.G), G: normalizeHex(params.G),
n: normalizeHex(params.n), n: normalizeHex(params.n),
h: normalizeHex(params.h) h: normalizeHex(params.h),
}; };
for (const curve of standardCurves) { for (const curve of standardCurves) {
if ( if (
normalizedParams.p === normalizeHex(curve.p) && normalizedParams.p === normalizeHex(curve.p) &&
normalizedParams.a === normalizeHex(curve.a) && normalizedParams.a === normalizeHex(curve.a) &&
normalizedParams.b === normalizeHex(curve.b) && normalizedParams.b === normalizeHex(curve.b) &&
normalizedParams.G === normalizeHex(curve.G) && normalizedParams.G === normalizeHex(curve.G) &&
normalizedParams.n === normalizeHex(curve.n) && normalizedParams.n === normalizeHex(curve.n) &&
normalizedParams.h === normalizeHex(curve.h) normalizedParams.h === normalizeHex(curve.h)
) { ) {
return curve.name; return curve.name;
}
} }
return "Unknown curve"; }
return 'Unknown curve';
} }
export function getNamedCurve(oid: string): string { export function getNamedCurve(oid: string): string {
const curves = { const curves = {
'1.2.840.10045.3.1.7': 'secp256r1', '1.2.840.10045.3.1.7': 'secp256r1',
'1.3.132.0.34': 'secp384r1', '1.3.132.0.34': 'secp384r1',
'1.3.132.0.35': 'secp521r1', '1.3.132.0.35': 'secp521r1',
// Add more curve OIDs as needed // Add more curve OIDs as needed
}; };
return curves[oid] || `Unknown (${oid})`; return curves[oid] || `Unknown (${oid})`;
} }
export function getECDSACurveBits(curveName: string): string { export function getECDSACurveBits(curveName: string): string {
const curveBits: { [key: string]: number } = { const curveBits: { [key: string]: number } = {
'secp256r1': 256, secp256r1: 256,
'secp384r1': 384, secp384r1: 384,
'secp521r1': 521, secp521r1: 521,
'brainpoolP256r1': 256, brainpoolP256r1: 256,
'brainpoolP384r1': 384, brainpoolP384r1: 384,
'brainpoolP512r1': 512, brainpoolP512r1: 512,
'secp256r1 (NIST P-256)': 256, 'secp256r1 (NIST P-256)': 256,
'secp384r1 (NIST P-384)': 384, 'secp384r1 (NIST P-384)': 384,
'secp521r1 (NIST P-521)': 521, 'secp521r1 (NIST P-521)': 521,
};
}; if (curveName in curveBits) {
if (curveName in curveBits) { return curveBits[curveName].toString();
return curveBits[curveName].toString(); }
} console.log('\x1b[31m%s\x1b[0m', `curve name ${curveName} not found in curveBits`);
console.log('\x1b[31m%s\x1b[0m', `curve name ${curveName} not found in curveBits`); return 'unknown';
return "unknown"; }
}

View File

@@ -1,36 +1,40 @@
import { StandardCurve } from "./curves"; import { StandardCurve } from './curves';
export interface CertificateData { export interface CertificateData {
id: string; id: string;
issuer: string; issuer: string;
validity: { validity: {
notBefore: string; notBefore: string;
notAfter: string; notAfter: string;
}; };
subjectKeyIdentifier: string; subjectKeyIdentifier: string;
signatureAlgorithm: string; signatureAlgorithm: string;
hashFunction: string; hashFunction: string;
publicKeyDetails: PublicKeyDetailsRSA | PublicKeyDetailsECDSA | PublicKeyDetailsRSAPSS | undefined; publicKeyDetails:
rawPem: string; | PublicKeyDetailsRSA
rawTxt: string; | PublicKeyDetailsECDSA
| PublicKeyDetailsRSAPSS
| undefined;
rawPem: string;
rawTxt: string;
} }
export interface PublicKeyDetailsRSA { export interface PublicKeyDetailsRSA {
modulus: string; modulus: string;
exponent: string; exponent: string;
bits: string; bits: string;
} }
export interface PublicKeyDetailsRSAPSS extends PublicKeyDetailsRSA { export interface PublicKeyDetailsRSAPSS extends PublicKeyDetailsRSA {
hashFunction: string; hashFunction: string;
mgf: string; mgf: string;
saltLength: string; saltLength: string;
} }
export interface PublicKeyDetailsECDSA { export interface PublicKeyDetailsECDSA {
curve: string; curve: string;
params: StandardCurve; params: StandardCurve;
bits: string; bits: string;
x: string; x: string;
y: string; y: string;
} }

View File

@@ -9,170 +9,269 @@ import { circuitNameFromMode } from '../../constants/constants';
import { Mode } from '../appType'; import { Mode } from '../appType';
if (typeof global.Buffer === 'undefined') { if (typeof global.Buffer === 'undefined') {
global.Buffer = require('buffer').Buffer; global.Buffer = require('buffer').Buffer;
} }
export function parseCertificate(pem: string) { export function parseCertificate(pem: string) {
const cert = getCertificateFromPem(pem); const cert = getCertificateFromPem(pem);
let { signatureAlgorithm, hashFunction } = getSignatureAlgorithmDetails(cert.signatureAlgorithm.algorithmId); let { signatureAlgorithm, hashFunction } = getSignatureAlgorithmDetails(
const subjectPublicKeyInfo = cert.subjectPublicKeyInfo; cert.signatureAlgorithm.algorithmId
const subjectKeyIdentifier = getSubjectKeyIdentifier(cert); );
const authorityKeyIdentifier = getAuthorityKeyIdentifier(cert); const subjectPublicKeyInfo = cert.subjectPublicKeyInfo;
let publicKeyDetails: any; const subjectKeyIdentifier = getSubjectKeyIdentifier(cert);
switch (signatureAlgorithm) { const authorityKeyIdentifier = getAuthorityKeyIdentifier(cert);
case 'rsa': let publicKeyDetails: any;
publicKeyDetails = parseRsaPublicKey(subjectPublicKeyInfo); switch (signatureAlgorithm) {
if (!publicKeyDetails) { case 'rsa':
console.log('\x1b[33mRSA public key not found, probably ECDSA certificate\x1b[0m'); publicKeyDetails = parseRsaPublicKey(subjectPublicKeyInfo);
} if (!publicKeyDetails) {
break; console.log('\x1b[33mRSA public key not found, probably ECDSA certificate\x1b[0m');
case 'rsapss': }
const rsaPssParams = cert.signatureAlgorithm.algorithmParams; break;
publicKeyDetails = parseRsaPssPublicKey(subjectPublicKeyInfo, rsaPssParams); case 'rsapss':
if (publicKeyDetails) { const rsaPssParams = cert.signatureAlgorithm.algorithmParams;
hashFunction = (publicKeyDetails as PublicKeyDetailsRSAPSS).hashFunction; publicKeyDetails = parseRsaPssPublicKey(subjectPublicKeyInfo, rsaPssParams);
} if (publicKeyDetails) {
if (!publicKeyDetails) { hashFunction = (publicKeyDetails as PublicKeyDetailsRSAPSS).hashFunction;
console.log('\x1b[33mRSA-PSS public key not found\x1b[0m'); }
} if (!publicKeyDetails) {
break; console.log('\x1b[33mRSA-PSS public key not found\x1b[0m');
case 'ecdsa': }
publicKeyDetails = parseECParameters(subjectPublicKeyInfo); break;
if (!publicKeyDetails) { case 'ecdsa':
console.log('\x1b[33mECDSA public key not found\x1b[0m'); publicKeyDetails = parseECParameters(subjectPublicKeyInfo);
} if (!publicKeyDetails) {
break; console.log('\x1b[33mECDSA public key not found\x1b[0m');
default: }
console.log('\x1b[33mUnknown signature algorithm: \x1b[0m', signatureAlgorithm); break;
} default:
const hashLen = getHashLen(hashFunction); console.log('\x1b[33mUnknown signature algorithm: \x1b[0m', signatureAlgorithm);
return { signatureAlgorithm, hashFunction, hashLen, subjectKeyIdentifier, authorityKeyIdentifier, ...publicKeyDetails }; }
const hashLen = getHashLen(hashFunction);
return {
signatureAlgorithm,
hashFunction,
hashLen,
subjectKeyIdentifier,
authorityKeyIdentifier,
...publicKeyDetails,
};
} }
export const getCircuitName = (circuitMode: Mode, signatureAlgorithm: string, hashFunction: string, domainParameter: string, keyLength: string) => { export const getCircuitName = (
const circuit = circuitNameFromMode[circuitMode]; circuitMode: Mode,
if (circuit == 'vc_and_disclose') { signatureAlgorithm: string,
return 'vc_and_disclose'; hashFunction: string,
} domainParameter: string,
if (circuit == 'dsc') { keyLength: string
return circuit + "_" + signatureAlgorithm + "_" + hashFunction + "_" + domainParameter + "_" + keyLength; ) => {
} const circuit = circuitNameFromMode[circuitMode];
return circuit + "_" + signatureAlgorithm + "_" + hashFunction + "_" + domainParameter + "_" + keyLength; if (circuit == 'vc_and_disclose') {
} return 'vc_and_disclose';
}
if (circuit == 'dsc') {
return (
circuit +
'_' +
signatureAlgorithm +
'_' +
hashFunction +
'_' +
domainParameter +
'_' +
keyLength
);
}
return (
circuit +
'_' +
signatureAlgorithm +
'_' +
hashFunction +
'_' +
domainParameter +
'_' +
keyLength
);
};
export function getSignatureAlgorithmDetails(oid: string): { signatureAlgorithm: string, hashFunction: string } { export function getSignatureAlgorithmDetails(oid: string): {
const details = { signatureAlgorithm: string;
'1.2.840.113549.1.1.5': { signatureAlgorithm: 'rsa', hashFunction: 'sha1', domainParameter: '65537', keyLength: '2048' }, hashFunction: string;
'1.2.840.113549.1.1.11': { signatureAlgorithm: 'rsa', hashFunction: 'sha256', domainParameter: '65537', keyLength: '2048' }, } {
'1.2.840.113549.1.1.12': { signatureAlgorithm: 'rsa', hashFunction: 'sha384', domainParameter: '65537', keyLength: '2048' }, const details = {
'1.2.840.113549.1.1.13': { signatureAlgorithm: 'rsa', hashFunction: 'sha512', domainParameter: '65537', keyLength: '2048' }, '1.2.840.113549.1.1.5': {
// rsapss signatureAlgorithm: 'rsa',
'1.2.840.113549.1.1.10': { signatureAlgorithm: 'rsapss', hashFunction: 'sha256', domainParameter: '65537', keyLength: '2048' }, // TODO: detect which hash function is used (not always sha256) hashFunction: 'sha1',
// ecdsa domainParameter: '65537',
'1.2.840.10045.4.1': { signatureAlgorithm: 'ecdsa', hashFunction: 'sha1', domainParameter: 'secp256r1', keyLength: '256' }, keyLength: '2048',
'1.2.840.10045.4.3.1': { signatureAlgorithm: 'ecdsa', hashFunction: 'sha224', domainParameter: 'secp256r1', keyLength: '256' }, },
'1.2.840.10045.4.3.2': { signatureAlgorithm: 'ecdsa', hashFunction: 'sha256', domainParameter: 'secp256r1', keyLength: '256' }, '1.2.840.113549.1.1.11': {
'1.2.840.10045.4.3.3': { signatureAlgorithm: 'ecdsa', hashFunction: 'sha384', domainParameter: 'secp384r1', keyLength: '384' }, signatureAlgorithm: 'rsa',
'1.2.840.10045.4.3.4': { signatureAlgorithm: 'ecdsa', hashFunction: 'sha512', domainParameter: 'secp521r1', keyLength: '521' }, hashFunction: 'sha256',
}; domainParameter: '65537',
return details[oid] || { signatureAlgorithm: `Unknown (${oid})`, hashFunction: 'Unknown' }; keyLength: '2048',
},
'1.2.840.113549.1.1.12': {
signatureAlgorithm: 'rsa',
hashFunction: 'sha384',
domainParameter: '65537',
keyLength: '2048',
},
'1.2.840.113549.1.1.13': {
signatureAlgorithm: 'rsa',
hashFunction: 'sha512',
domainParameter: '65537',
keyLength: '2048',
},
// rsapss
'1.2.840.113549.1.1.10': {
signatureAlgorithm: 'rsapss',
hashFunction: 'sha256',
domainParameter: '65537',
keyLength: '2048',
}, // TODO: detect which hash function is used (not always sha256)
// ecdsa
'1.2.840.10045.4.1': {
signatureAlgorithm: 'ecdsa',
hashFunction: 'sha1',
domainParameter: 'secp256r1',
keyLength: '256',
},
'1.2.840.10045.4.3.1': {
signatureAlgorithm: 'ecdsa',
hashFunction: 'sha224',
domainParameter: 'secp256r1',
keyLength: '256',
},
'1.2.840.10045.4.3.2': {
signatureAlgorithm: 'ecdsa',
hashFunction: 'sha256',
domainParameter: 'secp256r1',
keyLength: '256',
},
'1.2.840.10045.4.3.3': {
signatureAlgorithm: 'ecdsa',
hashFunction: 'sha384',
domainParameter: 'secp384r1',
keyLength: '384',
},
'1.2.840.10045.4.3.4': {
signatureAlgorithm: 'ecdsa',
hashFunction: 'sha512',
domainParameter: 'secp521r1',
keyLength: '521',
},
};
return details[oid] || { signatureAlgorithm: `Unknown (${oid})`, hashFunction: 'Unknown' };
} }
export function gethashFunctionName(oid: string): string { export function gethashFunctionName(oid: string): string {
const hashFunctions = { const hashFunctions = {
'1.3.14.3.2.26': 'sha1', '1.3.14.3.2.26': 'sha1',
'2.16.840.1.101.3.4.2.1': 'sha256', '2.16.840.1.101.3.4.2.1': 'sha256',
'2.16.840.1.101.3.4.2.2': 'sha384', '2.16.840.1.101.3.4.2.2': 'sha384',
'2.16.840.1.101.3.4.2.3': 'sha512', '2.16.840.1.101.3.4.2.3': 'sha512',
}; };
return hashFunctions[oid] || `Unknown (${oid})`; return hashFunctions[oid] || `Unknown (${oid})`;
} }
export function getCertificateFromPem(pemContent: string): Certificate { export function getCertificateFromPem(pemContent: string): Certificate {
const certBuffer = Buffer.from(pemContent.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''), 'base64'); const certBuffer = Buffer.from(
const asn1Data = asn1.fromBER(certBuffer); pemContent.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''),
return new Certificate({ schema: asn1Data.result }); 'base64'
);
const asn1Data = asn1.fromBER(certBuffer);
return new Certificate({ schema: asn1Data.result });
} }
export const getSubjectKeyIdentifier = (cert: Certificate): string => { export const getSubjectKeyIdentifier = (cert: Certificate): string => {
const subjectKeyIdentifier = cert.extensions.find( const subjectKeyIdentifier = cert.extensions.find(
(ext) => ext.extnID === '2.5.29.14' // OID for Subject Key Identifier (ext) => ext.extnID === '2.5.29.14' // OID for Subject Key Identifier
);
if (subjectKeyIdentifier) {
let skiValue = Buffer.from(subjectKeyIdentifier.extnValue.valueBlock.valueHexView).toString(
'hex'
); );
if (subjectKeyIdentifier) {
let skiValue = Buffer.from(subjectKeyIdentifier.extnValue.valueBlock.valueHexView).toString('hex');
skiValue = skiValue.replace(/^(?:3016)?(?:0414)?/, ''); skiValue = skiValue.replace(/^(?:3016)?(?:0414)?/, '');
return skiValue return skiValue;
} else { } else {
return null; return null;
} }
} };
export const getAuthorityKeyIdentifier = (cert: Certificate): string => { export const getAuthorityKeyIdentifier = (cert: Certificate): string => {
const authorityKeyIdentifier = cert.extensions.find( const authorityKeyIdentifier = cert.extensions.find((ext) => ext.extnID === '2.5.29.35');
(ext) => ext.extnID === '2.5.29.35' if (authorityKeyIdentifier) {
let akiValue = Buffer.from(authorityKeyIdentifier.extnValue.valueBlock.valueHexView).toString(
'hex'
); );
if (authorityKeyIdentifier) { akiValue = akiValue.replace(/^(?:3016)?(?:0414)?/, '');
let akiValue = Buffer.from(authorityKeyIdentifier.extnValue.valueBlock.valueHexView).toString('hex'); // cur off the first 2 bytes
akiValue = akiValue.replace(/^(?:3016)?(?:0414)?/, ''); akiValue = akiValue.slice(4);
// cur off the first 2 bytes return akiValue;
akiValue = akiValue.slice(4); }
return akiValue return null;
} };
return null;
}
export function getIssuerCountryCode(cert: Certificate): string { export function getIssuerCountryCode(cert: Certificate): string {
const issuerRDN = cert.issuer.typesAndValues; const issuerRDN = cert.issuer.typesAndValues;
let issuerCountryCode = ''; let issuerCountryCode = '';
for (const rdn of issuerRDN) { for (const rdn of issuerRDN) {
if (rdn.type === '2.5.4.6') { // OID for Country Name if (rdn.type === '2.5.4.6') {
issuerCountryCode = rdn.value.valueBlock.value; // OID for Country Name
break; issuerCountryCode = rdn.value.valueBlock.value;
} break;
} }
return issuerCountryCode.toUpperCase(); }
return issuerCountryCode.toUpperCase();
} }
export const parseDSC = (pemContent: string) => { export const parseDSC = (pemContent: string) => {
const certBuffer = Buffer.from(pemContent.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''), 'base64'); const certBuffer = Buffer.from(
const asn1Data = asn1.fromBER(certBuffer); pemContent.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''),
const cert = new Certificate({ schema: asn1Data.result }); 'base64'
const signatureAlgorithmOid = cert.signatureAlgorithm.algorithmId; );
const { signatureAlgorithm, hashFunction } = getSignatureAlgorithmDetails(signatureAlgorithmOid); const asn1Data = asn1.fromBER(certBuffer);
const hashLen = getHashLen(hashFunction); const cert = new Certificate({ schema: asn1Data.result });
const signatureAlgorithmOid = cert.signatureAlgorithm.algorithmId;
const { signatureAlgorithm, hashFunction } = getSignatureAlgorithmDetails(signatureAlgorithmOid);
const hashLen = getHashLen(hashFunction);
let publicKeyDetails; let publicKeyDetails;
if (signatureAlgorithm === 'ecdsa') { if (signatureAlgorithm === 'ecdsa') {
const subjectPublicKeyInfo = cert.subjectPublicKeyInfo; const subjectPublicKeyInfo = cert.subjectPublicKeyInfo;
const algorithmParams = subjectPublicKeyInfo.algorithm.algorithmParams; const algorithmParams = subjectPublicKeyInfo.algorithm.algorithmParams;
const curveOid = asn1.fromBER(algorithmParams.valueBeforeDecode).result.valueBlock.toString(); const curveOid = asn1.fromBER(algorithmParams.valueBeforeDecode).result.valueBlock.toString();
const curve = getNamedCurve(curveOid); const curve = getNamedCurve(curveOid);
const publicKeyBuffer = subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHexView; const publicKeyBuffer = subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHexView;
const curveForElliptic = curve === 'secp256r1' ? 'p256' : 'p384'; const curveForElliptic = curve === 'secp256r1' ? 'p256' : 'p384';
const ec = new elliptic.ec(curveForElliptic); const ec = new elliptic.ec(curveForElliptic);
const key = ec.keyFromPublic(publicKeyBuffer); const key = ec.keyFromPublic(publicKeyBuffer);
const x = key.getPublic().getX().toString('hex'); const x = key.getPublic().getX().toString('hex');
const y = key.getPublic().getY().toString('hex'); const y = key.getPublic().getY().toString('hex');
const fieldSizeMap: { [key: string]: number } = { const fieldSizeMap: { [key: string]: number } = {
'secp256r1': 256, secp256r1: 256,
'secp384r1': 384, secp384r1: 384,
}; };
const bits = fieldSizeMap[curve] const bits = fieldSizeMap[curve];
publicKeyDetails = { curve, x, y, bits }; publicKeyDetails = { curve, x, y, bits };
} else { } else {
const publicKey = cert.subjectPublicKeyInfo.subjectPublicKey; const publicKey = cert.subjectPublicKeyInfo.subjectPublicKey;
const asn1PublicKey = asn1.fromBER(publicKey.valueBlock.valueHexView); const asn1PublicKey = asn1.fromBER(publicKey.valueBlock.valueHexView);
const rsaPublicKey = asn1PublicKey.result.valueBlock; const rsaPublicKey = asn1PublicKey.result.valueBlock;
const modulus = Buffer.from((rsaPublicKey as any).value[0].valueBlock.valueHexView).toString('hex'); const modulus = Buffer.from((rsaPublicKey as any).value[0].valueBlock.valueHexView).toString(
const exponent = Buffer.from((rsaPublicKey as any).value[1].valueBlock.valueHexView).toString('hex'); 'hex'
const bits = Buffer.from(modulus, 'hex').length * 8; );
publicKeyDetails = { modulus, exponent, bits }; const exponent = Buffer.from((rsaPublicKey as any).value[1].valueBlock.valueHexView).toString(
} 'hex'
return { signatureAlgorithm, hashFunction, hashLen, ...publicKeyDetails }; );
} const bits = Buffer.from(modulus, 'hex').length * 8;
publicKeyDetails = { modulus, exponent, bits };
}
return { signatureAlgorithm, hashFunction, hashLen, ...publicKeyDetails };
};

View File

@@ -1,230 +1,252 @@
import { fromBER, BitString } from 'asn1js'; import { fromBER, BitString } from 'asn1js';
import * as asn1 from 'asn1js'; import * as asn1 from 'asn1js';
import * as forge from 'node-forge'; import * as forge from 'node-forge';
import { PublicKeyDetailsECDSA, PublicKeyDetailsRSA, PublicKeyDetailsRSAPSS } from './dataStructure'; import {
PublicKeyDetailsECDSA,
PublicKeyDetailsRSA,
PublicKeyDetailsRSAPSS,
} from './dataStructure';
import { identifyCurve, StandardCurve, getNamedCurve, getECDSACurveBits } from './curves'; import { identifyCurve, StandardCurve, getNamedCurve, getECDSACurveBits } from './curves';
import { gethashFunctionName } from './handleCertificate'; import { gethashFunctionName } from './handleCertificate';
import elliptic from 'elliptic'; import elliptic from 'elliptic';
export function parseRsaPublicKey(subjectPublicKeyInfo: any): PublicKeyDetailsRSA { export function parseRsaPublicKey(subjectPublicKeyInfo: any): PublicKeyDetailsRSA {
const publicKey = subjectPublicKeyInfo.subjectPublicKey; const publicKey = subjectPublicKeyInfo.subjectPublicKey;
const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView); const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView);
const rsaPublicKey = asn1PublicKey.result.valueBlock; const rsaPublicKey = asn1PublicKey.result.valueBlock;
if (rsaPublicKey && (rsaPublicKey as any).value && (rsaPublicKey as any).value[0] && (rsaPublicKey as any).value[1]) { if (
const modulusAsn1 = (rsaPublicKey as any).value[0]; rsaPublicKey &&
const exponentAsn1 = (rsaPublicKey as any).value[1]; (rsaPublicKey as any).value &&
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex'); (rsaPublicKey as any).value[0] &&
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex'); (rsaPublicKey as any).value[1]
) {
const modulusAsn1 = (rsaPublicKey as any).value[0];
const exponentAsn1 = (rsaPublicKey as any).value[1];
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex');
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex');
const publicKeyForge = forge.pki.rsa.setPublicKey( const publicKeyForge = forge.pki.rsa.setPublicKey(
new forge.jsbn.BigInteger(modulusHex, 16), new forge.jsbn.BigInteger(modulusHex, 16),
new forge.jsbn.BigInteger(exponentHex, 16) new forge.jsbn.BigInteger(exponentHex, 16)
); );
const publicKeyDetailsRSA: PublicKeyDetailsRSA = { const publicKeyDetailsRSA: PublicKeyDetailsRSA = {
modulus: publicKeyForge.n.toString(16), modulus: publicKeyForge.n.toString(16),
exponent: publicKeyForge.e.toString(10), exponent: publicKeyForge.e.toString(10),
bits: publicKeyForge.n.bitLength().toString() bits: publicKeyForge.n.bitLength().toString(),
}; };
return publicKeyDetailsRSA; return publicKeyDetailsRSA;
} } else {
else { return null;
return null; }
}
} }
export function parseECParameters(publicKeyInfo: any): PublicKeyDetailsECDSA { export function parseECParameters(publicKeyInfo: any): PublicKeyDetailsECDSA {
try { try {
const algorithmParams = publicKeyInfo.algorithm.algorithmParams; const algorithmParams = publicKeyInfo.algorithm.algorithmParams;
if (!algorithmParams) { if (!algorithmParams) {
console.error('\x1b[31mNo algorithm params found\x1b[0m'); console.error('\x1b[31mNo algorithm params found\x1b[0m');
return null; return null;
}
// get x and y;
const curveOid = asn1.fromBER(algorithmParams.valueBeforeDecode).result.valueBlock.toString();
const curve = getNamedCurve(curveOid);
const publicKeyBuffer = publicKeyInfo.subjectPublicKey.valueBlock.valueHexView;
const curveForElliptic = curve === 'secp256r1' ? 'p256' : 'p384';
const ec = new elliptic.ec(curveForElliptic);
const key = ec.keyFromPublic(publicKeyBuffer);
const x = key.getPublic().getX().toString('hex');
const y = key.getPublic().getY().toString('hex');
const fieldSizeMap: { [key: string]: number } = {
'secp256r1': 256,
'secp384r1': 384,
};
const bits = fieldSizeMap[curve]
const params = asn1.fromBER(algorithmParams.valueBeforeDecodeView).result;
const valueBlock: any = params.valueBlock;
let curveParams: StandardCurve = {} as StandardCurve;
// if (valueBlock.value && valueBlock.value.length >= 6) {
// // Field ID (index 1)
// const curveParams = {} as StandardCurve;
// const fieldId = valueBlock.value[1];
// if (fieldId && fieldId.valueBlock && fieldId.valueBlock.value) {
// const fieldType = fieldId.valueBlock.value[0];
// const prime = fieldId.valueBlock.value[1];
// //curveParams.fieldType = fieldType.valueBlock.toString();
// curveParams.p = Buffer.from(prime.valueBlock.valueHexView).toString('hex');
// }
// // Curve Coefficients (index 2)
// const curveCoefficients = valueBlock.value[2];
// if (curveCoefficients && curveCoefficients.valueBlock && curveCoefficients.valueBlock.value) {
// const a = curveCoefficients.valueBlock.value[0];
// const b = curveCoefficients.valueBlock.value[1];
// curveParams.a = Buffer.from(a.valueBlock.valueHexView).toString('hex');
// curveParams.b = Buffer.from(b.valueBlock.valueHexView).toString('hex');
// }
// // Base Point G (index 3)
// const basePoint = valueBlock.value[3];
// if (basePoint && basePoint.valueBlock) {
// curveParams.G = Buffer.from(basePoint.valueBlock.valueHexView).toString('hex');
// }
// // Order n (index 4)
// const order = valueBlock.value[4];
// if (order && order.valueBlock) {
// curveParams.n = Buffer.from(order.valueBlock.valueHexView).toString('hex');
// }
// // Cofactor h (index 5)
// const cofactor = valueBlock.value[5];
// if (cofactor && cofactor.valueBlock) {
// curveParams.h = Buffer.from(cofactor.valueBlock.valueHexView).toString('hex');
// }
// if (curveParams.p && curveParams.a && curveParams.b && curveParams.G && curveParams.n && curveParams.h) {
// const identifiedCurve = identifyCurve(curveParams);
// }
// } else {
// if (valueBlock.value) {
// if (algorithmParams.idBlock.tagNumber === 6) {
// console.log('\x1b[33malgorithmParams.idBlock.tagNumber === 6, looking for algorithmParams.valueBlock\x1b[0m');
// const curveOid = algorithmParams.valueBlock.toString();
// const curveName = getNamedCurve(curveOid);
// // console.error('\x1b[33mCurve OID:', curveName, '\x1b[0m');
// return { curve: curveName, params: {} as StandardCurve, bits: getECDSACurveBits(curveName) };
// }
// else {
// console.log('\x1b[31malgorithmParams.idBlock.tagNumber !== 6\x1b[0m');
// }
// }
// else {
// console.log('\x1b[31mvalue block is not defined\x1b[0m');
// }
// }
const publicKeyDetailsECDSA: PublicKeyDetailsECDSA = {
curve: curve,
params: curveParams,
bits: bits.toString(),
x: x,
y: y
};
return publicKeyDetailsECDSA;
} catch (error) {
console.error('Error parsing EC parameters:', error);
} }
// get x and y;
const curveOid = asn1.fromBER(algorithmParams.valueBeforeDecode).result.valueBlock.toString();
const curve = getNamedCurve(curveOid);
const publicKeyBuffer = publicKeyInfo.subjectPublicKey.valueBlock.valueHexView;
const curveForElliptic = curve === 'secp256r1' ? 'p256' : 'p384';
const ec = new elliptic.ec(curveForElliptic);
const key = ec.keyFromPublic(publicKeyBuffer);
const x = key.getPublic().getX().toString('hex');
const y = key.getPublic().getY().toString('hex');
const fieldSizeMap: { [key: string]: number } = {
secp256r1: 256,
secp384r1: 384,
};
const bits = fieldSizeMap[curve];
const params = asn1.fromBER(algorithmParams.valueBeforeDecodeView).result;
const valueBlock: any = params.valueBlock;
let curveParams: StandardCurve = {} as StandardCurve;
// if (valueBlock.value && valueBlock.value.length >= 6) {
// // Field ID (index 1)
// const curveParams = {} as StandardCurve;
// const fieldId = valueBlock.value[1];
// if (fieldId && fieldId.valueBlock && fieldId.valueBlock.value) {
// const fieldType = fieldId.valueBlock.value[0];
// const prime = fieldId.valueBlock.value[1];
// //curveParams.fieldType = fieldType.valueBlock.toString();
// curveParams.p = Buffer.from(prime.valueBlock.valueHexView).toString('hex');
// }
// // Curve Coefficients (index 2)
// const curveCoefficients = valueBlock.value[2];
// if (curveCoefficients && curveCoefficients.valueBlock && curveCoefficients.valueBlock.value) {
// const a = curveCoefficients.valueBlock.value[0];
// const b = curveCoefficients.valueBlock.value[1];
// curveParams.a = Buffer.from(a.valueBlock.valueHexView).toString('hex');
// curveParams.b = Buffer.from(b.valueBlock.valueHexView).toString('hex');
// }
// // Base Point G (index 3)
// const basePoint = valueBlock.value[3];
// if (basePoint && basePoint.valueBlock) {
// curveParams.G = Buffer.from(basePoint.valueBlock.valueHexView).toString('hex');
// }
// // Order n (index 4)
// const order = valueBlock.value[4];
// if (order && order.valueBlock) {
// curveParams.n = Buffer.from(order.valueBlock.valueHexView).toString('hex');
// }
// // Cofactor h (index 5)
// const cofactor = valueBlock.value[5];
// if (cofactor && cofactor.valueBlock) {
// curveParams.h = Buffer.from(cofactor.valueBlock.valueHexView).toString('hex');
// }
// if (curveParams.p && curveParams.a && curveParams.b && curveParams.G && curveParams.n && curveParams.h) {
// const identifiedCurve = identifyCurve(curveParams);
// }
// } else {
// if (valueBlock.value) {
// if (algorithmParams.idBlock.tagNumber === 6) {
// console.log('\x1b[33malgorithmParams.idBlock.tagNumber === 6, looking for algorithmParams.valueBlock\x1b[0m');
// const curveOid = algorithmParams.valueBlock.toString();
// const curveName = getNamedCurve(curveOid);
// // console.error('\x1b[33mCurve OID:', curveName, '\x1b[0m');
// return { curve: curveName, params: {} as StandardCurve, bits: getECDSACurveBits(curveName) };
// }
// else {
// console.log('\x1b[31malgorithmParams.idBlock.tagNumber !== 6\x1b[0m');
// }
// }
// else {
// console.log('\x1b[31mvalue block is not defined\x1b[0m');
// }
// }
const publicKeyDetailsECDSA: PublicKeyDetailsECDSA = {
curve: curve,
params: curveParams,
bits: bits.toString(),
x: x,
y: y,
};
return publicKeyDetailsECDSA;
} catch (error) {
console.error('Error parsing EC parameters:', error);
}
} }
export function parseRsaPssParams(params: any): { hashFunction: string, mgf: string, saltLength: string } { export function parseRsaPssParams(params: any): {
try { hashFunction: string;
const algorithmParams = asn1.fromBER(params.valueBeforeDecodeView); mgf: string;
const sequence = algorithmParams.result; saltLength: string;
} {
try {
const algorithmParams = asn1.fromBER(params.valueBeforeDecodeView);
const sequence = algorithmParams.result;
let hashFunction = 'Unknown';
let mgf = 'Unknown';
let saltLength = "Unknown";
// Parse hash algorithm
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[0]) {
const hashFunctionSequence = (sequence.valueBlock as any).value[0].valueBlock.value[0];
const hashFunctionOid = hashFunctionSequence.valueBlock.value[0].valueBlock.toString();
hashFunction = gethashFunctionName(hashFunctionOid);
}
// Parse MGF
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[1]) {
const mgfSequence = (sequence.valueBlock as any).value[1].valueBlock.value[0];
const mgfOid = mgfSequence.valueBlock.value[0].valueBlock.toString();
mgf = mgfOid === '1.2.840.113549.1.1.8' ? 'MGF1' : `Unknown (${mgfOid})`;
}
// console.log((sequence.valueBlock as any).value[0].valueBlock);
// console.log((sequence.valueBlock as any).value[1].valueBlock);
// console.log((sequence.valueBlock as any).value[2].valueBlock);
// Parse salt length
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[2]) {
const saltLengthContainer = (sequence.valueBlock as any).value[2];
if (saltLengthContainer.valueBlock && saltLengthContainer.valueBlock.value) {
const rawSaltLength = saltLengthContainer.valueBlock.value[0];
if (typeof rawSaltLength === 'number') {
saltLength = rawSaltLength.toString();
} else if (rawSaltLength && rawSaltLength.valueBlock && rawSaltLength.valueBlock.valueHexView) {
const saltLengthValue = rawSaltLength.valueBlock.valueHexView[0];
saltLength = saltLengthValue.toString();
} else {
console.error('\x1b[31mUnable to parse salt length\x1b[0m');
}
} else {
console.log("\x1b[31mSalt length not found\x1b[0m");
}
}
return { hashFunction, mgf, saltLength };
} catch (error) {
console.error('Error parsing RSA-PSS parameters:', error);
return { hashFunction: 'Unknown', mgf: 'Unknown', saltLength: "Unknown" };
}
}
export function parseRsaPssPublicKey(subjectPublicKeyInfo: any, rsaPssParams: any): PublicKeyDetailsRSAPSS {
let hashFunction = 'Unknown'; let hashFunction = 'Unknown';
let mgf = 'Unknown'; let mgf = 'Unknown';
let saltLength = "Unknown"; let saltLength = 'Unknown';
if (rsaPssParams) { // Parse hash algorithm
const parsedParams = parseRsaPssParams(rsaPssParams); if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[0]) {
hashFunction = parsedParams.hashFunction; const hashFunctionSequence = (sequence.valueBlock as any).value[0].valueBlock.value[0];
mgf = parsedParams.mgf; const hashFunctionOid = hashFunctionSequence.valueBlock.value[0].valueBlock.toString();
saltLength = parsedParams.saltLength; hashFunction = gethashFunctionName(hashFunctionOid);
} else {
console.log('\x1b[31mRSA-PSS parameters not found\x1b[0m');
} }
// Add PublicKeyDetails for RSA-PSS // Parse MGF
const publicKey = subjectPublicKeyInfo.subjectPublicKey; if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[1]) {
const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView); const mgfSequence = (sequence.valueBlock as any).value[1].valueBlock.value[0];
const rsaPublicKey = asn1PublicKey.result.valueBlock; const mgfOid = mgfSequence.valueBlock.value[0].valueBlock.toString();
mgf = mgfOid === '1.2.840.113549.1.1.8' ? 'MGF1' : `Unknown (${mgfOid})`;
if (rsaPublicKey && (rsaPublicKey as any).value && (rsaPublicKey as any).value[0] && (rsaPublicKey as any).value[1]) {
const modulusAsn1 = (rsaPublicKey as any).value[0];
const exponentAsn1 = (rsaPublicKey as any).value[1];
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex');
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex');
const publicKeyForge = forge.pki.rsa.setPublicKey(
new forge.jsbn.BigInteger(modulusHex, 16),
new forge.jsbn.BigInteger(exponentHex, 16)
);
const PublicKeyDetailsRSAPSS: PublicKeyDetailsRSAPSS = {
modulus: publicKeyForge.n.toString(16),
exponent: publicKeyForge.e.toString(10),
bits: publicKeyForge.n.bitLength().toString(),
hashFunction,
mgf,
saltLength
};
return PublicKeyDetailsRSAPSS;
} }
else { // console.log((sequence.valueBlock as any).value[0].valueBlock);
return null; // console.log((sequence.valueBlock as any).value[1].valueBlock);
// console.log((sequence.valueBlock as any).value[2].valueBlock);
// Parse salt length
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[2]) {
const saltLengthContainer = (sequence.valueBlock as any).value[2];
if (saltLengthContainer.valueBlock && saltLengthContainer.valueBlock.value) {
const rawSaltLength = saltLengthContainer.valueBlock.value[0];
if (typeof rawSaltLength === 'number') {
saltLength = rawSaltLength.toString();
} else if (
rawSaltLength &&
rawSaltLength.valueBlock &&
rawSaltLength.valueBlock.valueHexView
) {
const saltLengthValue = rawSaltLength.valueBlock.valueHexView[0];
saltLength = saltLengthValue.toString();
} else {
console.error('\x1b[31mUnable to parse salt length\x1b[0m');
}
} else {
console.log('\x1b[31mSalt length not found\x1b[0m');
}
} }
return { hashFunction, mgf, saltLength };
} catch (error) {
console.error('Error parsing RSA-PSS parameters:', error);
return { hashFunction: 'Unknown', mgf: 'Unknown', saltLength: 'Unknown' };
}
}
export function parseRsaPssPublicKey(
subjectPublicKeyInfo: any,
rsaPssParams: any
): PublicKeyDetailsRSAPSS {
let hashFunction = 'Unknown';
let mgf = 'Unknown';
let saltLength = 'Unknown';
if (rsaPssParams) {
const parsedParams = parseRsaPssParams(rsaPssParams);
hashFunction = parsedParams.hashFunction;
mgf = parsedParams.mgf;
saltLength = parsedParams.saltLength;
} else {
console.log('\x1b[31mRSA-PSS parameters not found\x1b[0m');
}
// Add PublicKeyDetails for RSA-PSS
const publicKey = subjectPublicKeyInfo.subjectPublicKey;
const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView);
const rsaPublicKey = asn1PublicKey.result.valueBlock;
if (
rsaPublicKey &&
(rsaPublicKey as any).value &&
(rsaPublicKey as any).value[0] &&
(rsaPublicKey as any).value[1]
) {
const modulusAsn1 = (rsaPublicKey as any).value[0];
const exponentAsn1 = (rsaPublicKey as any).value[1];
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex');
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex');
const publicKeyForge = forge.pki.rsa.setPublicKey(
new forge.jsbn.BigInteger(modulusHex, 16),
new forge.jsbn.BigInteger(exponentHex, 16)
);
const PublicKeyDetailsRSAPSS: PublicKeyDetailsRSAPSS = {
modulus: publicKeyForge.n.toString(16),
exponent: publicKeyForge.e.toString(10),
bits: publicKeyForge.n.bitLength().toString(),
hashFunction,
mgf,
saltLength,
};
return PublicKeyDetailsRSAPSS;
} else {
return null;
}
} }

View File

@@ -1,215 +1,234 @@
import { shaPad } from "./shaPad"; import { shaPad } from './shaPad';
import * as forge from "node-forge"; import * as forge from 'node-forge';
import { bytesToBigDecimal, extractRSFromSignature, getNAndK, getNAndKCSCA, hexToDecimal, splitToWords } from "./utils"; import {
import { CSCA_TREE_DEPTH, MODAL_SERVER_ADDRESS } from "../constants/constants"; bytesToBigDecimal,
import { poseidon2 } from "poseidon-lite"; extractRSFromSignature,
import { IMT } from "@openpassport/zk-kit-imt"; getNAndK,
import serialized_csca_tree from "../../pubkeys/serialized_csca_tree.json" getNAndKCSCA,
import axios from "axios"; hexToDecimal,
import { parseCertificate } from "./certificates/handleCertificate"; splitToWords,
import { getLeafCSCA } from "./pubkeyTree"; } from './utils';
import { SKI_PEM, SKI_PEM_DEV } from "../constants/skiPem"; import { CSCA_TREE_DEPTH, MODAL_SERVER_ADDRESS } from '../constants/constants';
import { poseidon2 } from 'poseidon-lite';
import { IMT } from '@openpassport/zk-kit-imt';
import serialized_csca_tree from '../../pubkeys/serialized_csca_tree.json';
import axios from 'axios';
import { parseCertificate } from './certificates/handleCertificate';
import { getLeafCSCA } from './pubkeyTree';
import { SKI_PEM, SKI_PEM_DEV } from '../constants/skiPem';
export function findStartIndex(modulus: string, messagePadded: Uint8Array): number { export function findStartIndex(modulus: string, messagePadded: Uint8Array): number {
console.log('messagePadded', messagePadded); console.log('messagePadded', messagePadded);
const modulusNumArray = []; const modulusNumArray = [];
for (let i = 0; i < modulus.length; i += 2) { for (let i = 0; i < modulus.length; i += 2) {
const hexPair = modulus.slice(i, i + 2); const hexPair = modulus.slice(i, i + 2);
const number = parseInt(hexPair, 16); const number = parseInt(hexPair, 16);
modulusNumArray.push(number); modulusNumArray.push(number);
} }
console.log('modulusNumArray', modulusNumArray); console.log('modulusNumArray', modulusNumArray);
const messagePaddedNumber = []; const messagePaddedNumber = [];
for (let i = 0; i < messagePadded.length; i += 1) { for (let i = 0; i < messagePadded.length; i += 1) {
const number = Number(messagePadded[i]); const number = Number(messagePadded[i]);
messagePaddedNumber.push(number); messagePaddedNumber.push(number);
} }
let startIndex = -1; let startIndex = -1;
for (let i = 0; i <= messagePaddedNumber.length; i++) { for (let i = 0; i <= messagePaddedNumber.length; i++) {
if (modulusNumArray[0] === messagePaddedNumber[i]) { if (modulusNumArray[0] === messagePaddedNumber[i]) {
for (let j = 0; j < modulusNumArray.length; j++) { for (let j = 0; j < modulusNumArray.length; j++) {
if (modulusNumArray[j] !== messagePaddedNumber[i + j]) { if (modulusNumArray[j] !== messagePaddedNumber[i + j]) {
break; break;
} } else if (j === modulusNumArray.length - 1) {
else if (j === modulusNumArray.length - 1) { startIndex = i;
startIndex = i;
}
}
break;
} }
}
break;
} }
if (startIndex === -1) { }
throw new Error('DSC Pubkey not found in CSCA certificate'); if (startIndex === -1) {
} throw new Error('DSC Pubkey not found in CSCA certificate');
return startIndex; }
return startIndex;
} }
export function generateCircuitInputsDSC(
dscSecret: string,
dscCertificate: any,
max_cert_bytes: number,
devMode: boolean = false
) {
const dscCert = forge.pki.certificateFromPem(dscCertificate);
const dscTbs = dscCert.tbsCertificate;
const dscTbsCertDer = forge.asn1.toDer(dscTbs).getBytes();
const dscTbsCertBytes = derToBytes(dscTbsCertDer);
const dscTbsCertUint8Array = Uint8Array.from(
dscTbsCertBytes.map((byte) => parseInt(byte.toString(16), 16))
);
export function generateCircuitInputsDSC(dscSecret: string, dscCertificate: any, max_cert_bytes: number, devMode: boolean = false) { const {
signatureAlgorithm,
hashFunction,
publicKeyDetails,
x,
y,
modulus,
curve,
exponent,
bits,
subjectKeyIdentifier,
authorityKeyIdentifier,
} = parseCertificate(dscCertificate);
let dsc_message_padded;
let dsc_messagePaddedLen;
[dsc_message_padded, dsc_messagePaddedLen] = shaPad(dscTbsCertUint8Array, max_cert_bytes);
const dscCert = forge.pki.certificateFromPem(dscCertificate); const { n, k } = getNAndK(signatureAlgorithm);
const dscTbs = dscCert.tbsCertificate; // Extract the signature from the DSC certificate
const dscTbsCertDer = forge.asn1.toDer(dscTbs).getBytes(); const dscSignature = dscCert.signature;
const dscTbsCertBytes = derToBytes(dscTbsCertDer); const encryptedDigest = Array.from(forge.util.createBuffer(dscSignature).getBytes(), (char) =>
const dscTbsCertUint8Array = Uint8Array.from(dscTbsCertBytes.map(byte => parseInt(byte.toString(16), 16))); char.charCodeAt(0)
);
const { signatureAlgorithm, hashFunction, publicKeyDetails, x, y, modulus, curve, exponent, bits, subjectKeyIdentifier, authorityKeyIdentifier } = parseCertificate(dscCertificate); let pubKey, signature;
let dsc_message_padded;
let dsc_messagePaddedLen;
[dsc_message_padded, dsc_messagePaddedLen] = shaPad(dscTbsCertUint8Array, max_cert_bytes);
const { n, k } = getNAndK(signatureAlgorithm); const startIndex = findStartIndex(modulus, dsc_message_padded);
// Extract the signature from the DSC certificate const startIndex_formatted = startIndex.toString();
const dscSignature = dscCert.signature; const dsc_message_padded_formatted = Array.from(dsc_message_padded).map((x) => x.toString());
const encryptedDigest = Array.from(forge.util.createBuffer(dscSignature).getBytes(), char => char.charCodeAt(0)); const dsc_messagePaddedLen_formatted = BigInt(dsc_messagePaddedLen).toString();
let pubKey, signature; const cscaPem = getCSCAFromSKI(authorityKeyIdentifier, devMode);
console.log('cscaPem', cscaPem);
const startIndex = findStartIndex(modulus, dsc_message_padded); const {
const startIndex_formatted = startIndex.toString(); x: csca_x,
const dsc_message_padded_formatted = Array.from(dsc_message_padded).map((x) => x.toString()) y: csca_y,
const dsc_messagePaddedLen_formatted = BigInt(dsc_messagePaddedLen).toString() modulus: csca_modulus,
signature_algorithm: csca_signature_algorithm,
} = parseCertificate(cscaPem);
const { n: n_csca, k: k_csca } = getNAndKCSCA(csca_signature_algorithm);
const cscaPem = getCSCAFromSKI(authorityKeyIdentifier, devMode); const leaf = getLeafCSCA(cscaPem);
console.log('cscaPem', cscaPem); const [root, proof] = getCSCAModulusProof(leaf);
const { x: csca_x, y: csca_y, modulus: csca_modulus, signature_algorithm: csca_signature_algorithm } = parseCertificate(cscaPem); if (signatureAlgorithm === 'ecdsa') {
const { n: n_csca, k: k_csca } = getNAndKCSCA(csca_signature_algorithm); const { r, s } = extractRSFromSignature(encryptedDigest);
const signature_r = splitToWords(BigInt(hexToDecimal(r)), n_csca, k_csca);
const signature_s = splitToWords(BigInt(hexToDecimal(s)), n_csca, k_csca);
signature = [...signature_r, ...signature_s];
const dsc_x_formatted = splitToWords(BigInt(hexToDecimal(x)), n, k);
const dsc_y_formatted = splitToWords(BigInt(hexToDecimal(y)), n, k);
pubKey = [...dsc_x_formatted, ...dsc_y_formatted];
} else {
signature = splitToWords(BigInt(bytesToBigDecimal(encryptedDigest)), n_csca, k_csca);
const leaf = getLeafCSCA(cscaPem); pubKey = splitToWords(BigInt(hexToDecimal(modulus)), n, k);
const [root, proof] = getCSCAModulusProof(leaf); }
if (signatureAlgorithm === 'ecdsa') { let csca_pubKey_formatted;
const { r, s } = extractRSFromSignature(encryptedDigest); if (csca_signature_algorithm === 'ecdsa') {
const signature_r = splitToWords(BigInt(hexToDecimal(r)), n_csca, k_csca) const csca_x_formatted = splitToWords(BigInt(hexToDecimal(csca_x)), n_csca, k_csca);
const signature_s = splitToWords(BigInt(hexToDecimal(s)), n_csca, k_csca) const csca_y_formatted = splitToWords(BigInt(hexToDecimal(csca_y)), n_csca, k_csca);
signature = [...signature_r, ...signature_s] csca_pubKey_formatted = [...csca_x_formatted, ...csca_y_formatted];
const dsc_x_formatted = splitToWords(BigInt(hexToDecimal(x)), n, k) } else {
const dsc_y_formatted = splitToWords(BigInt(hexToDecimal(y)), n, k) csca_pubKey_formatted = splitToWords(BigInt(hexToDecimal(csca_modulus)), n_csca, k_csca);
pubKey = [...dsc_x_formatted, ...dsc_y_formatted] }
} else {
signature = splitToWords(
BigInt(bytesToBigDecimal(encryptedDigest)),
n_csca,
k_csca
)
pubKey = splitToWords(
BigInt(hexToDecimal(modulus)),
n,
k
)
}
let csca_pubKey_formatted;
if (csca_signature_algorithm === 'ecdsa') {
const csca_x_formatted = splitToWords(BigInt(hexToDecimal(csca_x)), n_csca, k_csca);
const csca_y_formatted = splitToWords(BigInt(hexToDecimal(csca_y)), n_csca, k_csca);
csca_pubKey_formatted = [...csca_x_formatted, ...csca_y_formatted];
}
else {
csca_pubKey_formatted = splitToWords(BigInt(hexToDecimal(csca_modulus)), n_csca, k_csca);
}
return {
"signature_algorithm": `${signatureAlgorithm}_${curve || exponent}_${hashFunction}_${4096}`,
"inputs":
{
"raw_dsc_cert": dsc_message_padded_formatted,
"raw_dsc_cert_padded_bytes": [dsc_messagePaddedLen_formatted],
"csca_pubKey": csca_pubKey_formatted,
"signature": signature,
"dsc_pubKey": pubKey,
"dsc_pubKey_offset": [startIndex_formatted],
"secret": [dscSecret],
"merkle_root": [BigInt(root).toString()],
"path": proof.pathIndices.map(index => index.toString()),
"siblings": proof.siblings.flat().map(sibling => sibling.toString())
}
}
return {
signature_algorithm: `${signatureAlgorithm}_${curve || exponent}_${hashFunction}_${4096}`,
inputs: {
raw_dsc_cert: dsc_message_padded_formatted,
raw_dsc_cert_padded_bytes: [dsc_messagePaddedLen_formatted],
csca_pubKey: csca_pubKey_formatted,
signature: signature,
dsc_pubKey: pubKey,
dsc_pubKey_offset: [startIndex_formatted],
secret: [dscSecret],
merkle_root: [BigInt(root).toString()],
path: proof.pathIndices.map((index) => index.toString()),
siblings: proof.siblings.flat().map((sibling) => sibling.toString()),
},
};
} }
export function getCSCAFromSKI(ski: string, devMode: boolean): string { export function getCSCAFromSKI(ski: string, devMode: boolean): string {
const cscaPemPROD = (SKI_PEM as any)[ski]; const cscaPemPROD = (SKI_PEM as any)[ski];
const cscaPemDEV = (SKI_PEM_DEV as any)[ski]; const cscaPemDEV = (SKI_PEM_DEV as any)[ski];
const cscaPem = devMode ? cscaPemDEV || cscaPemPROD : cscaPemPROD; const cscaPem = devMode ? cscaPemDEV || cscaPemPROD : cscaPemPROD;
if (!cscaPem) { if (!cscaPem) {
console.log('\x1b[31m%s\x1b[0m', `CSCA with SKI ${ski} not found`, 'devMode: ', devMode); console.log('\x1b[31m%s\x1b[0m', `CSCA with SKI ${ski} not found`, 'devMode: ', devMode);
throw new Error(`CSCA not found, authorityKeyIdentifier: ${ski}, areMockPassportsAllowed: ${devMode},`); throw new Error(
} `CSCA not found, authorityKeyIdentifier: ${ski}, areMockPassportsAllowed: ${devMode},`
return cscaPem; );
}
return cscaPem;
} }
export function derToBytes(derValue: string) { export function derToBytes(derValue: string) {
const bytes = []; const bytes = [];
for (let i = 0; i < derValue.length; i++) { for (let i = 0; i < derValue.length; i++) {
bytes.push(derValue.charCodeAt(i)); bytes.push(derValue.charCodeAt(i));
} }
return bytes; return bytes;
} }
export function getCSCAModulusMerkleTree() { export function getCSCAModulusMerkleTree() {
const tree = new IMT(poseidon2, CSCA_TREE_DEPTH, 0, 2); const tree = new IMT(poseidon2, CSCA_TREE_DEPTH, 0, 2);
tree.setNodes(serialized_csca_tree); tree.setNodes(serialized_csca_tree);
return tree; return tree;
} }
export function getCSCAModulusProof(leaf) { export function getCSCAModulusProof(leaf) {
console.log('leaf', leaf); console.log('leaf', leaf);
let tree = new IMT(poseidon2, CSCA_TREE_DEPTH, 0, 2); let tree = new IMT(poseidon2, CSCA_TREE_DEPTH, 0, 2);
tree.setNodes(serialized_csca_tree); tree.setNodes(serialized_csca_tree);
const index = tree.indexOf(leaf); const index = tree.indexOf(leaf);
if (index === -1) { if (index === -1) {
throw new Error("Your public key was not found in the registry"); throw new Error('Your public key was not found in the registry');
} }
const proof = tree.createProof(index); const proof = tree.createProof(index);
return [tree.root, proof]; return [tree.root, proof];
} }
export function getTBSHash(cert: forge.pki.Certificate, hashFunction: 'sha1' | 'sha256', n: number, k: number): string[] { export function getTBSHash(
const tbsCertAsn1 = forge.pki.certificateToAsn1(cert).value[0]; cert: forge.pki.Certificate,
const tbsCertDer = forge.asn1.toDer(tbsCertAsn1 as any).getBytes(); hashFunction: 'sha1' | 'sha256',
const md = hashFunction === 'sha256' ? forge.md.sha256.create() : forge.md.sha1.create(); n: number,
md.update(tbsCertDer); k: number
const tbsCertificateHash = md.digest(); ): string[] {
const tbsCertificateHashString = tbsCertificateHash.data; const tbsCertAsn1 = forge.pki.certificateToAsn1(cert).value[0];
const tbsCertificateHashHex = Buffer.from(tbsCertificateHashString, 'binary').toString('hex'); const tbsCertDer = forge.asn1.toDer(tbsCertAsn1 as any).getBytes();
const tbsCertificateHashBigint = BigInt(`0x${tbsCertificateHashHex}`); const md = hashFunction === 'sha256' ? forge.md.sha256.create() : forge.md.sha1.create();
console.log('tbsCertificateHashBigint', tbsCertificateHashBigint); md.update(tbsCertDer);
return splitToWords(tbsCertificateHashBigint, n, k); const tbsCertificateHash = md.digest();
const tbsCertificateHashString = tbsCertificateHash.data;
const tbsCertificateHashHex = Buffer.from(tbsCertificateHashString, 'binary').toString('hex');
const tbsCertificateHashBigint = BigInt(`0x${tbsCertificateHashHex}`);
console.log('tbsCertificateHashBigint', tbsCertificateHashBigint);
return splitToWords(tbsCertificateHashBigint, n, k);
} }
export const sendCSCARequest = async (inputs_csca: any): Promise<any> => { export const sendCSCARequest = async (inputs_csca: any): Promise<any> => {
try { try {
const response = await axios.post(MODAL_SERVER_ADDRESS, inputs_csca, { const response = await axios.post(MODAL_SERVER_ADDRESS, inputs_csca, {
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
} },
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (axios.isAxiosError(error)) { if (axios.isAxiosError(error)) {
console.error('Axios error:', error.message); console.error('Axios error:', error.message);
if (error.response) { if (error.response) {
console.error('Response data:', error.response.data); console.error('Response data:', error.response.data);
console.error('Response status:', error.response.status); console.error('Response status:', error.response.status);
} }
} else { } else {
console.error('Unexpected error:', error); console.error('Unexpected error:', error);
}
throw error;
} }
throw error;
}
}; };
export const generateDscSecret = () => { export const generateDscSecret = () => {
const secretBytes = forge.random.getBytesSync(31); const secretBytes = forge.random.getBytesSync(31);
return BigInt(`0x${forge.util.bytesToHex(secretBytes)}`).toString(); return BigInt(`0x${forge.util.bytesToHex(secretBytes)}`).toString();
} };

View File

@@ -7,7 +7,7 @@ export function formatCallData_register(parsedCallData: any[]) {
a: parsedCallData[0], a: parsedCallData[0],
b: [parsedCallData[1][0], parsedCallData[1][1]], b: [parsedCallData[1][0], parsedCallData[1][1]],
c: parsedCallData[2], c: parsedCallData[2],
};; };
} }
export function formatCallData_dsc(parsedCallData: any[]) { export function formatCallData_dsc(parsedCallData: any[]) {
return { return {
@@ -16,7 +16,7 @@ export function formatCallData_dsc(parsedCallData: any[]) {
a: parsedCallData[0], a: parsedCallData[0],
b: [parsedCallData[1][0], parsedCallData[1][1]], b: [parsedCallData[1][0], parsedCallData[1][1]],
c: parsedCallData[2], c: parsedCallData[2],
};; };
} }
export function formatCallData_disclose(parsedCallData: any[]) { export function formatCallData_disclose(parsedCallData: any[]) {
@@ -26,10 +26,17 @@ export function formatCallData_disclose(parsedCallData: any[]) {
attestation_id: parsedCallData[3][4], attestation_id: parsedCallData[3][4],
merkle_root: parsedCallData[3][5], merkle_root: parsedCallData[3][5],
scope: parsedCallData[3][6], scope: parsedCallData[3][6],
current_date: [parsedCallData[3][7], parsedCallData[3][8], parsedCallData[3][9], parsedCallData[3][10], parsedCallData[3][11], parsedCallData[3][12]], current_date: [
parsedCallData[3][7],
parsedCallData[3][8],
parsedCallData[3][9],
parsedCallData[3][10],
parsedCallData[3][11],
parsedCallData[3][12],
],
user_identifier: parsedCallData[3][13], user_identifier: parsedCallData[3][13],
a: parsedCallData[0], a: parsedCallData[0],
b: [parsedCallData[1][0], parsedCallData[1][1]], b: [parsedCallData[1][0], parsedCallData[1][1]],
c: parsedCallData[2], c: parsedCallData[2],
}; };
} }

View File

@@ -1,10 +1,5 @@
import { PassportData } from './types'; import { PassportData } from './types';
import { import { hash, assembleEContent, formatAndConcatenateDataHashes, formatMrz } from './utils';
hash,
assembleEContent,
formatAndConcatenateDataHashes,
formatMrz,
} from './utils';
import * as forge from 'node-forge'; import * as forge from 'node-forge';
import * as asn1 from 'asn1js'; import * as asn1 from 'asn1js';
import elliptic from 'elliptic'; import elliptic from 'elliptic';
@@ -39,20 +34,26 @@ export function genMockPassportData(
nationality: keyof typeof countryCodes, nationality: keyof typeof countryCodes,
birthDate: string, birthDate: string,
expiryDate: string, expiryDate: string,
passportNumber: string = "15AA81234", passportNumber: string = '15AA81234',
lastName: string = "DUPONT", lastName: string = 'DUPONT',
firstName: string = "ALPHONSE HUGHUES ALBERT" firstName: string = 'ALPHONSE HUGHUES ALBERT'
): PassportData { ): PassportData {
if (birthDate.length !== 6 || expiryDate.length !== 6) { if (birthDate.length !== 6 || expiryDate.length !== 6) {
throw new Error('birthdate and expiry date have to be in the "YYMMDD" format'); throw new Error('birthdate and expiry date have to be in the "YYMMDD" format');
} }
// Prepare last name: Convert to uppercase, remove invalid characters, split by spaces, and join with '<' // Prepare last name: Convert to uppercase, remove invalid characters, split by spaces, and join with '<'
const lastNameParts = lastName.toUpperCase().replace(/[^A-Z< ]/g, '').split(' '); const lastNameParts = lastName
.toUpperCase()
.replace(/[^A-Z< ]/g, '')
.split(' ');
const formattedLastName = lastNameParts.join('<'); const formattedLastName = lastNameParts.join('<');
// Prepare first name: Convert to uppercase, remove invalid characters, split by spaces, and join with '<' // Prepare first name: Convert to uppercase, remove invalid characters, split by spaces, and join with '<'
const firstNameParts = firstName.toUpperCase().replace(/[^A-Z< ]/g, '').split(' '); const firstNameParts = firstName
.toUpperCase()
.replace(/[^A-Z< ]/g, '')
.split(' ');
const formattedFirstName = firstNameParts.join('<'); const formattedFirstName = firstNameParts.join('<');
// Build the first line of MRZ // Build the first line of MRZ
@@ -154,11 +155,7 @@ export function genMockPassportData(
}; };
} }
function sign( function sign(privateKeyPem: string, dsc: string, eContent: number[]): number[] {
privateKeyPem: string,
dsc: string,
eContent: number[]
): number[] {
const { signatureAlgorithm, hashFunction, curve } = parseCertificate(dsc); const { signatureAlgorithm, hashFunction, curve } = parseCertificate(dsc);
if (signatureAlgorithm === 'rsapss') { if (signatureAlgorithm === 'rsapss') {

View File

@@ -1,4 +1,9 @@
import { PUBKEY_TREE_DEPTH, DEFAULT_USER_ID_TYPE, MAX_PADDED_ECONTENT_LEN, MAX_PADDED_SIGNED_ATTR_LEN } from '../constants/constants'; import {
PUBKEY_TREE_DEPTH,
DEFAULT_USER_ID_TYPE,
MAX_PADDED_ECONTENT_LEN,
MAX_PADDED_SIGNED_ATTR_LEN,
} from '../constants/constants';
import { assert, shaPad } from './shaPad'; import { assert, shaPad } from './shaPad';
import { PassportData } from './types'; import { PassportData } from './types';
import { import {
@@ -20,11 +25,11 @@ import {
stringToAsciiBigIntArray, stringToAsciiBigIntArray,
formatCountriesList, formatCountriesList,
} from './utils'; } from './utils';
import { generateCommitment, getLeaf } from "./pubkeyTree"; import { generateCommitment, getLeaf } from './pubkeyTree';
import { LeanIMT } from "@openpassport/zk-kit-lean-imt"; import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
import { getCountryLeaf, getNameLeaf, getNameDobLeaf, getPassportNumberLeaf } from "./smtTree"; import { getCountryLeaf, getNameLeaf, getNameDobLeaf, getPassportNumberLeaf } from './smtTree';
import { packBytes } from "../utils/utils"; import { packBytes } from '../utils/utils';
import { SMT } from "@openpassport/zk-kit-smt" import { SMT } from '@openpassport/zk-kit-smt';
import { parseCertificate } from './certificates/handleCertificate'; import { parseCertificate } from './certificates/handleCertificate';
export function generateCircuitInputsDisclose( export function generateCircuitInputsDisclose(
@@ -41,13 +46,18 @@ export function generateCircuitInputsDisclose(
forbidden_countries_list: string[], forbidden_countries_list: string[],
user_identifier: string user_identifier: string
) { ) {
const pubkey_leaf = getLeaf(passportData.dsc); const pubkey_leaf = getLeaf(passportData.dsc);
const formattedMrz = formatMrz(passportData.mrz); const formattedMrz = formatMrz(passportData.mrz);
const mrz_bytes_packed = packBytes(formattedMrz); const mrz_bytes_packed = packBytes(formattedMrz);
const commitment = generateCommitment(BigInt(secret).toString(), BigInt(attestation_id).toString(), BigInt(pubkey_leaf).toString(), mrz_bytes_packed, formatDg2Hash(passportData.dg2Hash)); const commitment = generateCommitment(
console.log("\x1b[90mcommitment:\x1b[0m", commitment); BigInt(secret).toString(),
BigInt(attestation_id).toString(),
BigInt(pubkey_leaf).toString(),
mrz_bytes_packed,
formatDg2Hash(passportData.dg2Hash)
);
console.log('\x1b[90mcommitment:\x1b[0m', commitment);
const index = findIndexInTree(merkletree, commitment); const index = findIndexInTree(merkletree, commitment);
@@ -57,12 +67,16 @@ export function generateCircuitInputsDisclose(
PUBKEY_TREE_DEPTH PUBKEY_TREE_DEPTH
); );
const formattedMajority = majority.length === 1 ? `0${majority}` : majority; const formattedMajority = majority.length === 1 ? `0${majority}` : majority;
const majority_ascii = formattedMajority.split('').map(char => char.charCodeAt(0)); const majority_ascii = formattedMajority.split('').map((char) => char.charCodeAt(0));
// SMT - OFAC // SMT - OFAC
const name_leaf = getNameLeaf(formattedMrz.slice(10, 49)) // [6-44] + 5 shift const name_leaf = getNameLeaf(formattedMrz.slice(10, 49)); // [6-44] + 5 shift
const { root: smt_root, closestleaf: smt_leaf_value, siblings: smt_siblings } = generateSMTProof(name_smt, name_leaf); const {
root: smt_root,
closestleaf: smt_leaf_value,
siblings: smt_siblings,
} = generateSMTProof(name_smt, name_leaf);
return { return {
secret: formatInput(secret), secret: formatInput(secret),
@@ -84,20 +98,19 @@ export function generateCircuitInputsDisclose(
smt_leaf_value: formatInput(smt_leaf_value), smt_leaf_value: formatInput(smt_leaf_value),
smt_siblings: formatInput(smt_siblings), smt_siblings: formatInput(smt_siblings),
selector_ofac: formatInput(selector_ofac), selector_ofac: formatInput(selector_ofac),
forbidden_countries_list: formatInput(formatCountriesList(forbidden_countries_list)) forbidden_countries_list: formatInput(formatCountriesList(forbidden_countries_list)),
}; };
} }
export function generateCircuitInputsOfac( export function generateCircuitInputsOfac(
passportData: PassportData, passportData: PassportData,
sparsemerkletree: SMT, sparsemerkletree: SMT,
proofLevel: number, proofLevel: number
) { ) {
const mrz_bytes = formatMrz(passportData.mrz); const mrz_bytes = formatMrz(passportData.mrz);
const passport_leaf = getPassportNumberLeaf(mrz_bytes.slice(49, 58)) const passport_leaf = getPassportNumberLeaf(mrz_bytes.slice(49, 58));
const namedob_leaf = getNameDobLeaf(mrz_bytes.slice(10, 49), mrz_bytes.slice(62, 68)) // [57-62] + 5 shift const namedob_leaf = getNameDobLeaf(mrz_bytes.slice(10, 49), mrz_bytes.slice(62, 68)); // [57-62] + 5 shift
const name_leaf = getNameLeaf(mrz_bytes.slice(10, 49)) // [6-44] + 5 shift const name_leaf = getNameLeaf(mrz_bytes.slice(10, 49)); // [6-44] + 5 shift
let root, closestleaf, siblings; let root, closestleaf, siblings;
if (proofLevel == 3) { if (proofLevel == 3) {
@@ -107,7 +120,7 @@ export function generateCircuitInputsOfac(
} else if (proofLevel == 1) { } else if (proofLevel == 1) {
({ root, closestleaf, siblings } = generateSMTProof(sparsemerkletree, name_leaf)); ({ root, closestleaf, siblings } = generateSMTProof(sparsemerkletree, name_leaf));
} else { } else {
throw new Error("Invalid proof level") throw new Error('Invalid proof level');
} }
return { return {
@@ -120,11 +133,11 @@ export function generateCircuitInputsOfac(
export function generateCircuitInputsCountryVerifier( export function generateCircuitInputsCountryVerifier(
passportData: PassportData, passportData: PassportData,
sparsemerkletree: SMT, sparsemerkletree: SMT
) { ) {
const mrz_bytes = formatMrz(passportData.mrz); const mrz_bytes = formatMrz(passportData.mrz);
const usa_ascii = stringToAsciiBigIntArray("USA") const usa_ascii = stringToAsciiBigIntArray('USA');
const country_leaf = getCountryLeaf(usa_ascii, mrz_bytes.slice(7, 10)) const country_leaf = getCountryLeaf(usa_ascii, mrz_bytes.slice(7, 10));
const { root, closestleaf, siblings } = generateSMTProof(sparsemerkletree, country_leaf); const { root, closestleaf, siblings } = generateSMTProof(sparsemerkletree, country_leaf);
return { return {
@@ -152,7 +165,6 @@ export function findIndexInTree(tree: LeanIMT, commitment: bigint): number {
return index; return index;
} }
export function generateCircuitInputsProve( export function generateCircuitInputsProve(
selector_mode: number[] | string[], selector_mode: number[] | string[],
secret: number | string, secret: number | string,
@@ -168,9 +180,9 @@ export function generateCircuitInputsProve(
user_identifier: string, user_identifier: string,
user_identifier_type: 'uuid' | 'hex' | 'ascii' = DEFAULT_USER_ID_TYPE user_identifier_type: 'uuid' | 'hex' | 'ascii' = DEFAULT_USER_ID_TYPE
) { ) {
const { mrz, eContent, signedAttr, encryptedDigest, dsc, dg2Hash } = passportData; const { mrz, eContent, signedAttr, encryptedDigest, dsc, dg2Hash } = passportData;
const { signatureAlgorithm, hashFunction, hashLen, x, y, modulus, curve, exponent, bits } = parseCertificate(passportData.dsc); const { signatureAlgorithm, hashFunction, hashLen, x, y, modulus, curve, exponent, bits } =
parseCertificate(passportData.dsc);
const signatureAlgorithmFullName = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`; const signatureAlgorithmFullName = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`;
let pubKey: any; let pubKey: any;
@@ -180,40 +192,36 @@ export function generateCircuitInputsProve(
if (signatureAlgorithm === 'ecdsa') { if (signatureAlgorithm === 'ecdsa') {
const { r, s } = extractRSFromSignature(encryptedDigest); const { r, s } = extractRSFromSignature(encryptedDigest);
const signature_r = splitToWords(BigInt(hexToDecimal(r)), n, k) const signature_r = splitToWords(BigInt(hexToDecimal(r)), n, k);
const signature_s = splitToWords(BigInt(hexToDecimal(s)), n, k) const signature_s = splitToWords(BigInt(hexToDecimal(s)), n, k);
signature = [...signature_r, ...signature_s] signature = [...signature_r, ...signature_s];
const dsc_modulus_x = splitToWords(BigInt(hexToDecimal(x)), n, k) const dsc_modulus_x = splitToWords(BigInt(hexToDecimal(x)), n, k);
const dsc_modulus_y = splitToWords(BigInt(hexToDecimal(y)), n, k) const dsc_modulus_y = splitToWords(BigInt(hexToDecimal(y)), n, k);
pubKey = [...dsc_modulus_x, ...dsc_modulus_y] pubKey = [...dsc_modulus_x, ...dsc_modulus_y];
} else { } else {
signature = splitToWords( signature = splitToWords(BigInt(bytesToBigDecimal(encryptedDigest)), n, k);
BigInt(bytesToBigDecimal(encryptedDigest)),
n,
k
)
pubKey = splitToWords( pubKey = splitToWords(BigInt(hexToDecimal(modulus)), n, k);
BigInt(hexToDecimal(modulus)),
n,
k
)
} }
const formattedMrz = formatMrz(mrz); const formattedMrz = formatMrz(mrz);
const dg1Hash = hash(hashFunction, formattedMrz); const dg1Hash = hash(hashFunction, formattedMrz);
const dg1HashOffset = findSubarrayIndex(eContent, dg1Hash) const dg1HashOffset = findSubarrayIndex(eContent, dg1Hash);
console.log('\x1b[90m%s\x1b[0m', 'dg1HashOffset', dg1HashOffset); console.log('\x1b[90m%s\x1b[0m', 'dg1HashOffset', dg1HashOffset);
assert(dg1HashOffset !== -1, `DG1 hash ${dg1Hash} not found in eContent`); assert(dg1HashOffset !== -1, `DG1 hash ${dg1Hash} not found in eContent`);
const eContentHash = hash(hashFunction, eContent); const eContentHash = hash(hashFunction, eContent);
const eContentHashOffset = findSubarrayIndex(signedAttr, eContentHash) const eContentHashOffset = findSubarrayIndex(signedAttr, eContentHash);
console.log('\x1b[90m%s\x1b[0m', 'eContentHashOffset', eContentHashOffset); console.log('\x1b[90m%s\x1b[0m', 'eContentHashOffset', eContentHashOffset);
assert(eContentHashOffset !== -1, `eContent hash ${eContentHash} not found in signedAttr`); assert(eContentHashOffset !== -1, `eContent hash ${eContentHash} not found in signedAttr`);
if (eContent.length > MAX_PADDED_ECONTENT_LEN[signatureAlgorithmFullName]) { if (eContent.length > MAX_PADDED_ECONTENT_LEN[signatureAlgorithmFullName]) {
console.error(`Data hashes too long (${eContent.length} bytes). Max length is ${MAX_PADDED_ECONTENT_LEN[signatureAlgorithmFullName]} bytes.`); console.error(
throw new Error(`This length of datagroups (${eContent.length} bytes) is currently unsupported. Please contact us so we add support!`); `Data hashes too long (${eContent.length} bytes). Max length is ${MAX_PADDED_ECONTENT_LEN[signatureAlgorithmFullName]} bytes.`
);
throw new Error(
`This length of datagroups (${eContent.length} bytes) is currently unsupported. Please contact us so we add support!`
);
} }
const [eContentPadded, eContentLen] = shaPad( const [eContentPadded, eContentLen] = shaPad(
@@ -227,12 +235,16 @@ export function generateCircuitInputsProve(
); );
const formattedMajority = majority.length === 1 ? `0${majority}` : majority; const formattedMajority = majority.length === 1 ? `0${majority}` : majority;
const majority_ascii = formattedMajority.split('').map(char => char.charCodeAt(0)) const majority_ascii = formattedMajority.split('').map((char) => char.charCodeAt(0));
// SMT - OFAC // SMT - OFAC
const mrz_bytes = formatMrz(passportData.mrz); const mrz_bytes = formatMrz(passportData.mrz);
const name_leaf = getNameLeaf(mrz_bytes.slice(10, 49)) // [6-44] + 5 shift const name_leaf = getNameLeaf(mrz_bytes.slice(10, 49)); // [6-44] + 5 shift
const { root: smt_root, closestleaf: smt_leaf_value, siblings: smt_siblings } = generateSMTProof(name_smt, name_leaf); const {
root: smt_root,
closestleaf: smt_leaf_value,
siblings: smt_siblings,
} = generateSMTProof(name_smt, name_leaf);
return { return {
selector_mode: formatInput(selector_mode), selector_mode: formatInput(selector_mode),
dg1: formatInput(formattedMrz), dg1: formatInput(formattedMrz),
@@ -257,14 +269,13 @@ export function generateCircuitInputsProve(
smt_leaf_value: formatInput(smt_leaf_value), smt_leaf_value: formatInput(smt_leaf_value),
smt_siblings: formatInput(smt_siblings), smt_siblings: formatInput(smt_siblings),
selector_ofac: formatInput(selector_ofac), selector_ofac: formatInput(selector_ofac),
forbidden_countries_list: formatInput(formatCountriesList(forbidden_countries_list)) forbidden_countries_list: formatInput(formatCountriesList(forbidden_countries_list)),
}; };
} }
export function formatInput(input: any) { export function formatInput(input: any) {
if (Array.isArray(input)) { if (Array.isArray(input)) {
return input.map(item => BigInt(item).toString()); return input.map((item) => BigInt(item).toString());
} else { } else {
return [BigInt(input).toString()]; return [BigInt(input).toString()];
} }

View File

@@ -1,92 +1,89 @@
export function getAdjustedTimestampBytes(y: number = 0, m: number = 0, d: number = 0): number[] { export function getAdjustedTimestampBytes(y: number = 0, m: number = 0, d: number = 0): number[] {
// Get the current date/time // Get the current date/time
let currentDate: Date = new Date(); let currentDate: Date = new Date();
// Optionally adjust the date // Optionally adjust the date
if (y !== 0) currentDate.setFullYear(currentDate.getFullYear() + y); if (y !== 0) currentDate.setFullYear(currentDate.getFullYear() + y);
if (m !== 0) currentDate.setMonth(currentDate.getMonth() + m); if (m !== 0) currentDate.setMonth(currentDate.getMonth() + m);
if (d !== 0) currentDate.setDate(currentDate.getDate() + d); if (d !== 0) currentDate.setDate(currentDate.getDate() + d);
// Get the Unix timestamp (in seconds) // Get the Unix timestamp (in seconds)
const timestamp: number = Math.floor(currentDate.getTime() / 1000); const timestamp: number = Math.floor(currentDate.getTime() / 1000);
// Convert the timestamp to 4 bytes // Convert the timestamp to 4 bytes
const bytes: number[] = [ const bytes: number[] = [
(timestamp >> 24) & 0xFF, (timestamp >> 24) & 0xff,
(timestamp >> 16) & 0xFF, (timestamp >> 16) & 0xff,
(timestamp >> 8) & 0xFF, (timestamp >> 8) & 0xff,
timestamp & 0xFF, timestamp & 0xff,
]; ];
return bytes; return bytes;
} }
export function getTimestampBytesFromYearFraction(yearFraction: number): number[] { export function getTimestampBytesFromYearFraction(yearFraction: number): number[] {
// Separate the year and the fractional part // Separate the year and the fractional part
const year = Math.floor(yearFraction); const year = Math.floor(yearFraction);
const fraction = yearFraction - year; const fraction = yearFraction - year;
// Convert the fractional part into months (0-11) // Convert the fractional part into months (0-11)
const monthsFromFraction = Math.floor(fraction * 12); const monthsFromFraction = Math.floor(fraction * 12);
// Create a date object from the year and the calculated month // Create a date object from the year and the calculated month
// Assuming the first day of the month for simplicity // Assuming the first day of the month for simplicity
const date = new Date(year, monthsFromFraction, 1); const date = new Date(year, monthsFromFraction, 1);
// Get the Unix timestamp (in seconds) // Get the Unix timestamp (in seconds)
const timestamp: number = Math.floor(date.getTime() / 1000); const timestamp: number = Math.floor(date.getTime() / 1000);
// Convert the timestamp to 4 bytes // Convert the timestamp to 4 bytes
const bytes: number[] = [ const bytes: number[] = [
(timestamp >> 24) & 0xff,
(timestamp >> 16) & 0xff,
(timestamp >> 8) & 0xff,
timestamp & 0xff,
];
(timestamp >> 24) & 0xFF, return bytes;
(timestamp >> 16) & 0xFF,
(timestamp >> 8) & 0xFF,
timestamp & 0xFF,
];
return bytes;
} }
export function unixTimestampToYYMMDD(timestamp: number): string { export function unixTimestampToYYMMDD(timestamp: number): string {
console.log("timestamp: " + timestamp); console.log('timestamp: ' + timestamp);
const date = new Date(timestamp * 1000); const date = new Date(timestamp * 1000);
console.log("date: " + date); console.log('date: ' + date);
const year = date.getUTCFullYear(); const year = date.getUTCFullYear();
console.log("year: " + year); console.log('year: ' + year);
const month = date.getUTCMonth() + 1; const month = date.getUTCMonth() + 1;
const day = date.getUTCDate(); const day = date.getUTCDate();
// Ensure the year is correctly formatted as two digits // Ensure the year is correctly formatted as two digits
const YY = (`0${year % 100}`).slice(-2); const YY = `0${year % 100}`.slice(-2);
const MM = (`0${month}`).slice(-2); const MM = `0${month}`.slice(-2);
const DD = (`0${day}`).slice(-2); const DD = `0${day}`.slice(-2);
return `${YY}${MM}${DD}`; return `${YY}${MM}${DD}`;
} }
export function yearFractionToYYMMDD(yearFraction: number): string { export function yearFractionToYYMMDD(yearFraction: number): string {
// Separate the year and the fractional part // Separate the year and the fractional part
const year = yearFraction; const year = yearFraction;
const fraction = yearFraction - Math.floor(yearFraction); const fraction = yearFraction - Math.floor(yearFraction);
// Convert the fractional part into months (0-11) // Convert the fractional part into months (0-11)
const monthsFromFraction = Math.floor(fraction * 12); const monthsFromFraction = Math.floor(fraction * 12);
// Assuming the first day of the month for simplicity // Assuming the first day of the month for simplicity
const day = 1; const day = 1;
// Format year, month, and day into YYMMDD string // Format year, month, and day into YYMMDD string
const YY = (`0${Math.floor(year) % 100}`).slice(-2); const YY = `0${Math.floor(year) % 100}`.slice(-2);
const MM = (`0${monthsFromFraction + 1}`).slice(-2); // +1 because months are 1-indexed in this format const MM = `0${monthsFromFraction + 1}`.slice(-2); // +1 because months are 1-indexed in this format
const DD = (`0${day}`).slice(-2); const DD = `0${day}`.slice(-2);
return `${YY}${MM}${DD}`; return `${YY}${MM}${DD}`;
} }
export function yymmddToByteArray(yymmdd: string): number[] { export function yymmddToByteArray(yymmdd: string): number[] {
// Convert each character in the string to its ASCII value // Convert each character in the string to its ASCII value
const byteArray = Array.from(yymmdd).map(char => char.charCodeAt(0)); const byteArray = Array.from(yymmdd).map((char) => char.charCodeAt(0));
return byteArray; return byteArray;
} }

View File

@@ -1,8 +1,4 @@
import { import { ECDSA_K_LENGTH_FACTOR, k_dsc, k_dsc_ecdsa } from '../constants/constants';
ECDSA_K_LENGTH_FACTOR,
k_dsc,
k_dsc_ecdsa,
} from '../constants/constants';
import { parseDSC } from './certificates/handleCertificate'; import { parseDSC } from './certificates/handleCertificate';
import { import {
bigIntToHex, bigIntToHex,
@@ -12,7 +8,7 @@ import {
UserIdType, UserIdType,
} from './utils'; } from './utils';
import { unpackReveal } from './revealBitmap'; import { unpackReveal } from './revealBitmap';
import { getAttributeFromUnpackedReveal } from './utils' import { getAttributeFromUnpackedReveal } from './utils';
import { Mode } from 'fs'; import { Mode } from 'fs';
export interface OpenPassportAttestation { export interface OpenPassportAttestation {
@@ -135,9 +131,7 @@ export function buildAttestation(options: {
const scope = castToScope(BigInt(parsedPublicSignals.scope)); const scope = castToScope(BigInt(parsedPublicSignals.scope));
// Unpack the revealed data // Unpack the revealed data
const unpackedReveal = unpackReveal( const unpackedReveal = unpackReveal(parsedPublicSignals.revealedData_packed);
parsedPublicSignals.revealedData_packed
);
const attributeNames = [ const attributeNames = [
'issuing_state', 'issuing_state',
@@ -149,7 +143,9 @@ export function buildAttestation(options: {
'expiry_date', 'expiry_date',
'older_than', 'older_than',
]; ];
const formattedCountryList = formatForbiddenCountriesListFromCircuitOutput(parsedPublicSignals.forbidden_countries_list_packed_disclosed); const formattedCountryList = formatForbiddenCountriesListFromCircuitOutput(
parsedPublicSignals.forbidden_countries_list_packed_disclosed
);
const credentialSubject: any = { const credentialSubject: any = {
userId: userId, userId: userId,
application: scope, application: scope,
@@ -161,7 +157,6 @@ export function buildAttestation(options: {
not_in_countries: formattedCountryList, not_in_countries: formattedCountryList,
}; };
attributeNames.forEach((attrName) => { attributeNames.forEach((attrName) => {
const value = getAttributeFromUnpackedReveal(unpackedReveal, attrName); const value = getAttributeFromUnpackedReveal(unpackedReveal, attrName);
if (value !== undefined && value !== null) { if (value !== undefined && value !== null) {
@@ -172,10 +167,7 @@ export function buildAttestation(options: {
credentialSubject.pubKey = parsedPublicSignals.pubKey_disclosed ?? []; credentialSubject.pubKey = parsedPublicSignals.pubKey_disclosed ?? [];
const attestation: OpenPassportAttestation = { const attestation: OpenPassportAttestation = {
'@context': [ '@context': ['https://www.w3.org/2018/credentials/v1', 'https://openpassport.app'],
'https://www.w3.org/2018/credentials/v1',
'https://openpassport.app',
],
type: ['OpenPassportAttestation', 'PassportCredential'], type: ['OpenPassportAttestation', 'PassportCredential'],
issuer: 'https://openpassport.app', issuer: 'https://openpassport.app',
issuanceDate: new Date().toISOString(), issuanceDate: new Date().toISOString(),
@@ -185,8 +177,7 @@ export function buildAttestation(options: {
signatureAlgorithm: signatureAlgorithm, signatureAlgorithm: signatureAlgorithm,
hashFunction: hashFunction, hashFunction: hashFunction,
type: 'ZeroKnowledgeProof', type: 'ZeroKnowledgeProof',
verificationMethod: verificationMethod: 'https://github.com/zk-passport/openpassport',
'https://github.com/zk-passport/openpassport',
value: { value: {
proof: proof, proof: proof,
publicSignals: publicSignals, publicSignals: publicSignals,
@@ -197,8 +188,7 @@ export function buildAttestation(options: {
signatureAlgorithm: signatureAlgorithmDsc, signatureAlgorithm: signatureAlgorithmDsc,
hashFunction: hashFunctionDsc, hashFunction: hashFunctionDsc,
type: 'ZeroKnowledgeProof', type: 'ZeroKnowledgeProof',
verificationMethod: verificationMethod: 'https://github.com/zk-passport/openpassport',
'https://github.com/zk-passport/openpassport',
value: { value: {
proof: dscProof || [], proof: dscProof || [],
publicSignals: dscPublicSignals || [], publicSignals: dscPublicSignals || [],
@@ -288,8 +278,7 @@ export class OpenPassportDynamicAttestation implements OpenPassportAttestation {
private parsePublicSignals() { private parsePublicSignals() {
if (this.proof.mode === 'vc_and_disclose') { if (this.proof.mode === 'vc_and_disclose') {
return parsePublicSignalsDisclose(this.proof.value.publicSignals); return parsePublicSignalsDisclose(this.proof.value.publicSignals);
} } else {
else {
let kScaled: number; let kScaled: number;
switch (this.proof.signatureAlgorithm) { switch (this.proof.signatureAlgorithm) {
case 'ecdsa': case 'ecdsa':
@@ -301,7 +290,6 @@ export class OpenPassportDynamicAttestation implements OpenPassportAttestation {
return parsePublicSignalsProve(this.proof.value.publicSignals, kScaled); return parsePublicSignalsProve(this.proof.value.publicSignals, kScaled);
} }
// Parse the public signals // Parse the public signals
} }
@@ -329,8 +317,7 @@ export class OpenPassportDynamicAttestation implements OpenPassportAttestation {
const parsedPublicSignals = this.parsePublicSignals(); const parsedPublicSignals = this.parsePublicSignals();
if (this.proof.mode === 'vc_and_disclose') { if (this.proof.mode === 'vc_and_disclose') {
return ''; return '';
} } else {
else {
return (parsedPublicSignals as any).commitment; return (parsedPublicSignals as any).commitment;
} }
} }
@@ -346,8 +333,7 @@ export class OpenPassportDynamicAttestation implements OpenPassportAttestation {
if (this.dscProof.value.publicSignals) { if (this.dscProof.value.publicSignals) {
const parsedPublicSignalsDsc = parsePublicSignalsDsc(this.dscProof.value.publicSignals); const parsedPublicSignalsDsc = parsePublicSignalsDsc(this.dscProof.value.publicSignals);
return parsedPublicSignalsDsc.merkle_root; return parsedPublicSignalsDsc.merkle_root;
} } else {
else {
throw new Error('No DSC proof found'); throw new Error('No DSC proof found');
} }
} }
@@ -373,7 +359,7 @@ export function parsePublicSignalsDsc(publicSignals) {
return { return {
blinded_dsc_commitment: publicSignals[0], blinded_dsc_commitment: publicSignals[0],
merkle_root: publicSignals[1], merkle_root: publicSignals[1],
} };
} }
export function parsePublicSignalsDisclose(publicSignals) { export function parsePublicSignalsDisclose(publicSignals) {
@@ -389,6 +375,5 @@ export function parsePublicSignalsDisclose(publicSignals) {
current_date: publicSignals.slice(12, 18), current_date: publicSignals.slice(12, 18),
user_identifier: publicSignals[18], user_identifier: publicSignals[18],
smt_root: publicSignals[19], smt_root: publicSignals[19],
} };
} }

View File

@@ -1,12 +1,12 @@
import { PassportData } from "./types"; import { PassportData } from './types';
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
export function getLocalPassportData(): PassportData { export function getLocalPassportData(): PassportData {
const passportDataPath = path.join(__dirname, '../../inputs/passportData.json'); const passportDataPath = path.join(__dirname, '../../inputs/passportData.json');
if ( fs.existsSync(passportDataPath)) { if (fs.existsSync(passportDataPath)) {
return require(passportDataPath); return require(passportDataPath);
} else { } else {
throw new Error('Passport data not found at inputs/passportData.json'); throw new Error('Passport data not found at inputs/passportData.json');
} }
} }

View File

@@ -1,27 +1,57 @@
import { import {
poseidon1, poseidon2, poseidon3, poseidon4, poseidon5, poseidon6, poseidon7, poseidon8, poseidon1,
poseidon9, poseidon10, poseidon11, poseidon12, poseidon13, poseidon14, poseidon15, poseidon16 poseidon2,
poseidon3,
poseidon4,
poseidon5,
poseidon6,
poseidon7,
poseidon8,
poseidon9,
poseidon10,
poseidon11,
poseidon12,
poseidon13,
poseidon14,
poseidon15,
poseidon16,
} from 'poseidon-lite'; } from 'poseidon-lite';
export function flexiblePoseidon(inputs: bigint[]): bigint { export function flexiblePoseidon(inputs: bigint[]): bigint {
switch (inputs.length) { switch (inputs.length) {
case 1: return poseidon1(inputs); case 1:
case 2: return poseidon2(inputs); return poseidon1(inputs);
case 3: return poseidon3(inputs); case 2:
case 4: return poseidon4(inputs); return poseidon2(inputs);
case 5: return poseidon5(inputs); case 3:
case 6: return poseidon6(inputs); return poseidon3(inputs);
case 7: return poseidon7(inputs); case 4:
case 8: return poseidon8(inputs); return poseidon4(inputs);
case 9: return poseidon9(inputs); case 5:
case 10: return poseidon10(inputs); return poseidon5(inputs);
case 11: return poseidon11(inputs); case 6:
case 12: return poseidon12(inputs); return poseidon6(inputs);
case 13: return poseidon13(inputs); case 7:
case 14: return poseidon14(inputs); return poseidon7(inputs);
case 15: return poseidon15(inputs); case 8:
case 16: return poseidon16(inputs); return poseidon8(inputs);
default: case 9:
throw new Error(`Unsupported number of inputs: ${inputs.length}`); return poseidon9(inputs);
} case 10:
return poseidon10(inputs);
case 11:
return poseidon11(inputs);
case 12:
return poseidon12(inputs);
case 13:
return poseidon13(inputs);
case 14:
return poseidon14(inputs);
case 15:
return poseidon15(inputs);
case 16:
return poseidon16(inputs);
default:
throw new Error(`Unsupported number of inputs: ${inputs.length}`);
}
} }

View File

@@ -1,10 +1,14 @@
import { PUBKEY_TREE_DEPTH, COMMITMENT_TREE_TRACKER_URL, SignatureAlgorithmIndex } from "../constants/constants"; import {
import { LeanIMT } from '@openpassport/zk-kit-lean-imt' PUBKEY_TREE_DEPTH,
import axios from "axios"; COMMITMENT_TREE_TRACKER_URL,
SignatureAlgorithmIndex,
} from '../constants/constants';
import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
import axios from 'axios';
import { poseidon16, poseidon2, poseidon6, poseidon7 } from 'poseidon-lite'; import { poseidon16, poseidon2, poseidon6, poseidon7 } from 'poseidon-lite';
import { formatDg2Hash, getNAndK, getNAndKCSCA, hexToDecimal, splitToWords } from './utils'; import { formatDg2Hash, getNAndK, getNAndKCSCA, hexToDecimal, splitToWords } from './utils';
import { parseCertificate } from "./certificates/handleCertificate"; import { parseCertificate } from './certificates/handleCertificate';
import { flexiblePoseidon } from "./poseidon"; import { flexiblePoseidon } from './poseidon';
export function customHasher(pubKeyFormatted: string[]) { export function customHasher(pubKeyFormatted: string[]) {
const rounds = Math.ceil(pubKeyFormatted.length / 16); const rounds = Math.ceil(pubKeyFormatted.length / 16);
@@ -19,12 +23,13 @@ export function customHasher(pubKeyFormatted: string[]) {
} }
} }
} }
const finalHash = flexiblePoseidon(hash.map(h => poseidon16(h.inputs))); const finalHash = flexiblePoseidon(hash.map((h) => poseidon16(h.inputs)));
return finalHash.toString(); return finalHash.toString();
} }
export function getLeaf(dsc: string): string { export function getLeaf(dsc: string): string {
const { signatureAlgorithm, hashFunction, modulus, x, y, bits, curve, exponent } = parseCertificate(dsc); const { signatureAlgorithm, hashFunction, modulus, x, y, bits, curve, exponent } =
parseCertificate(dsc);
const { n, k } = getNAndK(signatureAlgorithm); const { n, k } = getNAndK(signatureAlgorithm);
console.log(`${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`); console.log(`${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`);
const sigAlgKey = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`; const sigAlgKey = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`;
@@ -37,17 +42,17 @@ export function getLeaf(dsc: string): string {
if (signatureAlgorithm === 'ecdsa') { if (signatureAlgorithm === 'ecdsa') {
let qx = splitToWords(BigInt(hexToDecimal(x)), n, k); let qx = splitToWords(BigInt(hexToDecimal(x)), n, k);
let qy = splitToWords(BigInt(hexToDecimal(y)), n, k); let qy = splitToWords(BigInt(hexToDecimal(y)), n, k);
return customHasher([sigAlgIndex, ...qx, ...qy]) return customHasher([sigAlgIndex, ...qx, ...qy]);
} else { } else {
const pubkeyChunked = splitToWords(BigInt(hexToDecimal(modulus)), n, k); const pubkeyChunked = splitToWords(BigInt(hexToDecimal(modulus)), n, k);
return customHasher([sigAlgIndex, ...pubkeyChunked]); return customHasher([sigAlgIndex, ...pubkeyChunked]);
} }
} }
export function getLeafCSCA(dsc: string): string { export function getLeafCSCA(dsc: string): string {
const { signatureAlgorithm, hashFunction, modulus, x, y, bits, curve, exponent } = parseCertificate(dsc); const { signatureAlgorithm, hashFunction, modulus, x, y, bits, curve, exponent } =
parseCertificate(dsc);
const { n, k } = getNAndKCSCA(signatureAlgorithm); const { n, k } = getNAndKCSCA(signatureAlgorithm);
console.log(`${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`) console.log(`${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`);
const sigAlgKey = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`; const sigAlgKey = `${signatureAlgorithm}_${hashFunction}_${curve || exponent}_${bits}`;
console.log('sigAlgKey', sigAlgKey); console.log('sigAlgKey', sigAlgKey);
const sigAlgIndex = SignatureAlgorithmIndex[sigAlgKey]; const sigAlgIndex = SignatureAlgorithmIndex[sigAlgKey];
@@ -60,16 +65,21 @@ export function getLeafCSCA(dsc: string): string {
if (signatureAlgorithm === 'ecdsa') { if (signatureAlgorithm === 'ecdsa') {
let qx = splitToWords(BigInt(hexToDecimal(x)), n, k); let qx = splitToWords(BigInt(hexToDecimal(x)), n, k);
let qy = splitToWords(BigInt(hexToDecimal(y)), n, k); let qy = splitToWords(BigInt(hexToDecimal(y)), n, k);
return customHasher([sigAlgIndex, ...qx, ...qy]) return customHasher([sigAlgIndex, ...qx, ...qy]);
} else { } else {
const pubkeyChunked = splitToWords(BigInt(hexToDecimal(modulus)), n, k); const pubkeyChunked = splitToWords(BigInt(hexToDecimal(modulus)), n, k);
return customHasher([sigAlgIndex, ...pubkeyChunked]); return customHasher([sigAlgIndex, ...pubkeyChunked]);
} }
} }
export function generateCommitment(secret: string, attestation_id: string, pubkey_leaf: string, mrz_bytes: any[], dg2Hash: any[]) { export function generateCommitment(
const dg2Hash2 = customHasher(formatDg2Hash(dg2Hash).map(x => x.toString())); secret: string,
attestation_id: string,
pubkey_leaf: string,
mrz_bytes: any[],
dg2Hash: any[]
) {
const dg2Hash2 = customHasher(formatDg2Hash(dg2Hash).map((x) => x.toString()));
const commitment = poseidon7([ const commitment = poseidon7([
secret, secret,
attestation_id, attestation_id,
@@ -77,19 +87,18 @@ export function generateCommitment(secret: string, attestation_id: string, pubke
mrz_bytes[0], mrz_bytes[0],
mrz_bytes[1], mrz_bytes[1],
mrz_bytes[2], mrz_bytes[2],
dg2Hash2 dg2Hash2,
]); ]);
return commitment; return commitment;
} }
export async function fetchTreeFromUrl(url: string): Promise<LeanIMT> { export async function fetchTreeFromUrl(url: string): Promise<LeanIMT> {
const response = await fetch(url); const response = await fetch(url);
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
const commitmentMerkleTree = await response.json(); const commitmentMerkleTree = await response.json();
console.log("\x1b[90m%s\x1b[0m", "commitment merkle tree: ", commitmentMerkleTree); console.log('\x1b[90m%s\x1b[0m', 'commitment merkle tree: ', commitmentMerkleTree);
const tree = LeanIMT.import((a, b) => poseidon2([a, b]), commitmentMerkleTree); const tree = LeanIMT.import((a, b) => poseidon2([a, b]), commitmentMerkleTree);
return tree; return tree;
} }

View File

@@ -1,11 +1,11 @@
import { attributeToPosition } from "../constants/constants"; import { attributeToPosition } from '../constants/constants';
import { DisclosureOptions } from "./appType"; import { DisclosureOptions } from './appType';
export function revealBitmapFromMapping(attributeToReveal: { [key: string]: string }): string[] { export function revealBitmapFromMapping(attributeToReveal: { [key: string]: string }): string[] {
const reveal_bitmap = Array(90).fill('0'); const reveal_bitmap = Array(90).fill('0');
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => { Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
if (reveal !== "") { if (reveal !== '') {
const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition]; const [start, end] = attributeToPosition[attribute as keyof typeof attributeToPosition];
reveal_bitmap.fill('1', start, end + 1); reveal_bitmap.fill('1', start, end + 1);
} }
@@ -26,10 +26,11 @@ export function revealBitmapFromAttributes(disclosureOptions: DisclosureOptions)
return reveal_bitmap; return reveal_bitmap;
} }
export function unpackReveal(revealedData_packed: string | string[]): string[] { export function unpackReveal(revealedData_packed: string | string[]): string[] {
// If revealedData_packed is not an array, convert it to an array // If revealedData_packed is not an array, convert it to an array
const packedArray = Array.isArray(revealedData_packed) ? revealedData_packed : [revealedData_packed]; const packedArray = Array.isArray(revealedData_packed)
? revealedData_packed
: [revealedData_packed];
const bytesCount = [31, 31, 28]; // nb of bytes in each of the first three field elements const bytesCount = [31, 31, 28]; // nb of bytes in each of the first three field elements
const bytesArray = packedArray.flatMap((element: string, index: number) => { const bytesArray = packedArray.flatMap((element: string, index: number) => {
@@ -45,20 +46,21 @@ export function unpackReveal(revealedData_packed: string | string[]): string[] {
return bytesArray.map((byte: bigint) => String.fromCharCode(Number(byte))); return bytesArray.map((byte: bigint) => String.fromCharCode(Number(byte)));
} }
export function formatAndUnpackReveal(revealedData_packed: string[]): string[] { export function formatAndUnpackReveal(revealedData_packed: string[]): string[] {
const revealedData_packed_formatted = [ const revealedData_packed_formatted = [
revealedData_packed["revealedData_packed[0]"], revealedData_packed['revealedData_packed[0]'],
revealedData_packed["revealedData_packed[1]"], revealedData_packed['revealedData_packed[1]'],
revealedData_packed["revealedData_packed[2]"], revealedData_packed['revealedData_packed[2]'],
]; ];
return unpackReveal(revealedData_packed_formatted); return unpackReveal(revealedData_packed_formatted);
} }
export function formatAndUnpackForbiddenCountriesList(forbiddenCountriesList_packed: string[]): string[] { export function formatAndUnpackForbiddenCountriesList(
forbiddenCountriesList_packed: string[]
): string[] {
const forbiddenCountriesList_packed_formatted = [ const forbiddenCountriesList_packed_formatted = [
forbiddenCountriesList_packed["forbidden_countries_list_packed[0]"], forbiddenCountriesList_packed['forbidden_countries_list_packed[0]'],
forbiddenCountriesList_packed["forbidden_countries_list_packed[1]"], forbiddenCountriesList_packed['forbidden_countries_list_packed[1]'],
]; ];
return unpackReveal(forbiddenCountriesList_packed_formatted); return unpackReveal(forbiddenCountriesList_packed_formatted);
} }

View File

@@ -9,7 +9,7 @@ export function shaPad(prehash_prepad_m: Uint8Array, maxShaBytes: number): [Uint
prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, int8toBytes(0)); prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, int8toBytes(0));
} }
prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, length_in_bytes); prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, length_in_bytes);
assert((prehash_prepad_m.length * 8) % 512 === 0, "Padding did not complete properly!"); assert((prehash_prepad_m.length * 8) % 512 === 0, 'Padding did not complete properly!');
let messageLen = prehash_prepad_m.length; let messageLen = prehash_prepad_m.length;
while (prehash_prepad_m.length < maxShaBytes) { while (prehash_prepad_m.length < maxShaBytes) {
prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, int64toBytes(0)); prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, int64toBytes(0));
@@ -49,4 +49,4 @@ export function assert(cond: boolean, errorMessage: string) {
if (!cond) { if (!cond) {
throw new Error(errorMessage); throw new Error(errorMessage);
} }
} }

View File

@@ -1,6 +1,6 @@
import { poseidon9, poseidon3, poseidon2, poseidon6, poseidon13 } from "poseidon-lite" import { poseidon9, poseidon3, poseidon2, poseidon6, poseidon13 } from 'poseidon-lite';
import { stringToAsciiBigIntArray } from "./utils"; import { stringToAsciiBigIntArray } from './utils';
import { ChildNodes, SMT } from "@openpassport/zk-kit-smt" import { ChildNodes, SMT } from '@openpassport/zk-kit-smt';
// SMT trees for 3 levels : // SMT trees for 3 levels :
// 1. Passport tree : level 3 (Absolute Match) // 1. Passport tree : level 3 (Absolute Match)
@@ -8,76 +8,77 @@ import { ChildNodes, SMT } from "@openpassport/zk-kit-smt"
// 3. Names tree : level 1 (Partial Match) // 3. Names tree : level 1 (Partial Match)
export function buildSMT(field: any[], treetype: string): [number, number, SMT] { export function buildSMT(field: any[], treetype: string): [number, number, SMT] {
let count = 0 let count = 0;
let startTime = performance.now(); let startTime = performance.now();
const hash2 = (childNodes: ChildNodes) => (childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes)) const hash2 = (childNodes: ChildNodes) =>
const tree = new SMT(hash2, true) childNodes.length === 2 ? poseidon2(childNodes) : poseidon3(childNodes);
const tree = new SMT(hash2, true);
for (let i = 0; i < field.length; i++) { for (let i = 0; i < field.length; i++) {
const entry = field[i] const entry = field[i];
if (i !== 0) { if (i !== 0) {
console.log('Processing', treetype, 'number', i, "out of", field.length); console.log('Processing', treetype, 'number', i, 'out of', field.length);
} }
let leaf = BigInt(0) let leaf = BigInt(0);
if (treetype == "passport") { if (treetype == 'passport') {
leaf = processPassport(entry.Pass_No, i) leaf = processPassport(entry.Pass_No, i);
} else if (treetype == "name_dob") { } else if (treetype == 'name_dob') {
leaf = processNameDob(entry, i) leaf = processNameDob(entry, i);
} else if (treetype == "name") { } else if (treetype == 'name') {
leaf = processName(entry.First_Name, entry.Last_Name, i) leaf = processName(entry.First_Name, entry.Last_Name, i);
} else if (treetype == "country") { } else if (treetype == 'country') {
const keys = Object.keys(entry); const keys = Object.keys(entry);
leaf = processCountry(keys[0], entry[keys[0]], i) leaf = processCountry(keys[0], entry[keys[0]], i);
} }
if (leaf == BigInt(0) || tree.createProof(leaf).membership) { if (leaf == BigInt(0) || tree.createProof(leaf).membership) {
console.log("This entry already exists in the tree, skipping...") console.log('This entry already exists in the tree, skipping...');
continue continue;
} }
count += 1 count += 1;
tree.add(leaf, BigInt(1)) tree.add(leaf, BigInt(1));
} }
console.log("Total", treetype, "paresed are : ", count, " over ", field.length) console.log('Total', treetype, 'paresed are : ', count, ' over ', field.length);
console.log(treetype, 'tree built in', performance.now() - startTime, 'ms') console.log(treetype, 'tree built in', performance.now() - startTime, 'ms');
return [count, performance.now() - startTime, tree] return [count, performance.now() - startTime, tree];
} }
function processPassport(passno: string, index: number): bigint { function processPassport(passno: string, index: number): bigint {
if (passno.length > 9) { if (passno.length > 9) {
console.log('passport length is greater than 9:', index, passno) console.log('passport length is greater than 9:', index, passno);
} else if (passno.length < 9) { } else if (passno.length < 9) {
while (passno.length != 9) { while (passno.length != 9) {
passno += '<' passno += '<';
} }
} }
const leaf = getPassportNumberLeaf(stringToAsciiBigIntArray(passno)) const leaf = getPassportNumberLeaf(stringToAsciiBigIntArray(passno));
if (!leaf) { if (!leaf) {
console.log('Error creating leaf value', index, passno) console.log('Error creating leaf value', index, passno);
return BigInt(0) return BigInt(0);
} }
return leaf return leaf;
} }
function processNameDob(entry: any, i: number): bigint { function processNameDob(entry: any, i: number): bigint {
const firstName = entry.First_Name const firstName = entry.First_Name;
const lastName = entry.Last_Name const lastName = entry.Last_Name;
const day = entry.day const day = entry.day;
const month = entry.month const month = entry.month;
const year = entry.year const year = entry.year;
if (day == null || month == null || year == null) { if (day == null || month == null || year == null) {
console.log('dob is null', i, entry) console.log('dob is null', i, entry);
return BigInt(0) return BigInt(0);
} }
const nameHash = processName(firstName, lastName, i) const nameHash = processName(firstName, lastName, i);
const dobHash = processDob(day, month, year, i) const dobHash = processDob(day, month, year, i);
const leaf = poseidon2([dobHash, nameHash]) const leaf = poseidon2([dobHash, nameHash]);
return leaf return leaf;
} }
function processName(firstName: string, lastName: string, i: number): bigint { function processName(firstName: string, lastName: string, i: number): bigint {
@@ -93,81 +94,89 @@ function processName(firstName: string, lastName: string, i: number): bigint {
// TODO : Handle special cases like malaysia : no two filler characters like << for surname and givenname // TODO : Handle special cases like malaysia : no two filler characters like << for surname and givenname
// TODO : Verify rules for . in names. eg : J. Doe (Done same as apostrophe for now) // TODO : Verify rules for . in names. eg : J. Doe (Done same as apostrophe for now)
let arr = lastName + '<<' + firstName let arr = lastName + '<<' + firstName;
if (arr.length > 39) { if (arr.length > 39) {
arr = arr.substring(0, 39) arr = arr.substring(0, 39);
} else { } else {
while (arr.length < 39) { while (arr.length < 39) {
arr += '<' arr += '<';
} }
} }
let nameArr = stringToAsciiBigIntArray(arr) let nameArr = stringToAsciiBigIntArray(arr);
return getNameLeaf(nameArr, i) return getNameLeaf(nameArr, i);
} }
function processDob(day: string, month: string, year: string, i: number): bigint { function processDob(day: string, month: string, year: string, i: number): bigint {
// YYMMDD // YYMMDD
const monthMap: { [key: string]: string } = { const monthMap: { [key: string]: string } = {
jan: "01", jan: '01',
feb: "02", feb: '02',
mar: "03", mar: '03',
apr: "04", apr: '04',
may: "05", may: '05',
jun: "06", jun: '06',
jul: "07", jul: '07',
aug: "08", aug: '08',
sep: "09", sep: '09',
oct: "10", oct: '10',
nov: "11", nov: '11',
dec: "12" dec: '12',
}; };
month = monthMap[month.toLowerCase()]; month = monthMap[month.toLowerCase()];
year = year.slice(-2); year = year.slice(-2);
const dob = year + month + day; const dob = year + month + day;
let arr = stringToAsciiBigIntArray(dob); let arr = stringToAsciiBigIntArray(dob);
return getDobLeaf(arr, i) return getDobLeaf(arr, i);
} }
function processCountry(country1: string, country2: string, i: number) { function processCountry(country1: string, country2: string, i: number) {
let arr = stringToAsciiBigIntArray(country1) let arr = stringToAsciiBigIntArray(country1);
let arr2 = stringToAsciiBigIntArray(country2) let arr2 = stringToAsciiBigIntArray(country2);
const leaf = getCountryLeaf(arr, arr2, i) const leaf = getCountryLeaf(arr, arr2, i);
if (!leaf) { if (!leaf) {
console.log('Error creating leaf value', i, country1, country2) console.log('Error creating leaf value', i, country1, country2);
return BigInt(0) return BigInt(0);
} }
return leaf return leaf;
} }
export function getCountryLeaf(country_by: (bigint | number)[], country_to: (bigint | number)[], i?: number): bigint { export function getCountryLeaf(
country_by: (bigint | number)[],
country_to: (bigint | number)[],
i?: number
): bigint {
if (country_by.length !== 3 || country_to.length !== 3) { if (country_by.length !== 3 || country_to.length !== 3) {
console.log('parsed passport length is not 3:', i, country_to, country_by) console.log('parsed passport length is not 3:', i, country_to, country_by);
return return;
} }
try { try {
const country = country_by.concat(country_to) const country = country_by.concat(country_to);
return poseidon6(country) return poseidon6(country);
} catch (err) { } catch (err) {
console.log('err : sanc_country hash', err, i, country_by, country_to) console.log('err : sanc_country hash', err, i, country_by, country_to);
} }
} }
export function getPassportNumberLeaf(passport: (bigint | number)[], i?: number): bigint { export function getPassportNumberLeaf(passport: (bigint | number)[], i?: number): bigint {
if (passport.length !== 9) { if (passport.length !== 9) {
console.log('parsed passport length is not 9:', i, passport) console.log('parsed passport length is not 9:', i, passport);
return return;
} }
try { try {
return poseidon9(passport) return poseidon9(passport);
} catch (err) { } catch (err) {
console.log('err : passport', err, i, passport) console.log('err : passport', err, i, passport);
} }
} }
export function getNameDobLeaf(nameMrz: (bigint | number)[], dobMrz: (bigint | number)[], i?: number): bigint { export function getNameDobLeaf(
return poseidon2([getDobLeaf(dobMrz), getNameLeaf(nameMrz)]) nameMrz: (bigint | number)[],
dobMrz: (bigint | number)[],
i?: number
): bigint {
return poseidon2([getDobLeaf(dobMrz), getNameLeaf(nameMrz)]);
} }
export function getNameLeaf(nameMrz: (bigint | number)[], i?: number): bigint { export function getNameLeaf(nameMrz: (bigint | number)[], i?: number): bigint {
@@ -177,24 +186,24 @@ export function getNameLeaf(nameMrz: (bigint | number)[], i?: number): bigint {
chunks.push(nameMrz.slice(0, 13), nameMrz.slice(13, 26), nameMrz.slice(26, 39)); // 39/3 for posedion to digest chunks.push(nameMrz.slice(0, 13), nameMrz.slice(13, 26), nameMrz.slice(26, 39)); // 39/3 for posedion to digest
for (const chunk of chunks) { for (const chunk of chunks) {
middleChunks.push(poseidon13(chunk)) middleChunks.push(poseidon13(chunk));
} }
try { try {
return poseidon3(middleChunks) return poseidon3(middleChunks);
} catch (err) { } catch (err) {
console.log('err : Name', err, i, nameMrz) console.log('err : Name', err, i, nameMrz);
} }
} }
export function getDobLeaf(dobMrz: (bigint | number)[], i?: number): bigint { export function getDobLeaf(dobMrz: (bigint | number)[], i?: number): bigint {
if (dobMrz.length !== 6) { if (dobMrz.length !== 6) {
console.log('parsed dob length is not 9:', i, dobMrz) console.log('parsed dob length is not 9:', i, dobMrz);
return return;
} }
try { try {
return poseidon6(dobMrz) return poseidon6(dobMrz);
} catch (err) { } catch (err) {
console.log('err : Dob', err, i, dobMrz) console.log('err : Dob', err, i, dobMrz);
} }
} }

View File

@@ -1,120 +1,154 @@
import { import {
PROVE_RSA_NULLIFIER_INDEX, PROVE_RSA_NULLIFIER_INDEX,
PROVE_RSA_REVEALED_DATA_PACKED_INDEX, PROVE_RSA_REVEALED_DATA_PACKED_INDEX,
PROVE_RSA_OLDER_THAN_INDEX, PROVE_RSA_OLDER_THAN_INDEX,
PROVE_RSA_PUBKEY_DISCLOSED_INDEX, PROVE_RSA_PUBKEY_DISCLOSED_INDEX,
PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX, PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX,
PROVE_RSA_OFAC_RESULT_INDEX, PROVE_RSA_OFAC_RESULT_INDEX,
PROVE_RSA_COMMITMENT_INDEX, PROVE_RSA_COMMITMENT_INDEX,
PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX, PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX,
PROVE_RSA_CURRENT_DATE_INDEX, PROVE_RSA_CURRENT_DATE_INDEX,
PROVE_RSA_USER_IDENTIFIER_INDEX, PROVE_RSA_USER_IDENTIFIER_INDEX,
PROVE_RSA_SCOPE_INDEX, PROVE_RSA_SCOPE_INDEX,
DSC_BLINDED_DSC_COMMITMENT_INDEX DSC_BLINDED_DSC_COMMITMENT_INDEX,
} from "../../constants/contractConstants"; } from '../../constants/contractConstants';
import { Proof } from "../types"; import { Proof } from '../types';
export function generateMockRSAProveVerifierInputs({ export function generateMockRSAProveVerifierInputs({
nullifier = "1", nullifier = '1',
revealedData_packed = ["2", "3", "4"], revealedData_packed = ['2', '3', '4'],
older_than = ["49", "56"], older_than = ['49', '56'],
pubkey_disclosed = ["0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0","0", "0", "0", "0"], pubkey_disclosed = [
forbidden_contries_list_packed_disclose = ["8", "9"], '0',
ofac_result = "10", '0',
commitment = "11", '0',
blinded_dsc_commitment = "12", '0',
current_date = new Date(), '0',
user_identifier = "13", '0',
scope = "14", '0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
],
forbidden_contries_list_packed_disclose = ['8', '9'],
ofac_result = '10',
commitment = '11',
blinded_dsc_commitment = '12',
current_date = new Date(),
user_identifier = '13',
scope = '14',
}: { }: {
nullifier?: string, nullifier?: string;
revealedData_packed?: string[], revealedData_packed?: string[];
older_than?: string[], older_than?: string[];
pubkey_disclosed?: string[], pubkey_disclosed?: string[];
forbidden_contries_list_packed_disclose?: string[], forbidden_contries_list_packed_disclose?: string[];
ofac_result?: string, ofac_result?: string;
commitment?: string, commitment?: string;
blinded_dsc_commitment?: string, blinded_dsc_commitment?: string;
current_date?: Date, current_date?: Date;
user_identifier?: string, user_identifier?: string;
scope?: string, scope?: string;
}): Proof { }): Proof {
let pub_signals: string[] = [];
let pub_signals: string[] = []; pub_signals[PROVE_RSA_NULLIFIER_INDEX] = nullifier;
pub_signals.splice(PROVE_RSA_REVEALED_DATA_PACKED_INDEX, 0, ...revealedData_packed);
pub_signals[PROVE_RSA_NULLIFIER_INDEX] = nullifier; pub_signals.splice(PROVE_RSA_OLDER_THAN_INDEX, 0, ...older_than);
pub_signals.splice(PROVE_RSA_REVEALED_DATA_PACKED_INDEX, 0, ...revealedData_packed); pub_signals.splice(PROVE_RSA_PUBKEY_DISCLOSED_INDEX, 0, ...pubkey_disclosed);
pub_signals.splice(PROVE_RSA_OLDER_THAN_INDEX, 0, ...older_than); pub_signals.splice(
pub_signals.splice(PROVE_RSA_PUBKEY_DISCLOSED_INDEX, 0, ...pubkey_disclosed); PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX,
pub_signals.splice(PROVE_RSA_FORBIDDEN_COUNTRIES_LIST_PACKED_DISCLOSED_INDEX, 0, ...forbidden_contries_list_packed_disclose); 0,
pub_signals[PROVE_RSA_OFAC_RESULT_INDEX] = ofac_result; ...forbidden_contries_list_packed_disclose
pub_signals[PROVE_RSA_COMMITMENT_INDEX] = commitment; );
pub_signals[PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment; pub_signals[PROVE_RSA_OFAC_RESULT_INDEX] = ofac_result;
pub_signals.splice(PROVE_RSA_CURRENT_DATE_INDEX, 0, ...getDateNum(current_date)); pub_signals[PROVE_RSA_COMMITMENT_INDEX] = commitment;
pub_signals[PROVE_RSA_USER_IDENTIFIER_INDEX] = user_identifier; pub_signals[PROVE_RSA_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment;
pub_signals[PROVE_RSA_SCOPE_INDEX] = scope; pub_signals.splice(PROVE_RSA_CURRENT_DATE_INDEX, 0, ...getDateNum(current_date));
pub_signals[PROVE_RSA_USER_IDENTIFIER_INDEX] = user_identifier;
pub_signals[PROVE_RSA_SCOPE_INDEX] = scope;
let proof: Proof = { let proof: Proof = {
proof: { proof: {
a: ["1", "1"], a: ['1', '1'],
b: [ b: [
["1", "2"], ['1', '2'],
["3", "4"] ['3', '4'],
], ],
c: ["5", "6"] c: ['5', '6'],
}, },
pub_signals: pub_signals pub_signals: pub_signals,
}; };
return proof; return proof;
} }
export function generateMockDSCVerifierInputs({ export function generateMockDSCVerifierInputs({
blinded_dsc_commitment = "12", blinded_dsc_commitment = '12',
}: { }: {
blinded_dsc_commitment?: string, blinded_dsc_commitment?: string;
}): Proof { }): Proof {
let pub_signals: string[] = [];
let pub_signals: string[] = []; pub_signals[DSC_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment;
pub_signals[DSC_BLINDED_DSC_COMMITMENT_INDEX] = blinded_dsc_commitment;
let proof: Proof = { let proof: Proof = {
proof: { proof: {
a: ["1", "1"], a: ['1', '1'],
b: [ b: [
["1", "2"], ['1', '2'],
["3", "4"] ['3', '4'],
], ],
c: ["5", "6"] c: ['5', '6'],
}, },
pub_signals: pub_signals pub_signals: pub_signals,
}; };
return proof; return proof;
} }
function getDateNum(date: Date = new Date()): string[] { function getDateNum(date: Date = new Date()): string[] {
const year = date.getUTCFullYear() % 100;
const month = date.getUTCMonth() + 1;
const day = date.getUTCDate();
const year = date.getUTCFullYear() % 100; const dateNum = [
const month = date.getUTCMonth() + 1; Math.floor(year / 10),
const day = date.getUTCDate(); year % 10,
Math.floor(month / 10),
month % 10,
Math.floor(day / 10),
day % 10,
];
const dateNum = [ return dateNum.map((num) => num.toString());
Math.floor(year / 10),
(year % 10),
(Math.floor(month / 10)),
(month % 10),
(Math.floor(day / 10)),
(day % 10),
];
return dateNum.map(num => num.toString());
} }
export function convertProofTypeIntoInput(proof: Proof) { export function convertProofTypeIntoInput(proof: Proof) {
return { return {
a: proof.proof.a, a: proof.proof.a,
b: proof.proof.b, b: proof.proof.b,
c: proof.proof.c, c: proof.proof.c,
pubSignals: proof.pub_signals pubSignals: proof.pub_signals,
} };
} }

View File

@@ -10,25 +10,33 @@ export type PassportData = {
}; };
// Define the signature algorithm in "algorithm_hashfunction_domainPapameter_keyLength" // Define the signature algorithm in "algorithm_hashfunction_domainPapameter_keyLength"
export type SignatureAlgorithm = 'rsa_sha1_65537_2048' | 'rsa_sha256_65537_2048' | 'rsapss_sha256_65537_2048' | 'ecdsa_sha256_secp256r1_256' | 'ecdsa_sha1_secp256r1_256' | 'ecdsa_sha384_secp384r1_384' | 'ecdsa_sha256_brainpoolP256r1_256' | 'rsa_sha256_3_2048' | 'rsa_sha256_65537_3072'; export type SignatureAlgorithm =
| 'rsa_sha1_65537_2048'
| 'rsa_sha256_65537_2048'
| 'rsapss_sha256_65537_2048'
| 'ecdsa_sha256_secp256r1_256'
| 'ecdsa_sha1_secp256r1_256'
| 'ecdsa_sha384_secp384r1_384'
| 'ecdsa_sha256_brainpoolP256r1_256'
| 'rsa_sha256_3_2048'
| 'rsa_sha256_65537_3072';
export type Proof = { export type Proof = {
proof: { proof: {
a: [string, string], a: [string, string];
b: [[string, string], [string, string]], b: [[string, string], [string, string]];
c: [string, string] c: [string, string];
}; };
pub_signals: string[]; pub_signals: string[];
} };
export function castCSCAProof(proof: any): Proof { export function castCSCAProof(proof: any): Proof {
return { return {
proof: { proof: {
a: proof.proof.pi_a.slice(0, 2), a: proof.proof.pi_a.slice(0, 2),
b: [proof.proof.pi_b[0].slice(0, 2), proof.proof.pi_b[1].slice(0, 2)], b: [proof.proof.pi_b[0].slice(0, 2), proof.proof.pi_b[1].slice(0, 2)],
c: proof.proof.pi_c.slice(0, 2) c: proof.proof.pi_c.slice(0, 2),
}, },
pub_signals: proof.pub_signals pub_signals: proof.pub_signals,
} };
} }

View File

@@ -4,7 +4,16 @@ import { sha1 } from 'js-sha1';
import { sha384, sha512_256 } from 'js-sha512'; import { sha384, sha512_256 } from 'js-sha512';
import { SMT } from '@openpassport/zk-kit-smt'; import { SMT } from '@openpassport/zk-kit-smt';
import forge from 'node-forge'; import forge from 'node-forge';
import { n_dsc, k_dsc, k_dsc_3072, n_dsc_ecdsa, k_dsc_ecdsa, n_csca, k_csca, attributeToPosition } from '../constants/constants'; import {
n_dsc,
k_dsc,
k_dsc_3072,
n_dsc_ecdsa,
k_dsc_ecdsa,
n_csca,
k_csca,
attributeToPosition,
} from '../constants/constants';
import { unpackReveal } from './revealBitmap'; import { unpackReveal } from './revealBitmap';
import { SignatureAlgorithm } from './types'; import { SignatureAlgorithm } from './types';
@@ -21,18 +30,18 @@ export function formatMrz(mrz: string) {
export function getNAndK(sigAlg: SignatureAlgorithm) { export function getNAndK(sigAlg: SignatureAlgorithm) {
if (sigAlg === 'rsa_sha256_65537_3072') { if (sigAlg === 'rsa_sha256_65537_3072') {
return { n: n_dsc, k: k_dsc_3072 }; // 3072/32 = 96 return { n: n_dsc, k: k_dsc_3072 }; // 3072/32 = 96
} }
if (sigAlg.startsWith('ecdsa_')) { if (sigAlg.startsWith('ecdsa_')) {
return { n: n_dsc_ecdsa, k: k_dsc_ecdsa }; // 256/32 = 8 return { n: n_dsc_ecdsa, k: k_dsc_ecdsa }; // 256/32 = 8
} }
if (sigAlg.startsWith('rsapss_')) { if (sigAlg.startsWith('rsapss_')) {
return { n: n_dsc, k: k_dsc }; // 2048/32 = 64 return { n: n_dsc, k: k_dsc }; // 2048/32 = 64
} }
return { n: n_dsc, k: k_dsc }; // 2048/32 = 64 return { n: n_dsc, k: k_dsc }; // 2048/32 = 64
} }
export function getNAndKCSCA(sigAlg: 'rsa' | 'ecdsa' | 'rsapss') { export function getNAndKCSCA(sigAlg: 'rsa' | 'ecdsa' | 'rsapss') {
@@ -43,7 +52,8 @@ export function getNAndKCSCA(sigAlg: 'rsa' | 'ecdsa' | 'rsapss') {
export function formatDg2Hash(dg2Hash: number[]) { export function formatDg2Hash(dg2Hash: number[]) {
const unsignedBytesDg2Hash = dg2Hash.map((x) => toUnsignedByte(x)); const unsignedBytesDg2Hash = dg2Hash.map((x) => toUnsignedByte(x));
while (unsignedBytesDg2Hash.length < 64) { // pad it to 64 bytes to correspond to the hash length of sha512 and avoid multiplying circuits while (unsignedBytesDg2Hash.length < 64) {
// pad it to 64 bytes to correspond to the hash length of sha512 and avoid multiplying circuits
unsignedBytesDg2Hash.push(0); unsignedBytesDg2Hash.push(0);
} }
return unsignedBytesDg2Hash; return unsignedBytesDg2Hash;
@@ -102,13 +112,13 @@ export function formatAndConcatenateDataHashes(
// spain // spain
// 48, -127, -79, // 48, -127, -79,
// 2, 1, // 2, 1,
// 0, // 0,
// 48, 7, 6, 5, // 48, 7, 6, 5,
// 1.3.14.3.2.26 is sha1 // 1.3.14.3.2.26 is sha1
// 43, 14, 3, 2, 26, // 43, 14, 3, 2, 26,
// SEQUENCE + ... // SEQUENCE + ...
// 48, -127, -94, // 48, -127, -94,
// => current conclusion is we should be able to just hardcode indexes // => current conclusion is we should be able to just hardcode indexes
// => as they shouldn't change must for same sig alg. // => as they shouldn't change must for same sig alg.
@@ -316,34 +326,35 @@ export function packBytes(unpacked) {
export function generateSMTProof(smt: SMT, leaf: bigint) { export function generateSMTProof(smt: SMT, leaf: bigint) {
const { entry, matchingEntry, siblings, root, membership } = smt.createProof(leaf); const { entry, matchingEntry, siblings, root, membership } = smt.createProof(leaf);
const depth = siblings.length const depth = siblings.length;
let closestleaf; let closestleaf;
if (!matchingEntry) { // we got the 0 leaf or membership if (!matchingEntry) {
// we got the 0 leaf or membership
// then check if entry[1] exists // then check if entry[1] exists
if (!entry[1]) { if (!entry[1]) {
// non membership proof // non membership proof
closestleaf = BigInt(0); // 0 leaf closestleaf = BigInt(0); // 0 leaf
} else { } else {
closestleaf = BigInt(entry[0]); // leaf itself (memb proof) closestleaf = BigInt(entry[0]); // leaf itself (memb proof)
} }
} else { } else {
// non membership proof // non membership proof
closestleaf = BigInt(matchingEntry[0]); // actual closest closestleaf = BigInt(matchingEntry[0]); // actual closest
} }
// PATH, SIBLINGS manipulation as per binary tree in the circuit // PATH, SIBLINGS manipulation as per binary tree in the circuit
siblings.reverse() siblings.reverse();
while (siblings.length < 256) siblings.push(BigInt(0)); while (siblings.length < 256) siblings.push(BigInt(0));
// ----- Useful for debugging hence leaving as comments ----- // ----- Useful for debugging hence leaving as comments -----
// const binary = entry[0].toString(2) // const binary = entry[0].toString(2)
// const bits = binary.slice(-depth); // const bits = binary.slice(-depth);
// let indices = bits.padEnd(256, "0").split("").map(Number) // let indices = bits.padEnd(256, "0").split("").map(Number)
// const pathToMatch = num2Bits(256,BigInt(entry[0])) // const pathToMatch = num2Bits(256,BigInt(entry[0]))
// while(indices.length < 256) indices.push(0); // while(indices.length < 256) indices.push(0);
// // CALCULATED ROOT FOR TESTING // // CALCULATED ROOT FOR TESTING
// // closestleaf, depth, siblings, indices, root : needed // // closestleaf, depth, siblings, indices, root : needed
// let calculatedNode = poseidon3([closestleaf,1,1]); // let calculatedNode = poseidon3([closestleaf,1,1]);
// console.log("Initial node while calculating",calculatedNode) // console.log("Initial node while calculating",calculatedNode)
// console.log(smt.verifyProof(smt.createProof(leaf))) // console.log(smt.verifyProof(smt.createProof(leaf)))
@@ -413,7 +424,7 @@ function hexToBigInt(hex: string): bigint {
function checkBigInt(bigInt: bigint) { function checkBigInt(bigInt: bigint) {
const max253BitValue = BigInt(2n ** 253n - 1n); const max253BitValue = BigInt(2n ** 253n - 1n);
if (bigInt > max253BitValue) { if (bigInt > max253BitValue) {
throw new Error("Input should be < 2^253 - 1"); throw new Error('Input should be < 2^253 - 1');
} }
} }
@@ -445,14 +456,17 @@ export function castToUUID(bigInt: bigint): string {
/// scope /// scope
function checkStringLength(str: string) { function checkStringLength(str: string) {
if (str.length > 25) { if (str.length > 25) {
throw new Error("Input string must not exceed 25 characters"); throw new Error('Input string must not exceed 25 characters');
} }
} }
function stringToBigInt(str: string): bigint { function stringToBigInt(str: string): bigint {
return BigInt('1' + Array.from(str) return BigInt(
.map(char => char.charCodeAt(0).toString().padStart(3, '0')) '1' +
.join('')); Array.from(str)
.map((char) => char.charCodeAt(0).toString().padStart(3, '0'))
.join('')
);
} }
export function castFromScope(scope: string): string { export function castFromScope(scope: string): string {
@@ -463,7 +477,7 @@ export function castFromScope(scope: string): string {
export function castToScope(num: bigint): string { export function castToScope(num: bigint): string {
const str = num.toString().slice(1); // Remove leading '1' const str = num.toString().slice(1); // Remove leading '1'
const charCodes = str.match(/.{1,3}/g) || []; const charCodes = str.match(/.{1,3}/g) || [];
return String.fromCharCode(...charCodes.map(code => parseInt(code, 10))); return String.fromCharCode(...charCodes.map((code) => parseInt(code, 10)));
} }
export function stringToAsciiBigIntArray(str: string): bigint[] { export function stringToAsciiBigIntArray(str: string): bigint[] {
@@ -475,11 +489,11 @@ export function stringToAsciiBigIntArray(str: string): bigint[] {
} }
export function hexToBin(n: string): string { export function hexToBin(n: string): string {
let bin = Number(`0x${n[0]}`).toString(2) let bin = Number(`0x${n[0]}`).toString(2);
for (let i = 1; i < n.length; i += 1) { for (let i = 1; i < n.length; i += 1) {
bin += Number(`0x${n[i]}`).toString(2).padStart(4, "0") bin += Number(`0x${n[i]}`).toString(2).padStart(4, '0');
} }
return bin return bin;
} }
export function num2Bits(n: number, inValue: bigint): bigint[] { export function num2Bits(n: number, inValue: bigint): bigint[] {
@@ -491,7 +505,7 @@ export function num2Bits(n: number, inValue: bigint): bigint[] {
out[i] = (inValue >> BigInt(i)) & BigInt(1); out[i] = (inValue >> BigInt(i)) & BigInt(1);
if (out[i] !== BigInt(0) && out[i] !== BigInt(1)) { if (out[i] !== BigInt(0) && out[i] !== BigInt(1)) {
throw new Error("Bit value is not binary."); throw new Error('Bit value is not binary.');
} }
lc1 += out[i] * e2; lc1 += out[i] * e2;
@@ -499,7 +513,7 @@ export function num2Bits(n: number, inValue: bigint): bigint[] {
} }
if (lc1 !== inValue) { if (lc1 !== inValue) {
throw new Error("Reconstructed value does not match the input."); throw new Error('Reconstructed value does not match the input.');
} }
return out; return out;
} }
@@ -515,11 +529,13 @@ const validateUserId = (userId: string, type: UserIdType): boolean => {
case 'hex': case 'hex':
return /^[0-9A-Fa-f]+$/.test(userId); return /^[0-9A-Fa-f]+$/.test(userId);
case 'uuid': case 'uuid':
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(userId); return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
userId
);
default: default:
return false; return false;
} }
} };
const getMaxLenght = (idType: UserIdType) => { const getMaxLenght = (idType: UserIdType) => {
switch (idType) { switch (idType) {
@@ -528,16 +544,21 @@ const getMaxLenght = (idType: UserIdType) => {
default: default:
return 63; return 63;
} }
} };
export const parseUIDToBigInt = (user_identifier: string, user_identifier_type: UserIdType): string => { export const parseUIDToBigInt = (
user_identifier: string,
user_identifier_type: UserIdType
): string => {
if (!validateUserId(user_identifier, user_identifier_type)) { if (!validateUserId(user_identifier, user_identifier_type)) {
throw new Error(`User identifier of type ${user_identifier_type} is not valid`); throw new Error(`User identifier of type ${user_identifier_type} is not valid`);
} }
const maxLength = getMaxLenght(user_identifier_type); const maxLength = getMaxLenght(user_identifier_type);
if (user_identifier.length > maxLength) { if (user_identifier.length > maxLength) {
throw new Error(`User identifier of type ${user_identifier_type} exceeds maximum length of ${maxLength} characters`); throw new Error(
`User identifier of type ${user_identifier_type} exceeds maximum length of ${maxLength} characters`
);
} }
switch (user_identifier_type) { switch (user_identifier_type) {
@@ -548,21 +569,23 @@ export const parseUIDToBigInt = (user_identifier: string, user_identifier_type:
case 'uuid': case 'uuid':
return uuidToBigInt(user_identifier).toString(); return uuidToBigInt(user_identifier).toString();
} }
} };
export function formatCountriesList(countries: string[]) { export function formatCountriesList(countries: string[]) {
if (countries.length > 20) { if (countries.length > 20) {
throw new Error("Countries list must be inferior or equals to 20"); throw new Error('Countries list must be inferior or equals to 20');
} }
const paddedCountries = countries.concat(Array(20 - countries.length).fill('')); const paddedCountries = countries.concat(Array(20 - countries.length).fill(''));
const result = paddedCountries.flatMap(country => { const result = paddedCountries.flatMap((country) => {
const chars = country.padEnd(3, '\0').split('').map(char => char.charCodeAt(0)); const chars = country
.padEnd(3, '\0')
.split('')
.map((char) => char.charCodeAt(0));
return chars; return chars;
}); });
return result; return result;
} }
export function getAttributeFromUnpackedReveal(unpackedReveal: string[], attribute: string) { export function getAttributeFromUnpackedReveal(unpackedReveal: string[], attribute: string) {
const position = attributeToPosition[attribute]; const position = attributeToPosition[attribute];
let attributeValue = ''; let attributeValue = '';
@@ -574,12 +597,14 @@ export function getAttributeFromUnpackedReveal(unpackedReveal: string[], attribu
return attributeValue; return attributeValue;
} }
export function formatForbiddenCountriesListFromCircuitOutput(forbiddenCountriesList: string[]): string[] { export function formatForbiddenCountriesListFromCircuitOutput(
forbiddenCountriesList: string[]
): string[] {
const countryList1 = unpackReveal(forbiddenCountriesList[0]); const countryList1 = unpackReveal(forbiddenCountriesList[0]);
const countryList2 = unpackReveal(forbiddenCountriesList[1]); const countryList2 = unpackReveal(forbiddenCountriesList[1]);
const concatenatedCountryList = countryList1.concat(countryList2); const concatenatedCountryList = countryList1.concat(countryList2);
// dump every '\x00' value from the list // dump every '\x00' value from the list
const cleanedCountryList = concatenatedCountryList.filter(value => value !== '\x00'); const cleanedCountryList = concatenatedCountryList.filter((value) => value !== '\x00');
// Concatenate every 3 elements to form country codes // Concatenate every 3 elements to form country codes
const formattedCountryList = []; const formattedCountryList = [];
for (let i = 0; i < cleanedCountryList.length; i += 3) { for (let i = 0; i < cleanedCountryList.length; i += 3) {
@@ -592,7 +617,7 @@ export function formatForbiddenCountriesListFromCircuitOutput(forbiddenCountries
} }
export function getOlderThanFromCircuitOutput(olderThan: string[]): number { export function getOlderThanFromCircuitOutput(olderThan: string[]): number {
const ageString = olderThan.map(code => String.fromCharCode(parseInt(code))).join(''); const ageString = olderThan.map((code) => String.fromCharCode(parseInt(code))).join('');
const age = parseInt(ageString, 10); const age = parseInt(ageString, 10);
return isNaN(age) ? 0 : age; return isNaN(age) ? 0 : age;
} }

View File

@@ -10,18 +10,18 @@ import { Certificate } from 'pkijs';
import elliptic from 'elliptic'; import elliptic from 'elliptic';
const sigAlgs: SignatureAlgorithm[] = [ const sigAlgs: SignatureAlgorithm[] = [
'rsa_sha1', 'rsa_sha1_65537_2048',
'rsa_sha256', 'rsa_sha256_65537_2048',
'rsapss_sha256', 'rsapss_sha256_65537_2048',
'ecdsa_sha256', 'ecdsa_sha256_secp256r1_256',
'ecdsa_sha1', 'ecdsa_sha1_secp256r1_256',
'ecdsa_sha384', // 'ecdsa_sha384_secp384r1_384',
]; ];
describe('Mock Passport Data Generator', function () { describe('Mock Passport Data Generator', function () {
this.timeout(0); this.timeout(0);
sigAlgs.forEach(sigAlg => { sigAlgs.forEach((sigAlg) => {
it(`should generate valid passport data for ${sigAlg}`, () => { it(`should generate valid passport data for ${sigAlg}`, () => {
const passportData = genMockPassportData(sigAlg, 'FRA', '000101', '300101'); const passportData = genMockPassportData(sigAlg, 'FRA', '000101', '300101');
expect(passportData).to.exist; expect(passportData).to.exist;
@@ -35,20 +35,31 @@ function verify(passportData: PassportData): boolean {
const { signatureAlgorithm, hashFunction, hashLen, curve } = parseCertificate(dsc); const { signatureAlgorithm, hashFunction, hashLen, curve } = parseCertificate(dsc);
const formattedMrz = formatMrz(mrz); const formattedMrz = formatMrz(mrz);
const mrzHash = hash(hashFunction, formattedMrz); const mrzHash = hash(hashFunction, formattedMrz);
const dg1HashOffset = findSubarrayIndex(eContent, mrzHash) const dg1HashOffset = findSubarrayIndex(eContent, mrzHash);
assert(dg1HashOffset !== -1, 'MRZ hash index not found in eContent'); assert(dg1HashOffset !== -1, 'MRZ hash index not found in eContent');
console.error("\x1b[32m", "signatureAlgorithm", signatureAlgorithm, " hashFunction", hashFunction, "eContent size", eContent.length, "signedAttr size", signedAttr.length, "\x1b[0m"); console.error(
const concatHash = hash(hashFunction, eContent) '\x1b[32m',
'signatureAlgorithm',
signatureAlgorithm,
' hashFunction',
hashFunction,
'eContent size',
eContent.length,
'signedAttr size',
signedAttr.length,
'\x1b[0m'
);
const concatHash = hash(hashFunction, eContent);
assert( assert(
arraysAreEqual( arraysAreEqual(concatHash, signedAttr.slice(signedAttr.length - hashLen)),
concatHash,
signedAttr.slice(signedAttr.length - hashLen)
),
'concatHash is not at the right place in signedAttr' 'concatHash is not at the right place in signedAttr'
); );
if (signatureAlgorithm === 'ecdsa') { if (signatureAlgorithm === 'ecdsa') {
const certBuffer = Buffer.from(dsc.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''), 'base64'); const certBuffer = Buffer.from(
dsc.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''),
'base64'
);
const asn1Data = asn1.fromBER(certBuffer); const asn1Data = asn1.fromBER(certBuffer);
const cert = new Certificate({ schema: asn1Data.result }); const cert = new Certificate({ schema: asn1Data.result });
const publicKeyInfo = cert.subjectPublicKeyInfo; const publicKeyInfo = cert.subjectPublicKeyInfo;
@@ -59,7 +70,7 @@ function verify(passportData: PassportData): boolean {
const key = ec.keyFromPublic(publicKeyBuffer); const key = ec.keyFromPublic(publicKeyBuffer);
const md = hashFunction === 'sha1' ? forge.md.sha1.create() : forge.md.sha256.create(); const md = hashFunction === 'sha1' ? forge.md.sha1.create() : forge.md.sha256.create();
md.update(forge.util.binary.raw.encode(new Uint8Array(signedAttr))); md.update(forge.util.binary.raw.encode(new Uint8Array(signedAttr)));
const msgHash = md.digest().toHex() const msgHash = md.digest().toHex();
const signature_crypto = Buffer.from(encryptedDigest).toString('hex'); const signature_crypto = Buffer.from(encryptedDigest).toString('hex');
return key.verify(msgHash, signature_crypto); return key.verify(msgHash, signature_crypto);
@@ -76,7 +87,7 @@ function verify(passportData: PassportData): boolean {
const pss = forge.pss.create({ const pss = forge.pss.create({
md: forge.md[hashFunction].create(), md: forge.md[hashFunction].create(),
mgf: forge.mgf.mgf1.create(forge.md[hashFunction].create()), mgf: forge.mgf.mgf1.create(forge.md[hashFunction].create()),
saltLength: hashLen saltLength: hashLen,
}); });
return publicKey.verify(md.digest().bytes(), signature, pss); return publicKey.verify(md.digest().bytes(), signature, pss);
} else { } else {

View File

@@ -5,4 +5,4 @@
"target": "ES2020", "target": "ES2020",
"moduleResolution": "node" "moduleResolution": "node"
} }
} }