From ed1397b923678bca57531aa8666e4a5aa25812f7 Mon Sep 17 00:00:00 2001 From: 0xvikasrushi <0xvikas@gmail.com> Date: Sun, 28 Jul 2024 06:21:48 +0000 Subject: [PATCH] feat: generate inputs for ecdsa with sha1 --- common/src/utils/generateInputs.ts | 142 +++++++++++++++++------------ common/src/utils/pubkeyTree.ts | 86 +++++++++-------- 2 files changed, 133 insertions(+), 95 deletions(-) diff --git a/common/src/utils/generateInputs.ts b/common/src/utils/generateInputs.ts index 9482eaa13..18f1fe74e 100644 --- a/common/src/utils/generateInputs.ts +++ b/common/src/utils/generateInputs.ts @@ -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; -} \ No newline at end of file +} diff --git a/common/src/utils/pubkeyTree.ts b/common/src/utils/pubkeyTree.ts index da5b4bcb4..17bcdfa33 100644 --- a/common/src/utils/pubkeyTree.ts +++ b/common/src/utils/pubkeyTree.ts @@ -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); } } }