From 345cccbb72860cd720685c8c11e86e33fa242165 Mon Sep 17 00:00:00 2001 From: motemotech Date: Thu, 16 Jan 2025 16:57:27 +0900 Subject: [PATCH 1/4] change dependency --- .../circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuits/circuits/utils/circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom b/circuits/circuits/utils/circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom index 80e7067ab..d05590e39 100644 --- a/circuits/circuits/utils/circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom +++ b/circuits/circuits/utils/circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom @@ -1,6 +1,6 @@ pragma circom 2.1.9; -include "@zk-email/circuits/lib/fp.circom"; +include "@zk-email/circuits/lib/bigint.circom"; include "./pkcs1v1_5Padding.circom"; include "../FpPowMod.circom"; From dd51c49b720e3d8192e2013e5750890a70b1cb56 Mon Sep 17 00:00:00 2001 From: motemotech Date: Thu, 16 Jan 2025 21:41:46 +0900 Subject: [PATCH 2/4] lint --- circuits/tests/utils/rsaPkcs1v1_5.test.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/circuits/tests/utils/rsaPkcs1v1_5.test.ts b/circuits/tests/utils/rsaPkcs1v1_5.test.ts index a2830b6b6..25501c287 100644 --- a/circuits/tests/utils/rsaPkcs1v1_5.test.ts +++ b/circuits/tests/utils/rsaPkcs1v1_5.test.ts @@ -47,10 +47,7 @@ describe('VerifyRsaPkcs1v1_5 Circuit Test', function () { const invalidSignature = signature.map((byte: string) => String((parseInt(byte) + 1) % 256)); const circuit = await wasmTester( - path.join( - __dirname, - `../../circuits/tests/utils/rsa/test_${algorithm}.circom` - ), + path.join(__dirname, `../../circuits/tests/utils/rsa/test_${algorithm}.circom`), { include: ['node_modules', './node_modules/@zk-kit/binary-merkle-root.circom/src'], } @@ -72,10 +69,7 @@ describe('VerifyRsaPkcs1v1_5 Circuit Test', function () { const invalidMessage = message.map((byte: string) => String((parseInt(byte) + 1) % 256)); const circuit = await wasmTester( - path.join( - __dirname, - `../../circuits/tests/utils/rsa/test_${algorithm}.circom` - ), + path.join(__dirname, `../../circuits/tests/utils/rsa/test_${algorithm}.circom`), { include: ['node_modules', './node_modules/@zk-kit/binary-merkle-root.circom/src'], } From 9f41228e5a8d7cdf043e59a3e933ff6ee7559c78 Mon Sep 17 00:00:00 2001 From: motemotech Date: Fri, 17 Jan 2025 03:11:13 +0900 Subject: [PATCH 3/4] added sha224 rsa --- .../utils/rsa/test_rsa_sha224_65537_2048.circom | 13 +++++++++++++ .../tests/utils/generateMockInputsInCircuits.ts | 6 ++++++ circuits/tests/utils/rsaPkcs1v1_5.test.ts | 1 + common/src/utils/types.ts | 1 + 4 files changed, 21 insertions(+) create mode 100644 circuits/circuits/tests/utils/rsa/test_rsa_sha224_65537_2048.circom diff --git a/circuits/circuits/tests/utils/rsa/test_rsa_sha224_65537_2048.circom b/circuits/circuits/tests/utils/rsa/test_rsa_sha224_65537_2048.circom new file mode 100644 index 000000000..d979eb5cb --- /dev/null +++ b/circuits/circuits/tests/utils/rsa/test_rsa_sha224_65537_2048.circom @@ -0,0 +1,13 @@ +pragma circom 2.1.9; + +include "../../../utils/crypto/signature/rsa/verifyRsa65537Pkcs1v1_5.circom"; + +template VerifyRsaPkcs1v1_5Tester() { + signal input signature[35]; + signal input modulus[35]; + signal input message[35]; + + VerifyRsa65537Pkcs1v1_5(120,35,224)(signature, modulus, message); +} + +component main = VerifyRsaPkcs1v1_5Tester(); \ No newline at end of file diff --git a/circuits/tests/utils/generateMockInputsInCircuits.ts b/circuits/tests/utils/generateMockInputsInCircuits.ts index fe5665120..fc2915979 100644 --- a/circuits/tests/utils/generateMockInputsInCircuits.ts +++ b/circuits/tests/utils/generateMockInputsInCircuits.ts @@ -6,6 +6,7 @@ import { getNAndK, } from '../../../common/src/utils/utils'; import { SignatureAlgorithm } from '../../../common/src/utils/types'; +import { sha224 } from 'hash.js'; export const generateMockRsaPkcs1v1_5Inputs = (signatureAlgorithm: SignatureAlgorithm) => { let privateKey: string; @@ -33,6 +34,11 @@ export const generateMockRsaPkcs1v1_5Inputs = (signatureAlgorithm: SignatureAlgo signAlgorithm = signatureAlgorithm.includes('sha256') ? 'sha256' : 'sha512'; publicExponent = 65537; break; + case 'rsa_sha224_65537_2048': + modulusLength = 2048; + signAlgorithm = 'sha224'; + publicExponent = 65537; + break; default: throw new Error(`Unsupported signature algorithm: ${signatureAlgorithm}`); } diff --git a/circuits/tests/utils/rsaPkcs1v1_5.test.ts b/circuits/tests/utils/rsaPkcs1v1_5.test.ts index 25501c287..46a85f27f 100644 --- a/circuits/tests/utils/rsaPkcs1v1_5.test.ts +++ b/circuits/tests/utils/rsaPkcs1v1_5.test.ts @@ -14,6 +14,7 @@ describe('VerifyRsaPkcs1v1_5 Circuit Test', function () { 'rsa_sha256_65537_3072', 'rsa_sha256_65537_4096', 'rsa_sha512_65537_4096', + 'rsa_sha224_65537_2048', ]; rsaAlgorithms.forEach((algorithm) => { diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index 218746cf8..e8d9d79e4 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -31,6 +31,7 @@ export type SignatureAlgorithm = | 'rsa_sha256_65537_3072' | 'rsa_sha256_65537_4096' | 'rsa_sha512_65537_4096' + | 'rsa_sha224_65537_2048' | 'rsapss_sha256_65537_3072' | 'rsapss_sha256_65537_4096' | 'rsapss_sha256_3_2048' From 2527b1298935d27e1a5872456162c68e5431897a Mon Sep 17 00:00:00 2001 From: motemotech Date: Fri, 17 Jan 2025 04:00:19 +0900 Subject: [PATCH 4/4] delete unused import --- .../utils/generateMockInputsInCircuits.ts | 1 - common/src/utils/generateInputs.ts | 8 +- common/src/utils/parsePassportData.ts | 224 +++++++++--------- common/src/utils/types.ts | 2 +- 4 files changed, 114 insertions(+), 121 deletions(-) diff --git a/circuits/tests/utils/generateMockInputsInCircuits.ts b/circuits/tests/utils/generateMockInputsInCircuits.ts index fc2915979..da5fc9f38 100644 --- a/circuits/tests/utils/generateMockInputsInCircuits.ts +++ b/circuits/tests/utils/generateMockInputsInCircuits.ts @@ -6,7 +6,6 @@ import { getNAndK, } from '../../../common/src/utils/utils'; import { SignatureAlgorithm } from '../../../common/src/utils/types'; -import { sha224 } from 'hash.js'; export const generateMockRsaPkcs1v1_5Inputs = (signatureAlgorithm: SignatureAlgorithm) => { let privateKey: string; diff --git a/common/src/utils/generateInputs.ts b/common/src/utils/generateInputs.ts index 9f2faacc6..2c7f6fbf8 100644 --- a/common/src/utils/generateInputs.ts +++ b/common/src/utils/generateInputs.ts @@ -223,8 +223,8 @@ export function generateCircuitInputsProve( const dg1PaddingFunction = passportMetadata.dg1HashFunction === 'sha1' || - passportMetadata.dg1HashFunction === 'sha224' || - passportMetadata.dg1HashFunction === 'sha256' + passportMetadata.dg1HashFunction === 'sha224' || + passportMetadata.dg1HashFunction === 'sha256' ? shaPad : sha384_512Pad; @@ -235,8 +235,8 @@ export function generateCircuitInputsProve( const eContentPaddingFunction = passportMetadata.eContentHashFunction === 'sha1' || - passportMetadata.eContentHashFunction === 'sha224' || - passportMetadata.eContentHashFunction === 'sha256' + passportMetadata.eContentHashFunction === 'sha224' || + passportMetadata.eContentHashFunction === 'sha256' ? shaPad : sha384_512Pad; const [signedAttrPadded, signedAttrPaddedLen] = eContentPaddingFunction( diff --git a/common/src/utils/parsePassportData.ts b/common/src/utils/parsePassportData.ts index 06d6033b6..0a5858e4a 100644 --- a/common/src/utils/parsePassportData.ts +++ b/common/src/utils/parsePassportData.ts @@ -2,153 +2,147 @@ import { PassportData } from '../../../common/src/utils/types'; import { findSubarrayIndex, formatMrz, getHashLen, hash } from './utils'; import { parseCertificateSimple } from './certificate_parsing/parseCertificateSimple'; import { - CertificateData, - PublicKeyDetailsECDSA, - PublicKeyDetailsRSA, - PublicKeyDetailsRSAPSS, + CertificateData, + PublicKeyDetailsECDSA, + PublicKeyDetailsRSA, + PublicKeyDetailsRSAPSS, } from './certificate_parsing/dataStructure'; import { hashAlgos } from '../constants/constants'; import { brutforceSignatureAlgorithm } from './brutForcePassportSignature'; import { DscCertificateMetaData, parseDscCertificateData } from './parseDscCertificateData'; export interface PassportMetadata { - dataGroups: string; - dg1HashFunction: string; - dg1HashOffset: number; - dgPaddingBytes: number; - eContentSize: number; - eContentHashFunction: string; - eContentHashOffset: number; - signedAttrSize: number; - signedAttrHashFunction: string; - signatureAlgorithm: string; - saltLength: number; - curveOrExponent: string; - signatureAlgorithmBits: number; - countryCode: string; - cscaFound: boolean; - cscaHashFunction: string; - cscaSignature: string; - cscaSaltLength: number; - cscaCurveOrExponent: string; - cscaSignatureAlgorithmBits: number; - dsc: string; + dataGroups: string; + dg1HashFunction: string; + dg1HashOffset: number; + dgPaddingBytes: number; + eContentSize: number; + eContentHashFunction: string; + eContentHashOffset: number; + signedAttrSize: number; + signedAttrHashFunction: string; + signatureAlgorithm: string; + saltLength: number; + curveOrExponent: string; + signatureAlgorithmBits: number; + countryCode: string; + cscaFound: boolean; + cscaHashFunction: string; + cscaSignature: string; + cscaSaltLength: number; + cscaCurveOrExponent: string; + cscaSignatureAlgorithmBits: number; + dsc: string; } function findHashSizeOfEContent(eContent: number[], signedAttr: number[]) { - for (const hashFunction of hashAlgos) { - const hashValue = hash(hashFunction, eContent); - const hashOffset = findSubarrayIndex(signedAttr, hashValue as number[]); - if (hashOffset !== -1) { - return { hashFunction, offset: hashOffset }; - } + for (const hashFunction of hashAlgos) { + const hashValue = hash(hashFunction, eContent); + const hashOffset = findSubarrayIndex(signedAttr, hashValue as number[]); + if (hashOffset !== -1) { + return { hashFunction, offset: hashOffset }; } - return { hashFunction: 'unknown', offset: -1 }; + } + return { hashFunction: 'unknown', offset: -1 }; } function findDG1HashInEContent( - mrz: string, - eContent: number[] + mrz: string, + eContent: number[] ): { hash: number[]; hashFunction: string; offset: number } | null { - const formattedMrz = formatMrz(mrz); + const formattedMrz = formatMrz(mrz); - for (const hashFunction of hashAlgos) { - const hashValue = hash(hashFunction, formattedMrz); - const normalizedHash = (hashValue as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); - const hashOffset = findSubarrayIndex(eContent, normalizedHash); + for (const hashFunction of hashAlgos) { + const hashValue = hash(hashFunction, formattedMrz); + const normalizedHash = (hashValue as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); + const hashOffset = findSubarrayIndex(eContent, normalizedHash); - if (hashOffset !== -1) { - return { hash: hashValue as number[], hashFunction, offset: hashOffset }; - } + if (hashOffset !== -1) { + return { hash: hashValue as number[], hashFunction, offset: hashOffset }; } - return null; + } + return null; } function getDgPaddingBytes(passportData: PassportData, dg1HashFunction: string): number { - const formattedMrz = formatMrz(passportData.mrz); - const hashValue = hash(dg1HashFunction, formattedMrz); - const normalizedHash = (hashValue as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); - const dg1HashOffset = findSubarrayIndex(passportData.eContent, normalizedHash); - const dg2Hash = passportData.dg2Hash; - const normalizedDg2Hash = (dg2Hash as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); - const dg2HashOffset = findSubarrayIndex(passportData.eContent, normalizedDg2Hash); - return dg2HashOffset - dg1HashOffset - getHashLen(dg1HashFunction); + const formattedMrz = formatMrz(passportData.mrz); + const hashValue = hash(dg1HashFunction, formattedMrz); + const normalizedHash = (hashValue as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); + const dg1HashOffset = findSubarrayIndex(passportData.eContent, normalizedHash); + const dg2Hash = passportData.dg2Hash; + const normalizedDg2Hash = (dg2Hash as number[]).map((byte) => (byte > 127 ? byte - 256 : byte)); + const dg2HashOffset = findSubarrayIndex(passportData.eContent, normalizedDg2Hash); + return dg2HashOffset - dg1HashOffset - getHashLen(dg1HashFunction); } export function getCountryCodeFromMrz(mrz: string): string { - return mrz.substring(2, 5); + return mrz.substring(2, 5); } export function getCurveOrExponent(certData: CertificateData): string { - if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') { - return (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent; - } - return (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve; + if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') { + return (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent; + } + return (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve; } - - - - export function parsePassportData(passportData: PassportData): PassportMetadata { - const dg1HashInfo = passportData.mrz - ? findDG1HashInEContent(passportData.mrz, passportData.eContent) - : null; + const dg1HashInfo = passportData.mrz + ? findDG1HashInEContent(passportData.mrz, passportData.eContent) + : null; - const dg1HashFunction = dg1HashInfo?.hashFunction || 'unknown'; - const dg1HashOffset = dg1HashInfo?.offset || 0; - let dgPaddingBytes = -1; - try { - dgPaddingBytes = getDgPaddingBytes(passportData, dg1HashFunction); - } catch (error) { - console.error('Error getting DG padding bytes:', error); - } - const { hashFunction: eContentHashFunction, offset: eContentHashOffset } = findHashSizeOfEContent( - passportData.eContent, - passportData.signedAttr - ); + const dg1HashFunction = dg1HashInfo?.hashFunction || 'unknown'; + const dg1HashOffset = dg1HashInfo?.offset || 0; + let dgPaddingBytes = -1; + try { + dgPaddingBytes = getDgPaddingBytes(passportData, dg1HashFunction); + } catch (error) { + console.error('Error getting DG padding bytes:', error); + } + const { hashFunction: eContentHashFunction, offset: eContentHashOffset } = findHashSizeOfEContent( + passportData.eContent, + passportData.signedAttr + ); - const brutForcedPublicKeyDetails = brutforceSignatureAlgorithm(passportData); + const brutForcedPublicKeyDetails = brutforceSignatureAlgorithm(passportData); - let parsedDsc = null; - let dscSignatureAlgorithmBits = 0; + let parsedDsc = null; + let dscSignatureAlgorithmBits = 0; - let brutForcedPublicKeyDetailsDsc: DscCertificateMetaData; + let brutForcedPublicKeyDetailsDsc: DscCertificateMetaData; - if (passportData.dsc) { - parsedDsc = parseCertificateSimple(passportData.dsc); - dscSignatureAlgorithmBits = parseInt(parsedDsc.publicKeyDetails?.bits || '0'); + if (passportData.dsc) { + parsedDsc = parseCertificateSimple(passportData.dsc); + dscSignatureAlgorithmBits = parseInt(parsedDsc.publicKeyDetails?.bits || '0'); - brutForcedPublicKeyDetailsDsc = parseDscCertificateData(parsedDsc) + brutForcedPublicKeyDetailsDsc = parseDscCertificateData(parsedDsc); + } - - } - - return { - dataGroups: - passportData.dgPresents - ?.toString() - .split(',') - .map((item) => item.replace('DG', '')) - .join(',') || 'None', - dg1HashFunction, - dg1HashOffset, - dgPaddingBytes, - eContentSize: passportData.eContent?.length || 0, - eContentHashFunction, - eContentHashOffset, - signedAttrSize: passportData.signedAttr?.length || 0, - signedAttrHashFunction: brutForcedPublicKeyDetails.hashAlgorithm, - signatureAlgorithm: brutForcedPublicKeyDetails.signatureAlgorithm, - saltLength: brutForcedPublicKeyDetails.saltLength, - curveOrExponent: parsedDsc ? getCurveOrExponent(parsedDsc) : 'unknown', - signatureAlgorithmBits: dscSignatureAlgorithmBits, - countryCode: passportData.mrz ? getCountryCodeFromMrz(passportData.mrz) : 'unknown', - cscaFound: brutForcedPublicKeyDetailsDsc.cscaFound, - cscaHashFunction: brutForcedPublicKeyDetailsDsc.cscaHashAlgorithm, - cscaSignature: brutForcedPublicKeyDetailsDsc.cscaSignatureAlgorithm, - cscaSaltLength: brutForcedPublicKeyDetailsDsc.cscaSaltLength, - cscaCurveOrExponent: brutForcedPublicKeyDetailsDsc.cscaCurveOrExponent, - cscaSignatureAlgorithmBits: brutForcedPublicKeyDetailsDsc.cscaSignatureAlgorithmBits, - dsc: passportData.dsc, - }; -} \ No newline at end of file + return { + dataGroups: + passportData.dgPresents + ?.toString() + .split(',') + .map((item) => item.replace('DG', '')) + .join(',') || 'None', + dg1HashFunction, + dg1HashOffset, + dgPaddingBytes, + eContentSize: passportData.eContent?.length || 0, + eContentHashFunction, + eContentHashOffset, + signedAttrSize: passportData.signedAttr?.length || 0, + signedAttrHashFunction: brutForcedPublicKeyDetails.hashAlgorithm, + signatureAlgorithm: brutForcedPublicKeyDetails.signatureAlgorithm, + saltLength: brutForcedPublicKeyDetails.saltLength, + curveOrExponent: parsedDsc ? getCurveOrExponent(parsedDsc) : 'unknown', + signatureAlgorithmBits: dscSignatureAlgorithmBits, + countryCode: passportData.mrz ? getCountryCodeFromMrz(passportData.mrz) : 'unknown', + cscaFound: brutForcedPublicKeyDetailsDsc.cscaFound, + cscaHashFunction: brutForcedPublicKeyDetailsDsc.cscaHashAlgorithm, + cscaSignature: brutForcedPublicKeyDetailsDsc.cscaSignatureAlgorithm, + cscaSaltLength: brutForcedPublicKeyDetailsDsc.cscaSaltLength, + cscaCurveOrExponent: brutForcedPublicKeyDetailsDsc.cscaCurveOrExponent, + cscaSignatureAlgorithmBits: brutForcedPublicKeyDetailsDsc.cscaSignatureAlgorithmBits, + dsc: passportData.dsc, + }; +} diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index e8d9d79e4..4a7f7ac5f 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -47,7 +47,7 @@ export type SignatureAlgorithm = | 'ecdsa_sha1_brainpoolP224r1_224' | 'ecdsa_sha224_brainpoolP224r1_224' | 'ecdsa_sha256_brainpoolP224r1_224' - | 'ecdsa_sha512_brainpoolP512r1_512' + | 'ecdsa_sha512_brainpoolP512r1_512'; export type Proof = { proof: {