mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
add eu id support (#527)
* add eu id support * add ofac and disclosure euid support * add contract support for euid cards --------- Co-authored-by: motemotech <i.am.nicoshark@gmail.com>
This commit is contained in:
committed by
GitHub
parent
8351609046
commit
5d01e29bf4
@@ -156,7 +156,7 @@ describe('Disclose', function () {
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
|
||||
for (let i = 0; i < 88; i++) {
|
||||
if (selector_dg1[i] == '1') {
|
||||
@@ -187,8 +187,8 @@ describe('Disclose', function () {
|
||||
});
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const older_than = getAttributeFromUnpackedReveal(reveal_unpacked, 'older_than');
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
const older_than = getAttributeFromUnpackedReveal(reveal_unpacked, 'older_than', 'passport');
|
||||
expect(older_than).to.equal('18');
|
||||
});
|
||||
|
||||
@@ -203,7 +203,7 @@ describe('Disclose', function () {
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
expect(reveal_unpacked[88]).to.equal('\x00');
|
||||
expect(reveal_unpacked[89]).to.equal('\x00');
|
||||
});
|
||||
@@ -213,7 +213,7 @@ describe('Disclose', function () {
|
||||
w = await circuit.calculateWitness(inputs);
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
|
||||
console.log('reveal_unpacked', reveal_unpacked);
|
||||
// OFAC result is stored at index 90 in the revealed data
|
||||
@@ -235,7 +235,7 @@ describe('Disclose', function () {
|
||||
});
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
|
||||
// OFAC result should be hidden (null byte)
|
||||
const ofac_result = reveal_unpacked[90];
|
||||
@@ -382,7 +382,7 @@ describe('Disclose', function () {
|
||||
|
||||
w = await circuit.calculateWitness(testInputs);
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[3]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'passport');
|
||||
const ofac_results = reveal_unpacked.slice(90, 93);
|
||||
|
||||
console.log(`${testCase.desc} - OFAC bits:`, ofac_results);
|
||||
|
||||
297
circuits/tests/disclose/vc_and_disclose_id.test.ts
Normal file
297
circuits/tests/disclose/vc_and_disclose_id.test.ts
Normal file
@@ -0,0 +1,297 @@
|
||||
import { describe } from 'mocha';
|
||||
import { assert, expect } from 'chai';
|
||||
import path from 'path';
|
||||
import { wasm as wasm_tester } from 'circom_tester';
|
||||
import {
|
||||
attributeToPosition_ID,
|
||||
ID_CARD_ATTESTATION_ID
|
||||
} from '../../../common/src/constants/constants';
|
||||
import { poseidon1, poseidon2 } from 'poseidon-lite';
|
||||
import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
|
||||
import { generateCircuitInputsVCandDisclose } from '../../../common/src/utils/circuits/generateInputs';
|
||||
import crypto from 'crypto';
|
||||
import { SMT } from '@openpassport/zk-kit-smt';
|
||||
import nameAndDobjson from '../../../common/ofacdata/outputs/nameAndDobSMT_ID.json';
|
||||
import nameAndYobjson from '../../../common/ofacdata/outputs/nameAndYobSMT_ID.json';
|
||||
import passportNojson from '../../../common/ofacdata/outputs/passportNoAndNationalitySMT.json';
|
||||
import {
|
||||
formatAndUnpackForbiddenCountriesList,
|
||||
formatAndUnpackReveal,
|
||||
getAttributeFromUnpackedReveal,
|
||||
} from '../../../common/src/utils/circuits/formatOutputs';
|
||||
import { generateCommitment } from '../../../common/src/utils/passports/passport';
|
||||
import { hashEndpointWithScope } from '../../../common/src/utils/scope';
|
||||
import { genMockIdDoc } from '../../../common/src/utils/passports/genMockIdDoc';
|
||||
|
||||
describe('Disclose', function () {
|
||||
this.timeout(0);
|
||||
let inputs: any;
|
||||
let circuit: any;
|
||||
let w: any;
|
||||
const passportData = genMockIdDoc({
|
||||
idType: 'mock_id_card'
|
||||
});
|
||||
console.log(passportData.mrz);
|
||||
const forbidden_countries_list = ['ALG', 'DZA'];
|
||||
|
||||
const secret = BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString();
|
||||
const majority = '18';
|
||||
const user_identifier = crypto.randomUUID();
|
||||
const selector_dg1 = Array(90).fill('1');
|
||||
const selector_older_than = '1';
|
||||
const endpoint = 'https://example.com';
|
||||
const scope = 'scope';
|
||||
const fullScope = hashEndpointWithScope(endpoint, scope);
|
||||
const attestation_id = ID_CARD_ATTESTATION_ID;
|
||||
|
||||
// compute the commitment and insert it in the tree
|
||||
const commitment = generateCommitment(secret, attestation_id, passportData);
|
||||
console.log('commitment in js ', commitment);
|
||||
const tree: any = new LeanIMT((a, b) => poseidon2([a, b]), []);
|
||||
tree.insert(BigInt(commitment));
|
||||
|
||||
const passportNo_smt = new SMT(poseidon2, true);
|
||||
passportNo_smt.import(passportNojson);
|
||||
|
||||
const nameAndDob_smt = new SMT(poseidon2, true);
|
||||
nameAndDob_smt.import(nameAndDobjson);
|
||||
|
||||
const nameAndYob_smt = new SMT(poseidon2, true);
|
||||
nameAndYob_smt.import(nameAndYobjson);
|
||||
|
||||
const selector_ofac = 1;
|
||||
|
||||
before(async () => {
|
||||
circuit = await wasm_tester(
|
||||
path.join(__dirname, '../../circuits/disclose/vc_and_disclose_id.circom'),
|
||||
{
|
||||
include: [
|
||||
'node_modules',
|
||||
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
|
||||
'./node_modules/circomlib/circuits',
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
inputs = generateCircuitInputsVCandDisclose(
|
||||
secret,
|
||||
ID_CARD_ATTESTATION_ID,
|
||||
passportData,
|
||||
fullScope,
|
||||
selector_dg1,
|
||||
selector_older_than,
|
||||
tree,
|
||||
majority,
|
||||
passportNo_smt,
|
||||
nameAndDob_smt,
|
||||
nameAndYob_smt,
|
||||
selector_ofac,
|
||||
forbidden_countries_list,
|
||||
user_identifier
|
||||
);
|
||||
});
|
||||
|
||||
// it('should compile and load the circuit', async function () {
|
||||
// expect(circuit).to.not.be.undefined;
|
||||
// });
|
||||
|
||||
it('should have nullifier == poseidon(secret, scope)', async function () {
|
||||
w = await circuit.calculateWitness(inputs);
|
||||
const nullifier_js = poseidon2([inputs.secret, inputs.scope]).toString();
|
||||
const nullifier_circom = (await circuit.getOutput(w, ['nullifier'])).nullifier;
|
||||
|
||||
console.log('nullifier_circom', nullifier_circom);
|
||||
console.log('nullifier_js', nullifier_js);
|
||||
expect(nullifier_circom).to.equal(nullifier_js);
|
||||
});
|
||||
|
||||
|
||||
describe('MRZ selective disclosure', function () {
|
||||
const attributeCombinations = [
|
||||
['issuing_state', 'name'],
|
||||
['passport_number', 'nationality', 'date_of_birth'],
|
||||
['gender', 'expiry_date'],
|
||||
];
|
||||
|
||||
attributeCombinations.forEach((combination) => {
|
||||
it(`Disclosing ${combination.join(', ')}`, async function () {
|
||||
const attributeToReveal = Object.keys(attributeToPosition_ID).reduce((acc, attribute) => {
|
||||
acc[attribute] = combination.includes(attribute);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const selector_dg1 = Array(90).fill('0');
|
||||
|
||||
Object.entries(attributeToReveal).forEach(([attribute, reveal]) => {
|
||||
if (reveal) {
|
||||
const [start, end] = attributeToPosition_ID[attribute];
|
||||
selector_dg1.fill('1', start, end + 1);
|
||||
}
|
||||
});
|
||||
|
||||
inputs = {
|
||||
...inputs,
|
||||
selector_dg1: selector_dg1.map(String),
|
||||
};
|
||||
|
||||
w = await circuit.calculateWitness(inputs);
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
|
||||
for (let i = 0; i < 88; i++) {
|
||||
if (selector_dg1[i] == '1') {
|
||||
const char = String.fromCharCode(Number(inputs.dg1[i + 5]));
|
||||
assert(reveal_unpacked[i] == char, 'Should reveal the right character');
|
||||
} else {
|
||||
assert(reveal_unpacked[i] == '\x00', 'Should not reveal');
|
||||
}
|
||||
}
|
||||
|
||||
const forbidden_countries_list_packed = await circuit.getOutput(w, [
|
||||
'forbidden_countries_list_packed[4]',
|
||||
]);
|
||||
const forbidden_countries_list_unpacked = formatAndUnpackForbiddenCountriesList(
|
||||
forbidden_countries_list_packed
|
||||
);
|
||||
expect(forbidden_countries_list_unpacked).to.deep.equal(forbidden_countries_list);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow disclosing majority', async function () {
|
||||
const selector_dg1 = Array(90).fill('0');
|
||||
|
||||
w = await circuit.calculateWitness({
|
||||
...inputs,
|
||||
selector_dg1: selector_dg1.map(String),
|
||||
});
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
const older_than = getAttributeFromUnpackedReveal(reveal_unpacked, 'older_than', 'id');
|
||||
expect(older_than).to.equal('18');
|
||||
});
|
||||
|
||||
it("shouldn't allow disclosing wrong majority", async function () {
|
||||
const selector_dg1 = Array(90).fill('0');
|
||||
|
||||
w = await circuit.calculateWitness({
|
||||
...inputs,
|
||||
majority: ['5', '0'].map((char) => BigInt(char.charCodeAt(0)).toString()),
|
||||
selector_dg1: selector_dg1.map(String),
|
||||
});
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
expect(reveal_unpacked[88]).to.equal('\x00');
|
||||
expect(reveal_unpacked[89]).to.equal('\x00');
|
||||
});
|
||||
|
||||
describe('OFAC disclosure', function () {
|
||||
it('should allow disclosing OFAC check result when selector is 1', async function () {
|
||||
w = await circuit.calculateWitness(inputs);
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
const ofac_results = reveal_unpacked.slice(92, 94);
|
||||
expect(ofac_results).to.deep.equal(
|
||||
['\x01', '\x01'],
|
||||
'OFAC result bits should be [1, 1]'
|
||||
);
|
||||
expect(ofac_results).to.not.equal(['\x00', '\x00'], 'OFAC result should be revealed');
|
||||
});
|
||||
|
||||
it('should not disclose OFAC check result when selector is 0', async function () {
|
||||
w = await circuit.calculateWitness({
|
||||
...inputs,
|
||||
selector_ofac: '0',
|
||||
});
|
||||
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
|
||||
// OFAC result should be hidden (null byte)
|
||||
const ofac_results = reveal_unpacked.slice(92, 94);
|
||||
expect(ofac_results).to.deep.equal(
|
||||
['\x00', '\x00'],
|
||||
'OFAC result bits should be [0, 0]'
|
||||
);
|
||||
expect(ofac_results).to.not.equal(['\x01', '\x01'], 'OFAC result should not be revealed');
|
||||
});
|
||||
|
||||
it('should show different levels of OFAC matching', async function () {
|
||||
// Test cases for different matching scenarios
|
||||
const testCases = [
|
||||
{
|
||||
desc: 'No details match',
|
||||
data: genMockIdDoc({ idType: 'mock_id_card' }),
|
||||
expectedBits: ['\x01', '\x01'],
|
||||
},
|
||||
{
|
||||
desc: 'Name and DOB matches (so YOB matches too)',
|
||||
data: genMockIdDoc({
|
||||
idType: 'mock_id_card',
|
||||
passportNumber: 'DIF123456',
|
||||
lastName: 'HENAO MONTOYA',
|
||||
firstName: 'ARCANGEL DE JESUS',
|
||||
birthDate: '541007',
|
||||
expiryDate: '300101',
|
||||
}),
|
||||
expectedBits: ['\x00', '\x00'],
|
||||
},
|
||||
{
|
||||
desc: 'Only name and YOB match',
|
||||
data: genMockIdDoc({
|
||||
idType: 'mock_id_card',
|
||||
passportNumber: 'DIF123456',
|
||||
lastName: 'HENAO MONTOYA',
|
||||
firstName: 'ARCANGEL DE JESUS',
|
||||
birthDate: '541299',
|
||||
expiryDate: '300101', // Same year (54) different month/day
|
||||
}),
|
||||
expectedBits: ['\x01', '\x00'],
|
||||
},
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
console.log(`Testing: ${testCase.desc}`);
|
||||
const passportData = testCase.data;
|
||||
const sanctionedCommitment = generateCommitment(
|
||||
secret,
|
||||
ID_CARD_ATTESTATION_ID,
|
||||
passportData
|
||||
);
|
||||
tree.insert(BigInt(sanctionedCommitment));
|
||||
|
||||
const testInputs = generateCircuitInputsVCandDisclose(
|
||||
secret,
|
||||
ID_CARD_ATTESTATION_ID,
|
||||
passportData,
|
||||
fullScope,
|
||||
Array(90).fill('0'), // selector_dg1
|
||||
selector_older_than,
|
||||
tree,
|
||||
majority,
|
||||
passportNo_smt,
|
||||
nameAndDob_smt,
|
||||
nameAndYob_smt,
|
||||
'1', // selector_ofac
|
||||
forbidden_countries_list,
|
||||
user_identifier
|
||||
);
|
||||
|
||||
w = await circuit.calculateWitness(testInputs);
|
||||
const revealedData_packed = await circuit.getOutput(w, ['revealedData_packed[4]']);
|
||||
const reveal_unpacked = formatAndUnpackReveal(revealedData_packed, 'id');
|
||||
const ofac_results = reveal_unpacked.slice(92, 94);
|
||||
|
||||
console.log(`${testCase.desc} - OFAC bits:`, ofac_results);
|
||||
expect(ofac_results).to.deep.equal(
|
||||
testCase.expectedBits,
|
||||
`Failed matching pattern for: ${testCase.desc}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,9 @@ import path from 'path';
|
||||
import { poseidon2 } from 'poseidon-lite';
|
||||
import nameAndDobjson from '../../../common/ofacdata/outputs/nameAndDobSMT.json';
|
||||
import nameAndYobjson from '../../../common/ofacdata/outputs/nameAndYobSMT.json';
|
||||
import nameAndDobIdCardJson from '../../../common/ofacdata/outputs/nameAndDobSMT_ID.json';
|
||||
import nameAndYobIdCardJson from '../../../common/ofacdata/outputs/nameAndYobSMT_ID.json';
|
||||
import { genMockIdDoc } from '../../../common/src/utils/passports/genMockIdDoc';
|
||||
import passportNoAndNationalityjson from '../../../common/ofacdata/outputs/passportNoAndNationalitySMT.json';
|
||||
import { generateCircuitInputsOfac } from '../../../common/src/utils/circuits/generateInputs';
|
||||
import { genAndInitMockPassportData } from '../../../common/src/utils/passports/genMockPassportData';
|
||||
@@ -12,6 +15,9 @@ import { genAndInitMockPassportData } from '../../../common/src/utils/passports/
|
||||
let circuit: any;
|
||||
|
||||
// Mock passport not added in ofac list
|
||||
const mockIdData = genMockIdDoc(
|
||||
{ 'idType': 'mock_passport' }
|
||||
);
|
||||
const passportData = genAndInitMockPassportData(
|
||||
'sha256',
|
||||
'sha256',
|
||||
@@ -33,6 +39,30 @@ const passportDataInOfac = genAndInitMockPassportData(
|
||||
'ARCANGEL DE JESUS'
|
||||
);
|
||||
|
||||
const mockIdDataInOfac = genMockIdDoc({
|
||||
'idType': 'mock_passport',
|
||||
'nationality': 'FRA',
|
||||
'birthDate': '541007',
|
||||
'lastName': 'HENAO MONTOYA',
|
||||
'passportNumber': '98lh90556',
|
||||
'firstName': 'ARCANGEL DE JESUS'
|
||||
})
|
||||
|
||||
// Mock ID Card not in OFAC list
|
||||
const idCardData = genMockIdDoc({
|
||||
'idType': 'mock_id_card'
|
||||
})
|
||||
|
||||
// Mock ID Card in OFAC list
|
||||
const idCardDataInOfac = genMockIdDoc({
|
||||
'idType': 'mock_id_card',
|
||||
'nationality': 'FRA',
|
||||
'birthDate': '541007',
|
||||
'firstName': 'ARCANGEL DE JESUS',
|
||||
'lastName': 'HENAO MONTOYA'
|
||||
})
|
||||
|
||||
|
||||
// POSSIBLE TESTS (for each of 3 circuits):
|
||||
// 0. Cicuits compiles and loads
|
||||
// 1. Valid proof : Correct path and corresponding closest leaf AND leaf != pasport_hash ; Valid prove of non-membership
|
||||
@@ -65,10 +95,8 @@ describe('OFAC - Passport number and Nationality match', function () {
|
||||
passNoAndNationality_smt,
|
||||
proofLevel
|
||||
);
|
||||
// console.log('memSmtInputs', memSmtInputs);
|
||||
|
||||
nonMemSmtInputs = generateCircuitInputsOfac(passportData, passNoAndNationality_smt, proofLevel);
|
||||
// console.log('nonMemSmtInputs', nonMemSmtInputs);
|
||||
});
|
||||
|
||||
// Compile circuit
|
||||
@@ -138,7 +166,7 @@ describe('OFAC - Name and DOB match', function () {
|
||||
);
|
||||
});
|
||||
|
||||
// Compile circuit
|
||||
// // Compile circuit
|
||||
it('should compile and load the circuit, level 2', async function () {
|
||||
expect(circuit).to.not.be.undefined;
|
||||
});
|
||||
@@ -334,3 +362,129 @@ describe('OFAC - SMT Security Tests', function () {
|
||||
expect(ofacCheckResult).to.equal('0');
|
||||
});
|
||||
});
|
||||
|
||||
// ===========================
|
||||
// ID Card Tests
|
||||
// ===========================
|
||||
|
||||
// Level 2: NameDob match in OfacList - ID Card
|
||||
describe('OFAC - ID Card - Name and DOB match', function () {
|
||||
this.timeout(0);
|
||||
let namedob_id_smt = new SMT(poseidon2, true);
|
||||
let memSmtInputs: any;
|
||||
let nonMemSmtInputs: any;
|
||||
|
||||
before(async () => {
|
||||
circuit = await wasm_tester(
|
||||
// Use the same circuit as passport level 2
|
||||
path.join(__dirname, '../../circuits/tests/ofac/ofac_name_dob_id_tester.circom'),
|
||||
{
|
||||
include: [
|
||||
'node_modules',
|
||||
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
|
||||
'./node_modules/circomlib/circuits',
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// IMPORTANT: Ensure this JSON path is correct
|
||||
namedob_id_smt.import(nameAndDobIdCardJson);
|
||||
const proofLevel = 2;
|
||||
memSmtInputs = generateCircuitInputsOfac(
|
||||
idCardDataInOfac, // Use ID card data
|
||||
namedob_id_smt,
|
||||
proofLevel
|
||||
);
|
||||
|
||||
nonMemSmtInputs = generateCircuitInputsOfac(
|
||||
idCardData, // Use ID card data
|
||||
namedob_id_smt,
|
||||
proofLevel
|
||||
);
|
||||
});
|
||||
|
||||
it('ID Card L2: should pass without errors, non-membership', async function () {
|
||||
let w = await circuit.calculateWitness(nonMemSmtInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('1'); // 1 means not found (non-membership is ok)
|
||||
});
|
||||
|
||||
it('ID Card L2: should pass - ID card details are in OFAC list', async function () {
|
||||
let w = await circuit.calculateWitness(memSmtInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('0'); // 0 means found (membership proof fails non-membership check)
|
||||
});
|
||||
|
||||
it('ID Card L2: should fail - wrong leaf key provided', async function () {
|
||||
const wrongInputs = {
|
||||
...nonMemSmtInputs,
|
||||
smt_leaf_key: BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString(),
|
||||
};
|
||||
let w = await circuit.calculateWitness(wrongInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('0'); // Fails because root won't match
|
||||
});
|
||||
});
|
||||
|
||||
// Level 1: Name and YOB match in OfacList - ID Card
|
||||
describe('OFAC - ID Card - Name and YOB match', function () {
|
||||
this.timeout(0);
|
||||
let nameyob_id_smt = new SMT(poseidon2, true);
|
||||
let memSmtInputs: any;
|
||||
let nonMemSmtInputs: any;
|
||||
|
||||
before(async () => {
|
||||
circuit = await wasm_tester(
|
||||
// Use the same circuit as passport level 1
|
||||
path.join(__dirname, '../../circuits/tests/ofac/ofac_name_yob_id_tester.circom'),
|
||||
{
|
||||
include: [
|
||||
'node_modules',
|
||||
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
|
||||
'./node_modules/circomlib/circuits',
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// IMPORTANT: Ensure this JSON path is correct
|
||||
nameyob_id_smt.import(nameAndYobIdCardJson);
|
||||
const proofLevel = 1;
|
||||
memSmtInputs = generateCircuitInputsOfac(
|
||||
idCardDataInOfac, // Use ID card data
|
||||
nameyob_id_smt,
|
||||
proofLevel
|
||||
);
|
||||
|
||||
nonMemSmtInputs = generateCircuitInputsOfac(
|
||||
idCardData, // Use ID card data
|
||||
nameyob_id_smt,
|
||||
proofLevel
|
||||
);
|
||||
});
|
||||
|
||||
// it('should compile and load the circuit for ID Card, level 1', async function () {
|
||||
// expect(circuit).to.not.be.undefined;
|
||||
// });
|
||||
|
||||
it('ID Card L1: should pass without errors, non-membership', async function () {
|
||||
let w = await circuit.calculateWitness(nonMemSmtInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('1'); // 1 means not found (non-membership is ok)
|
||||
});
|
||||
|
||||
it('ID Card L1: should pass - ID card details are in OFAC list', async function () {
|
||||
let w = await circuit.calculateWitness(memSmtInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('0'); // 0 means found (membership proof fails non-membership check)
|
||||
});
|
||||
|
||||
it('ID Card L1: should fail - wrong leaf key provided', async function () {
|
||||
const wrongInputs = {
|
||||
...nonMemSmtInputs,
|
||||
smt_leaf_key: BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString(),
|
||||
};
|
||||
let w = await circuit.calculateWitness(wrongInputs);
|
||||
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
|
||||
expect(ofacCheckResult).to.equal('0'); // Fails because root won't match
|
||||
});
|
||||
});
|
||||
|
||||
330
circuits/tests/register_id/register_id.test.ts
Normal file
330
circuits/tests/register_id/register_id.test.ts
Normal file
@@ -0,0 +1,330 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { describe } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import path from 'path';
|
||||
import { wasm as wasm_tester } from 'circom_tester';
|
||||
import { generateCircuitInputsRegister } from '../../../common/src/utils/circuits/generateInputs';
|
||||
import { genMockPassportData } from '../../../common/src/utils/passports/genMockPassportData';
|
||||
import { SignatureAlgorithm } from '../../../common/src/utils/types';
|
||||
import { getCircuitNameFromPassportData } from '../../../common/src/utils/circuits/circuitsName';
|
||||
import { sigAlgs, fullSigAlgs } from './test_cases';
|
||||
import {
|
||||
generateCommitment,
|
||||
generateNullifier,
|
||||
} from '../../../common/src/utils/passports/passport';
|
||||
import { poseidon6 } from 'poseidon-lite';
|
||||
import { hashAlgosTypes, PASSPORT_ATTESTATION_ID } from '../../../common/src/constants/constants';
|
||||
import { parseCertificateSimple } from '../../../common/src/utils/certificate_parsing/parseCertificateSimple';
|
||||
import serialized_dsc_tree from '../../../common/pubkeys/serialized_dsc_tree.json';
|
||||
import { genMockIdDoc } from '../../../common/src/utils/passports/genMockIdDoc';
|
||||
dotenv.config();
|
||||
|
||||
const testSuite = process.env.FULL_TEST_SUITE === 'true' ? fullSigAlgs : sigAlgs;
|
||||
|
||||
testSuite.forEach(
|
||||
({
|
||||
dgHashAlgo,
|
||||
eContentHashAlgo,
|
||||
sigAlg,
|
||||
hashFunction,
|
||||
domainParameter,
|
||||
keyLength,
|
||||
saltLength,
|
||||
}) => {
|
||||
describe(`Register - ${dgHashAlgo.toUpperCase()} ${eContentHashAlgo.toUpperCase()} ${hashFunction.toUpperCase()} ${sigAlg.toUpperCase()} ${domainParameter
|
||||
} ${keyLength}${saltLength ? ` Salt:${saltLength}` : ''}`, function () {
|
||||
this.timeout(0);
|
||||
let circuit: any;
|
||||
|
||||
const passportData = genMockIdDoc({
|
||||
idType: 'mock_id_card',
|
||||
dgHashAlgo: dgHashAlgo as hashAlgosTypes,
|
||||
eContentHashAlgo: eContentHashAlgo as hashAlgosTypes,
|
||||
signatureType: `${sigAlg}_${hashFunction}_${domainParameter}_${keyLength}${saltLength ? `_${saltLength}` : ''}` as SignatureAlgorithm,
|
||||
})
|
||||
const secret = poseidon6('SECRET'.split('').map((x) => BigInt(x.charCodeAt(0)))).toString();
|
||||
|
||||
const inputs = generateCircuitInputsRegister(
|
||||
secret,
|
||||
passportData,
|
||||
serialized_dsc_tree as string
|
||||
);
|
||||
|
||||
before(async () => {
|
||||
circuit = await wasm_tester(
|
||||
path.join(
|
||||
__dirname,
|
||||
`../../circuits/register_id/instances/${getCircuitNameFromPassportData(passportData, 'register')}.circom`
|
||||
),
|
||||
{
|
||||
include: [
|
||||
'node_modules',
|
||||
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
|
||||
'./node_modules/circomlib/circuits',
|
||||
],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should compile and load the circuit', async function () {
|
||||
expect(circuit).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it('should calculate the witness with correct inputs, and have the right nullifier and commitment', async function () {
|
||||
const w = await circuit.calculateWitness(inputs);
|
||||
await circuit.checkConstraints(w);
|
||||
|
||||
const nullifier_js = generateNullifier(passportData);
|
||||
console.log('\x1b[35m%s\x1b[0m', 'js: nullifier:', nullifier_js);
|
||||
const nullifier = (await circuit.getOutput(w, ['nullifier'])).nullifier;
|
||||
console.log('\x1b[34m%s\x1b[0m', 'circom: nullifier', nullifier);
|
||||
expect(nullifier).to.be.equal(nullifier_js);
|
||||
|
||||
const commitment_js = generateCommitment(
|
||||
secret.toString(),
|
||||
PASSPORT_ATTESTATION_ID,
|
||||
passportData
|
||||
);
|
||||
console.log('\x1b[35m%s\x1b[0m', 'js: commitment:', commitment_js);
|
||||
const commitment = (await circuit.getOutput(w, ['commitment'])).commitment;
|
||||
console.log('\x1b[34m%s\x1b[0m', 'circom commitment', commitment);
|
||||
expect(commitment).to.be.equal(commitment_js);
|
||||
});
|
||||
|
||||
it('should fail if dsc_pubKey_actual_size is lower than the minimum key length', async () => {
|
||||
try {
|
||||
const dscParsed = parseCertificateSimple(passportData.dsc);
|
||||
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
if (dscParsed.signatureAlgorithm === 'rsa') {
|
||||
tamperedInputs.dsc_pubKey_actual_size = (256 - 1).toString(); // 256 is the minimum key length for RSA
|
||||
} else {
|
||||
// for ecdsa and rsapss, the minimum key length is fixed for each circuit
|
||||
tamperedInputs.dsc_pubKey_actual_size = (
|
||||
Number(tamperedInputs.dsc_pubKey_actual_size) - 1
|
||||
).toString();
|
||||
}
|
||||
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Tests for dsc_pubKey offset and size checks -----
|
||||
it('should fail if dsc_pubKey_offset + dsc_pubKey_actual_size > raw_dsc_actual_length', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.dsc_pubKey_offset = (
|
||||
Number(tamperedInputs.raw_dsc_actual_length) -
|
||||
Number(tamperedInputs.dsc_pubKey_actual_size) +
|
||||
1
|
||||
).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if dsc_pubKey_actual_size is larger than the actual key size in certificate', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.dsc_pubKey_actual_size = (
|
||||
Number(tamperedInputs.dsc_pubKey_actual_size) + 8
|
||||
).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Tests for Merkle tree inclusion -----
|
||||
it('should fail if merkle_root is invalid', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.merkle_root = (BigInt(tamperedInputs.merkle_root) + 1n).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if leaf_depth is tampered', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
// Change leaf_depth to an incorrect value (e.g., add 1)
|
||||
tamperedInputs.leaf_depth = (Number(tamperedInputs.leaf_depth) + 1).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if a value in the merkle path is invalid', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.path[0] = (BigInt(tamperedInputs.path[0]) + 1n).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if a sibling in the merkle proof is invalid', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.siblings[0] = (BigInt(tamperedInputs.siblings[0]) + 1n).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Tests for passport signature and data integrity -----
|
||||
it('should fail to calculate witness with invalid mrz', async function () {
|
||||
try {
|
||||
const ininputs = {
|
||||
...inputs,
|
||||
dg1: Array(95)
|
||||
.fill(0)
|
||||
.map((byte) => BigInt(byte).toString()),
|
||||
};
|
||||
await circuit.calculateWitness(ininputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail to calculate witness with invalid eContent', async function () {
|
||||
try {
|
||||
const ininputs = {
|
||||
...inputs,
|
||||
eContent: inputs.eContent.map((byte: string) => String((parseInt(byte, 10) + 1) % 256)),
|
||||
};
|
||||
await circuit.calculateWitness(ininputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if signed_attr is invalid', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.signed_attr = tamperedInputs.signed_attr.map((byte: string) =>
|
||||
((parseInt(byte, 10) + 1) % 256).toString()
|
||||
);
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail if signature_passport is invalid', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.signature_passport = tamperedInputs.signature_passport.map(
|
||||
(byte: string) => ((parseInt(byte, 10) + 1) % 256).toString()
|
||||
);
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Test for tampering with csca_hash (used in commitment) -----
|
||||
it('should fail if csca_hash is tampered', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.csca_tree_leaf = (BigInt(tamperedInputs.csca_tree_leaf) + 1n).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Test for tampering with secret (affects commitment and nullifier) -----
|
||||
it('should compute different outputs if secret is changed', async function () {
|
||||
const wValid = await circuit.calculateWitness(inputs);
|
||||
await circuit.checkConstraints(wValid);
|
||||
const nullifierValid = (await circuit.getOutput(wValid, ['nullifier'])).nullifier;
|
||||
const commitmentValid = (await circuit.getOutput(wValid, ['commitment'])).commitment;
|
||||
|
||||
const tamperedInputs = { ...inputs, secret: (BigInt(inputs.secret[0]) + 1n).toString() };
|
||||
const wTampered = await circuit.calculateWitness(tamperedInputs);
|
||||
await circuit.checkConstraints(wTampered);
|
||||
const nullifierTampered = (await circuit.getOutput(wTampered, ['nullifier'])).nullifier;
|
||||
const commitmentTampered = (await circuit.getOutput(wTampered, ['commitment'])).commitment;
|
||||
|
||||
expect(nullifierTampered).to.equal(nullifierValid);
|
||||
expect(commitmentTampered).to.not.be.equal(commitmentValid);
|
||||
});
|
||||
|
||||
if (sigAlg.startsWith('rsa') || sigAlg.startsWith('rsapss')) {
|
||||
it('should fail if RSA public key prefix is invalid', async function () {
|
||||
const invalidPrefixes = [
|
||||
[0x03, 0x82, 0x01, 0x01, 0x00],
|
||||
[0x02, 0x83, 0x01, 0x01, 0x00],
|
||||
[0x02, 0x82, 0x02, 0x02, 0x00],
|
||||
];
|
||||
|
||||
for (const invalidPrefix of invalidPrefixes) {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
for (let i = 0; i < invalidPrefix.length; i++) {
|
||||
tamperedInputs.raw_dsc[
|
||||
Number(tamperedInputs.dsc_pubKey_offset) - invalidPrefix.length + i
|
||||
] = invalidPrefix[i].toString();
|
||||
}
|
||||
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should pass with valid RSA prefix for the key length', async function () {
|
||||
const keyLengthToPrefix = {
|
||||
2048: [0x02, 0x82, 0x01, 0x01, 0x00],
|
||||
3072: [0x02, 0x82, 0x01, 0x81, 0x00],
|
||||
4096: [0x02, 0x82, 0x02, 0x01, 0x00],
|
||||
};
|
||||
|
||||
const expectedPrefix = keyLengthToPrefix[keyLength];
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const prefixByte = parseInt(inputs.raw_dsc[Number(inputs.dsc_pubKey_offset) - 5 + i]);
|
||||
expect(prefixByte).to.equal(
|
||||
expectedPrefix[i],
|
||||
`Prefix byte ${i} mismatch for ${keyLength} bit key`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it('should fail if raw_dsc has a signal that is longer than a byte', async function () {
|
||||
try {
|
||||
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
|
||||
tamperedInputs.raw_dsc[0] = (parseInt(tamperedInputs.raw_dsc[0], 10) + 256).toString();
|
||||
await circuit.calculateWitness(tamperedInputs);
|
||||
expect.fail('Expected an error but none was thrown.');
|
||||
} catch (error: any) {
|
||||
expect(error.message).to.include('Assert Failed');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
230
circuits/tests/register_id/test_cases.ts
Normal file
230
circuits/tests/register_id/test_cases.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
// Define the interface for test cases with optional saltLength
|
||||
export interface TestCase {
|
||||
dgHashAlgo: string;
|
||||
eContentHashAlgo: string;
|
||||
sigAlg: string;
|
||||
hashFunction: string;
|
||||
domainParameter: string;
|
||||
keyLength: string;
|
||||
saltLength?: string; // Optional salt length for RSA-PSS
|
||||
}
|
||||
|
||||
export const sigAlgs: TestCase[] = [
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048'
|
||||
},
|
||||
];
|
||||
|
||||
export const fullSigAlgs: TestCase[] = [
|
||||
// RSA
|
||||
{
|
||||
dgHashAlgo: 'sha1',
|
||||
eContentHashAlgo: 'sha1',
|
||||
hashFunction: 'sha1',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha1',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '3',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha512',
|
||||
eContentHashAlgo: 'sha512',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '4096',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha512',
|
||||
eContentHashAlgo: 'sha512',
|
||||
hashFunction: 'sha512',
|
||||
sigAlg: 'rsa',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
// RSAPSS
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '3',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
saltLength: '64', // Denmark
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '65537',
|
||||
keyLength: '3072',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha384',
|
||||
eContentHashAlgo: 'sha384',
|
||||
hashFunction: 'sha384',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha512',
|
||||
eContentHashAlgo: 'sha512',
|
||||
hashFunction: 'sha512',
|
||||
sigAlg: 'rsapss',
|
||||
domainParameter: '65537',
|
||||
keyLength: '2048',
|
||||
},
|
||||
// ECDSA
|
||||
// brainpool
|
||||
{
|
||||
dgHashAlgo: 'sha1',
|
||||
eContentHashAlgo: 'sha1',
|
||||
hashFunction: 'sha1',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP224r1',
|
||||
keyLength: '224',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha224',
|
||||
eContentHashAlgo: 'sha224',
|
||||
hashFunction: 'sha224',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP224r1',
|
||||
keyLength: '224',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP256r1',
|
||||
keyLength: '256',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP384r1',
|
||||
keyLength: '384',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha384',
|
||||
eContentHashAlgo: 'sha384',
|
||||
hashFunction: 'sha384',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP384r1',
|
||||
keyLength: '384',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha384',
|
||||
eContentHashAlgo: 'sha384',
|
||||
hashFunction: 'sha384',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP512r1',
|
||||
keyLength: '512',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha512',
|
||||
eContentHashAlgo: 'sha512',
|
||||
hashFunction: 'sha512',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'brainpoolP512r1',
|
||||
keyLength: '512',
|
||||
},
|
||||
// secp
|
||||
{
|
||||
dgHashAlgo: 'sha1',
|
||||
eContentHashAlgo: 'sha1',
|
||||
hashFunction: 'sha1',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp256r1',
|
||||
keyLength: '256',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha224',
|
||||
hashFunction: 'sha224',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp224r1',
|
||||
keyLength: '224',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp256r1',
|
||||
keyLength: '256',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha256',
|
||||
eContentHashAlgo: 'sha256',
|
||||
hashFunction: 'sha256',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp384r1',
|
||||
keyLength: '384',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha384',
|
||||
eContentHashAlgo: 'sha384',
|
||||
hashFunction: 'sha384',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp384r1',
|
||||
keyLength: '384',
|
||||
},
|
||||
{
|
||||
dgHashAlgo: 'sha512',
|
||||
eContentHashAlgo: 'sha512',
|
||||
hashFunction: 'sha512',
|
||||
sigAlg: 'ecdsa',
|
||||
domainParameter: 'secp521r1',
|
||||
keyLength: '521',
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user