feat: generate inputs for ecdsa with sha1

This commit is contained in:
0xvikasrushi
2024-07-28 06:21:48 +00:00
parent 30f7cdda8e
commit ed1397b923
2 changed files with 133 additions and 95 deletions

View File

@@ -1,20 +1,25 @@
import { MAX_DATAHASHES_LEN, PUBKEY_TREE_DEPTH, DEVELOPMENT_MODE } from "../constants/constants";
import { assert, shaPad } from "./shaPad";
import { PassportData } from "./types";
import { MAX_DATAHASHES_LEN, PUBKEY_TREE_DEPTH, DEVELOPMENT_MODE } from '../constants/constants';
import { assert, shaPad } from './shaPad';
import { PassportData } from './types';
import {
arraysAreEqual, bytesToBigDecimal, formatMrz, hash, splitToWords,
toUnsignedByte, getHashLen, getCurrentDateYYMMDD,
arraysAreEqual,
bytesToBigDecimal,
formatMrz,
hash,
splitToWords,
toUnsignedByte,
getHashLen,
getCurrentDateYYMMDD,
generateMerkleProof,
findSubarrayIndex
} from "./utils";
import { LeanIMT } from "@zk-kit/lean-imt";
import { getLeaf } from "./pubkeyTree";
import { poseidon6 } from "poseidon-lite";
import { packBytes } from "../utils/utils";
import { getCSCAModulusMerkleTree } from "./csca";
import {
mockPassportDatas,
} from "../constants/mockPassportData";
findSubarrayIndex,
hexToDecimal,
} from './utils';
import { LeanIMT } from '@zk-kit/lean-imt';
import { getLeaf } from './pubkeyTree';
import { poseidon6 } from 'poseidon-lite';
import { packBytes } from '../utils/utils';
import { getCSCAModulusMerkleTree } from './csca';
import { mockPassportDatas } from '../constants/mockPassportData';
export function generateCircuitInputsRegister(
secret: string,
@@ -25,21 +30,26 @@ export function generateCircuitInputsRegister(
k_dsc: number,
mocks: PassportData[] = mockPassportDatas
) {
const { mrz, signatureAlgorithm, pubKey, dataGroupHashes, eContent, encryptedDigest } = passportData;
const { mrz, signatureAlgorithm, pubKey, dataGroupHashes, eContent, encryptedDigest } =
passportData;
const tree = getCSCAModulusMerkleTree();
if (DEVELOPMENT_MODE) {
for (const mockPassportData of mocks) {
console.log('mockPassportData', mockPassportData);
tree.insert(getLeaf(mockPassportData).toString());
}
}
if (![
"sha256WithRSAEncryption",
"sha1WithRSAEncryption",
"sha256WithRSASSAPSS"
].includes(signatureAlgorithm)) {
if (
![
'sha256WithRSAEncryption',
'sha1WithRSAEncryption',
'sha256WithRSASSAPSS',
'ecdsa-with-SHA1',
].includes(signatureAlgorithm)
) {
console.error(`${signatureAlgorithm} has not been implemented.`);
throw new Error(`${signatureAlgorithm} has not been implemented.`);
}
@@ -48,7 +58,7 @@ export function generateCircuitInputsRegister(
const formattedMrz = formatMrz(mrz);
const mrzHash = hash(signatureAlgorithm, formattedMrz);
const dg1HashOffset = findSubarrayIndex(dataGroupHashes, mrzHash)
const dg1HashOffset = findSubarrayIndex(dataGroupHashes, mrzHash);
console.log('dg1HashOffset', dg1HashOffset);
assert(dg1HashOffset !== -1, 'MRZ hash index not found in dataGroupHashes');
@@ -56,30 +66,31 @@ export function generateCircuitInputsRegister(
const concatHash = hash(signatureAlgorithm, dataGroupHashes);
assert(
arraysAreEqual(
concatHash,
eContent.slice(eContent.length - hashLen)
),
arraysAreEqual(concatHash, eContent.slice(eContent.length - hashLen)),
'concatHash is not at the right place in eContent'
);
// const leaf = getLeaf({
// signatureAlgorithm: signatureAlgorithm,
// ...pubKey,
// }).toString();
const leaf = getLeaf({
signatureAlgorithm: signatureAlgorithm,
...pubKey,
}).toString();
// const index = tree.indexOf(leaf);
// // console.log(`Index of pubkey in the registry: ${index}`);
// if (index === -1) {
// throw new Error("Your public key was not found in the registry");
// }
const index = tree.indexOf(leaf);
// console.log(`Index of pubkey in the registry: ${index}`);
if (index === -1) {
throw new Error('Your public key was not found in the registry');
}
// const proof = tree.createProof(index);
// console.log("verifyProof", tree.verifyProof(proof));
const proof = tree.createProof(index);
console.log('verifyProof', tree.verifyProof(proof));
if (dataGroupHashes.length > MAX_DATAHASHES_LEN) {
console.error(`Data hashes too long (${dataGroupHashes.length} bytes). Max length is ${MAX_DATAHASHES_LEN} bytes.`);
throw new Error(`This length of datagroups (${dataGroupHashes.length} bytes) is currently unsupported. Please contact us so we add support!`);
console.error(
`Data hashes too long (${dataGroupHashes.length} bytes). Max length is ${MAX_DATAHASHES_LEN} bytes.`
);
throw new Error(
`This length of datagroups (${dataGroupHashes.length} bytes) is currently unsupported. Please contact us so we add support!`
);
}
const [messagePadded, messagePaddedLen] = shaPad(
@@ -88,25 +99,38 @@ export function generateCircuitInputsRegister(
MAX_DATAHASHES_LEN
);
let dsc_modulus: any;
if (signatureAlgorithm === 'ecdsa-with-SHA1') {
console.log('pubKey', pubKey);
const curve_params = pubKey.publicKeyQ.replace(/[()]/g, '').split(',');
let k = hexToDecimal(curve_params[0]);
let m = hexToDecimal(curve_params[1]);
dsc_modulus = [
...splitToWords(BigInt(k), BigInt(n_dsc), BigInt(k_dsc)),
...splitToWords(BigInt(m), BigInt(n_dsc), BigInt(k_dsc)),
];
} else {
dsc_modulus = splitToWords(
BigInt(passportData.pubKey.modulus as string),
BigInt(n_dsc),
BigInt(k_dsc)
);
}
return {
secret: [secret],
mrz: formattedMrz.map(byte => String(byte)),
mrz: formattedMrz.map((byte) => String(byte)),
dg1_hash_offset: [dg1HashOffset.toString()], // uncomment when adding new circuits
econtent: Array.from(messagePadded).map((x) => x.toString()),
datahashes_padded_length: [messagePaddedLen.toString()],
signed_attributes: eContent.map(toUnsignedByte).map(byte => String(byte)),
signed_attributes: eContent.map(toUnsignedByte).map((byte) => String(byte)),
signature: splitToWords(
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
BigInt(n_dsc),
BigInt(k_dsc)
),
dsc_modulus: splitToWords(
BigInt(passportData.pubKey.modulus as string),
BigInt(n_dsc),
BigInt(k_dsc)
),
dsc_modulus: dsc_modulus,
attestation_id: [attestation_id],
dsc_secret: [dscSecret]
dsc_secret: [dscSecret],
};
}
@@ -118,7 +142,7 @@ export function generateCircuitInputsDisclose(
majority: string[],
bitmap: string[],
scope: string,
user_identifier: string,
user_identifier: string
) {
const pubkey_leaf = getLeaf({
signatureAlgorithm: passportData.signatureAlgorithm,
@@ -134,28 +158,32 @@ export function generateCircuitInputsDisclose(
pubkey_leaf,
mrz_bytes[0],
mrz_bytes[1],
mrz_bytes[2]
mrz_bytes[2],
]);
//console.log('commitment', commitment.toString());
const index = findIndexInTree(merkletree, commitment);
const { merkleProofSiblings, merkleProofIndices, depthForThisOne } = generateMerkleProof(merkletree, index, PUBKEY_TREE_DEPTH)
const { merkleProofSiblings, merkleProofIndices, depthForThisOne } = generateMerkleProof(
merkletree,
index,
PUBKEY_TREE_DEPTH
);
return {
secret: [secret],
attestation_id: [attestation_id],
pubkey_leaf: [pubkey_leaf.toString()],
mrz: formattedMrz.map(byte => String(byte)),
mrz: formattedMrz.map((byte) => String(byte)),
merkle_root: [merkletree.root.toString()],
merkletree_size: [BigInt(depthForThisOne).toString()],
path: merkleProofIndices.map(index => BigInt(index).toString()),
siblings: merkleProofSiblings.map(index => BigInt(index).toString()),
path: merkleProofIndices.map((index) => BigInt(index).toString()),
siblings: merkleProofSiblings.map((index) => BigInt(index).toString()),
bitmap: bitmap,
scope: [scope],
current_date: getCurrentDateYYMMDD().map(datePart => BigInt(datePart).toString()),
majority: majority.map(char => BigInt(char.charCodeAt(0)).toString()),
current_date: getCurrentDateYYMMDD().map((datePart) => BigInt(datePart).toString()),
majority: majority.map((char) => BigInt(char.charCodeAt(0)).toString()),
user_identifier: [user_identifier],
};
}
@@ -169,9 +197,9 @@ export function findIndexInTree(tree: LeanIMT, commitment: bigint): number {
index = tree.indexOf(commitment.toString() as unknown as bigint);
}
if (index === -1) {
throw new Error("This commitment was not found in the tree");
throw new Error('This commitment was not found in the tree');
} else {
// console.log(`Index of commitment in the registry: ${index}`);
}
return index;
}
}

View File

@@ -1,75 +1,85 @@
import { poseidon10, poseidon2, poseidon8 } from "poseidon-lite"
import { SignatureAlgorithm, PUBKEY_TREE_DEPTH } from "../constants/constants";
import { IMT } from '@zk-kit/imt'
import { splitToWords } from "./utils";
import { formatSigAlgNameForCircuit } from "./utils";
import { toStandardName } from "./formatNames";
import { poseidon10, poseidon2, poseidon5, poseidon8 } from 'poseidon-lite';
import { SignatureAlgorithm, PUBKEY_TREE_DEPTH } from '../constants/constants';
import { IMT } from '@zk-kit/imt';
import { hexToDecimal, splitToWords } from './utils';
import { formatSigAlgNameForCircuit } from './utils';
import { toStandardName } from './formatNames';
export function buildPubkeyTree(pubkeys: any[]) {
let leaves: bigint[] = []
let leaves: bigint[] = [];
let startTime = performance.now();
for (let i = 0; i < pubkeys.length; i++) {
const pubkey = pubkeys[i]
const pubkey = pubkeys[i];
if (i % 3000 === 0 && i !== 0) {
console.log('Processing pubkey number', i, "over", pubkeys.length);
console.log('Processing pubkey number', i, 'over', pubkeys.length);
}
const leaf = getLeaf(pubkey, i)
const leaf = getLeaf(pubkey, i);
if (!leaf) {
// console.log('no leaf for this weird signature:', i, formatSigAlgNameForCircuit(pubkey.signatureAlgorithm, pubkey.exponent))
continue
continue;
}
leaves.push(leaf)
leaves.push(leaf);
}
const tree = new IMT(poseidon2, PUBKEY_TREE_DEPTH, 0, 2, leaves)
console.log('pubkey tree built in', performance.now() - startTime, 'ms')
const tree = new IMT(poseidon2, PUBKEY_TREE_DEPTH, 0, 2, leaves);
console.log('pubkey tree built in', performance.now() - startTime, 'ms');
return tree
return tree;
}
export function getLeaf(pubkey: any, i?: number): bigint {
if (!pubkey?.modulus && pubkey?.pubKey?.modulus) {
pubkey.modulus = pubkey.pubKey.modulus
pubkey.exponent = pubkey.pubKey.exponent
pubkey.modulus = pubkey.pubKey.modulus;
pubkey.exponent = pubkey.pubKey.exponent;
}
if (!pubkey?.publicKeyQ && pubkey?.pubKey?.publicKeyQ) {
pubkey.publicKeyQ = pubkey.pubKey.publicKeyQ
pubkey.publicKeyQ = pubkey.pubKey.publicKeyQ;
}
const sigAlgFormatted = toStandardName(pubkey.signatureAlgorithm)
const sigAlgFormattedForCircuit = formatSigAlgNameForCircuit(sigAlgFormatted, pubkey.exponent)
const sigAlgFormatted = toStandardName(pubkey.signatureAlgorithm);
const sigAlgFormattedForCircuit = formatSigAlgNameForCircuit(sigAlgFormatted, pubkey.exponent);
if (
sigAlgFormattedForCircuit === "sha256WithRSAEncryption_65537"
|| sigAlgFormattedForCircuit === "sha256WithRSAEncryption_3"
|| sigAlgFormattedForCircuit === "sha1WithRSAEncryption_65537"
|| sigAlgFormattedForCircuit === "sha256WithRSASSAPSS_65537"
|| sigAlgFormattedForCircuit === "sha256WithRSASSAPSS_3"
|| sigAlgFormattedForCircuit === "sha512WithRSAEncryption_65537"
sigAlgFormattedForCircuit === 'sha256WithRSAEncryption_65537' ||
sigAlgFormattedForCircuit === 'sha256WithRSAEncryption_3' ||
sigAlgFormattedForCircuit === 'sha1WithRSAEncryption_65537' ||
sigAlgFormattedForCircuit === 'sha256WithRSASSAPSS_65537' ||
sigAlgFormattedForCircuit === 'sha256WithRSASSAPSS_3' ||
sigAlgFormattedForCircuit === 'sha512WithRSAEncryption_65537'
) {
const pubkeyChunked = splitToWords(BigInt(pubkey.modulus), BigInt(230), BigInt(9));
const leaf = poseidon10([SignatureAlgorithm[sigAlgFormattedForCircuit], ...pubkeyChunked])
const leaf = poseidon10([SignatureAlgorithm[sigAlgFormattedForCircuit], ...pubkeyChunked]);
try {
return leaf
return leaf;
} catch (err) {
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey)
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey);
}
} else if (
sigAlgFormattedForCircuit === "ecdsa_with_SHA1"
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA224"
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA384"
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA256"
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA512"
sigAlgFormattedForCircuit === 'ecdsa_with_SHA1' ||
sigAlgFormattedForCircuit === 'ecdsa_with_SHA224' ||
sigAlgFormattedForCircuit === 'ecdsa_with_SHA384' ||
sigAlgFormattedForCircuit === 'ecdsa_with_SHA256' ||
sigAlgFormattedForCircuit === 'ecdsa_with_SHA512'
) {
try {
// this will be replaced by just X and Y or pubkey in publicKeyQ
return poseidon8([SignatureAlgorithm[sigAlgFormattedForCircuit], pubkey.pub, pubkey.prime, pubkey.a, pubkey.b, pubkey.generator, pubkey.order, pubkey.cofactor])
const [x, y, a, p] = pubkey.publicKeyQ.replace(/[()]/g, '').split(',');
// ! @TODO check if this is correct
return poseidon5([
SignatureAlgorithm[sigAlgFormattedForCircuit],
hexToDecimal(x), // pub.x
hexToDecimal(y), // pub.y
hexToDecimal(p), // prime
hexToDecimal(a), // a
// pubkey.b ? pubkey.b : BigInt(0), // null then 0
// pubkey.generator ? pubkey.generator : BigInt(0), // null then 0
// pubkey.order ? pubkey.order : BigInt(0), // null then 0
// pubkey.cofactor ? pubkey.cofactor : BigInt(0), // null then 0
]);
} catch (err) {
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey)
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey);
}
}
}