mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
362 lines
9.7 KiB
TypeScript
362 lines
9.7 KiB
TypeScript
import { describe } from 'mocha';
|
|
import { expect } from 'chai';
|
|
import path from 'path';
|
|
import { wasm as wasm_tester } from 'circom_tester';
|
|
import { generateCircuitInputsProve } from '../../common/src/utils/generateInputs';
|
|
import { genMockPassportData } from '../../common/src/utils/genMockPassportData';
|
|
import { SignatureAlgorithm } from '../../common/src/utils/types';
|
|
import crypto from 'crypto';
|
|
import { poseidon2 } from 'poseidon-lite';
|
|
import { SMT } from '@openpassport/zk-kit-smt';
|
|
import namejson from '../../common/ofacdata/outputs/nameSMT.json';
|
|
import { getCircuitNameFromPassportData } from '../../common/src/utils/circuitsName';
|
|
|
|
const sigAlgs = [
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '3',
|
|
keyLength: '3072',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha1',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha1',
|
|
eContentHashAlgo: 'sha1',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha1',
|
|
domainParameter: 'secp256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha224',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha224',
|
|
domainParameter: 'brainpoolP224r1',
|
|
keyLength: '224',
|
|
},
|
|
];
|
|
|
|
const fullSigAlgs = [
|
|
{
|
|
dgHashAlgo: 'sha1',
|
|
eContentHashAlgo: 'sha1',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha1',
|
|
domainParameter: '65537',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '3072',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '4096',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '3',
|
|
keyLength: '4096',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsapss',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '3',
|
|
keyLength: '3072',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '3',
|
|
keyLength: '2048',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'rsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: '65537',
|
|
keyLength: '3072',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: 'secp256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha1',
|
|
eContentHashAlgo: 'sha1',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha1',
|
|
domainParameter: 'secp256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: 'brainpoolP256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: 'secp384r1',
|
|
keyLength: '384',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha384',
|
|
eContentHashAlgo: 'sha384',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha384',
|
|
domainParameter: 'brainpoolP256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha384',
|
|
eContentHashAlgo: 'sha384',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha384',
|
|
domainParameter: 'brainpoolP384r1',
|
|
keyLength: '384',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha384',
|
|
eContentHashAlgo: 'sha384',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha384',
|
|
domainParameter: 'secp384r1',
|
|
keyLength: '384',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha512',
|
|
eContentHashAlgo: 'sha512',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha512',
|
|
domainParameter: 'brainpoolP256r1',
|
|
keyLength: '256',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha224',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha224',
|
|
domainParameter: 'brainpoolP224r1',
|
|
keyLength: '224',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: 'brainpoolP224r1',
|
|
keyLength: '224',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha1',
|
|
eContentHashAlgo: 'sha1',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha1',
|
|
domainParameter: 'brainpoolP224r1',
|
|
keyLength: '224',
|
|
},
|
|
{
|
|
dgHashAlgo: 'sha256',
|
|
eContentHashAlgo: 'sha256',
|
|
sigAlg: 'ecdsa',
|
|
hashFunction: 'sha256',
|
|
domainParameter: 'secp256r1',
|
|
keyLength: '256',
|
|
},
|
|
];
|
|
|
|
const testSuite = process.env.FULL_TEST_SUITE === 'true' ? fullSigAlgs : sigAlgs;
|
|
// const testSuite = fullSigAlgs;
|
|
|
|
testSuite.forEach(
|
|
({ dgHashAlgo, eContentHashAlgo, sigAlg, hashFunction, domainParameter, keyLength }) => {
|
|
describe(`Prove - ${dgHashAlgo.toUpperCase()} ${eContentHashAlgo.toUpperCase()} ${hashFunction.toUpperCase()} ${sigAlg.toUpperCase()} ${domainParameter} ${keyLength}`, function () {
|
|
this.timeout(0);
|
|
let circuit: any;
|
|
|
|
const passportData = genMockPassportData(
|
|
dgHashAlgo,
|
|
eContentHashAlgo,
|
|
`${sigAlg}_${hashFunction}_${domainParameter}_${keyLength}` as SignatureAlgorithm,
|
|
'FRA',
|
|
'000101',
|
|
'300101'
|
|
);
|
|
const majority = '18';
|
|
const user_identifier = crypto.randomUUID();
|
|
const scope = '@coboyApp';
|
|
const selector_dg1 = Array(88).fill('1');
|
|
const selector_older_than = '1';
|
|
const secret = 0;
|
|
const dsc_secret = 0;
|
|
const selector_mode = [1, 1];
|
|
const selector_ofac = 1;
|
|
const forbidden_countries_list = ['DZA'];
|
|
|
|
let name_smt = new SMT(poseidon2, true);
|
|
name_smt.import(namejson);
|
|
const inputs = generateCircuitInputsProve(
|
|
selector_mode,
|
|
secret,
|
|
dsc_secret,
|
|
passportData,
|
|
scope,
|
|
selector_dg1,
|
|
selector_older_than,
|
|
majority,
|
|
name_smt,
|
|
selector_ofac,
|
|
forbidden_countries_list,
|
|
user_identifier
|
|
);
|
|
|
|
before(async () => {
|
|
circuit = await wasm_tester(
|
|
path.join(
|
|
__dirname,
|
|
`../circuits/prove/instances/${getCircuitNameFromPassportData(passportData)}.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', async function () {
|
|
const w = await circuit.calculateWitness(inputs);
|
|
await circuit.checkConstraints(w);
|
|
// circuits.getOutput takes way too long for ecdsa
|
|
if (true) {
|
|
console.log('skipping printing outputs to console for ecdsa');
|
|
return;
|
|
}
|
|
|
|
const nullifier = (await circuit.getOutput(w, ['nullifier'])).nullifier;
|
|
console.log('\x1b[34m%s\x1b[0m', 'nullifier', nullifier);
|
|
const commitment = (await circuit.getOutput(w, ['commitment'])).commitment;
|
|
console.log('\x1b[34m%s\x1b[0m', 'commitment', commitment);
|
|
const blinded_dsc_commitment = (await circuit.getOutput(w, ['blinded_dsc_commitment']))
|
|
.blinded_dsc_commitment;
|
|
console.log('\x1b[34m%s\x1b[0m', 'blinded_dsc_commitment', blinded_dsc_commitment);
|
|
|
|
const ofac_result = (await circuit.getOutput(w, ['ofac_result'])).ofac_result;
|
|
console.log('\x1b[34m%s\x1b[0m', 'ofac_result', ofac_result);
|
|
|
|
expect(blinded_dsc_commitment).to.be.not.null;
|
|
expect(nullifier).to.be.not.null;
|
|
});
|
|
|
|
it('should fail to calculate witness with invalid mrz', async function () {
|
|
try {
|
|
const invalidInputs = {
|
|
...inputs,
|
|
dg1: Array(93)
|
|
.fill(0)
|
|
.map((byte) => BigInt(byte).toString()),
|
|
};
|
|
await circuit.calculateWitness(invalidInputs);
|
|
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 invalidInputs = {
|
|
...inputs,
|
|
eContent: inputs.eContent.map((byte: string) => String((parseInt(byte, 10) + 1) % 256)),
|
|
};
|
|
await circuit.calculateWitness(invalidInputs);
|
|
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 signature', async function () {
|
|
try {
|
|
const invalidInputs = {
|
|
...inputs,
|
|
signature: inputs.signature.map((byte: string) =>
|
|
String((parseInt(byte, 10) + 1) % 256)
|
|
),
|
|
};
|
|
await circuit.calculateWitness(invalidInputs);
|
|
expect.fail('Expected an error but none was thrown.');
|
|
} catch (error) {
|
|
expect(error.message).to.include('Assert Failed');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
);
|