mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
fix common test
This commit is contained in:
@@ -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
@@ -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
@@ -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}"
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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-----`;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -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],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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') {
|
||||||
|
|||||||
@@ -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()];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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],
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -5,4 +5,4 @@
|
|||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"moduleResolution": "node"
|
"moduleResolution": "node"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user