diff --git a/app/src/screens/MainScreen.tsx b/app/src/screens/MainScreen.tsx index b12de32ba..c060525a8 100644 --- a/app/src/screens/MainScreen.tsx +++ b/app/src/screens/MainScreen.tsx @@ -143,7 +143,7 @@ const MainScreen: React.FC = () => { // console.log('CSCA Proof received:', cscaProof); // if ((cscaProof !== null) && (localProof !== null)) { // const sendTransaction = async () => { - // const sigAlgFormatted = formatSigAlgNameForCircuit(passportData.signatureAlgorithm, passportData.pubKey.exponent); + // const sigAlgFormatted = formatSigAlgNameForCircuit(passportData.signatureAlgorithm, passportData.pubKey.exponent); // this is old formatting // const sigAlgIndex = SignatureAlgorithmIndex[sigAlgFormatted as keyof typeof SignatureAlgorithmIndex] // console.log("local proof already generated, sending transaction"); // const provider = new ethers.JsonRpcProvider(RPC_URL); diff --git a/app/src/screens/ProveScreen.tsx b/app/src/screens/ProveScreen.tsx index a41312bec..ad27ff2d1 100644 --- a/app/src/screens/ProveScreen.tsx +++ b/app/src/screens/ProveScreen.tsx @@ -37,7 +37,7 @@ const ProveScreen: React.FC = ({ setSheetRegisterIsOpen }) => const [socket, setSocket] = useState(null); const [isConnecting, setIsConnecting] = useState(false); - const { signatureAlgorithm, hashFunction } = getSignatureAlgorithm(passportData.dsc as string); + const { signatureAlgorithm, hashFunction } = getSignatureAlgorithm(passportData.dsc); const circuitName = getCircuitName(selectedApp.circuit, signatureAlgorithm, hashFunction); const waitForSocketConnection = (socket: Socket): Promise => { diff --git a/app/src/stores/userStore.ts b/app/src/stores/userStore.ts index 359163d5b..e31eb7a81 100644 --- a/app/src/stores/userStore.ts +++ b/app/src/stores/userStore.ts @@ -10,6 +10,7 @@ import * as Keychain from 'react-native-keychain'; import * as amplitude from '@amplitude/analytics-react-native'; import { loadPassportData, loadSecret, loadSecretOrCreateIt, storePassportData } from '../utils/keychain'; import { generateDscSecret } from '../../../common/src/utils/csca'; +import { genMockPassportData } from '../../../common/src/utils/genMockPassportData'; interface UserState { passportNumber: string @@ -43,7 +44,7 @@ const useUserStore = create((set, get) => ({ dateOfExpiry: DEFAULT_DOE ?? "", dscSecret: null, registered: false, - passportData: mockPassportData_sha256_rsa_65537, + passportData: genMockPassportData("rsa_sha256", "FRA", "19900101", "20300101"), secret: "", cscaProof: null, localProof: null, diff --git a/app/src/utils/nfcScanner.ts b/app/src/utils/nfcScanner.ts index d416032df..056e6b15b 100644 --- a/app/src/utils/nfcScanner.ts +++ b/app/src/utils/nfcScanner.ts @@ -1,7 +1,6 @@ import { NativeModules, Platform } from 'react-native'; // @ts-ignore import PassportReader from 'react-native-passport-reader'; -import { toStandardName } from '../../../common/src/utils/formatNames'; import { checkInputs } from '../utils/utils'; import { PassportData } from '../../../common/src/utils/types'; import forge from 'node-forge'; @@ -121,7 +120,6 @@ const handleResponseIOS = async ( const eContentBase64 = parsed.eContentBase64; // this is what we call concatenatedDataHashes in android world const signedAttributes = parsed.signedAttributes; // this is what we call eContent in android world - const signatureAlgorithm = parsed.signatureAlgorithm; const mrz = parsed.passportMRZ; const signatureBase64 = parsed.signatureBase64; console.log('dataGroupsPresent', parsed.dataGroupsPresent) @@ -131,19 +129,12 @@ const handleResponseIOS = async ( console.log('isChipAuthenticationSupported', parsed.isChipAuthenticationSupported) console.log('residenceAddress', parsed.residenceAddress) console.log('passportPhoto', parsed.passportPhoto.substring(0, 100) + '...') - console.log('signatureAlgorithm', signatureAlgorithm) console.log('encapsulatedContentDigestAlgorithm', parsed.encapsulatedContentDigestAlgorithm) console.log('parsed.documentSigningCertificate', parsed.documentSigningCertificate) const pem = JSON.parse(parsed.documentSigningCertificate).PEM.replace(/\n/g, ''); - const certificate = forge.pki.certificateFromPem(pem); console.log('pem', pem) try { - const publicKey = certificate.publicKey; - //console.log('publicKey', publicKey); - - const modulus = (publicKey as any).n.toString(10); - const eContentArray = Array.from(Buffer.from(signedAttributes, 'base64')); const signedEContentArray = eContentArray.map(byte => byte > 127 ? byte - 256 : byte); @@ -153,15 +144,9 @@ const handleResponseIOS = async ( const encryptedDigestArray = Array.from(Buffer.from(signatureBase64, 'base64')).map(byte => byte > 127 ? byte - 256 : byte); //amplitude.track('Sig alg before conversion: ' + signatureAlgorithm); - console.log('signatureAlgorithm before conversion', signatureAlgorithm); const passportData = { mrz, - signatureAlgorithm: toStandardName(signatureAlgorithm), dsc: pem, - pubKey: { - modulus: modulus, - exponent: (publicKey as any).e.toString(10), - }, dataGroupHashes: concatenatedDataHashesArraySigned, eContent: signedEContentArray, encryptedDigest: encryptedDigestArray, @@ -169,8 +154,8 @@ const handleResponseIOS = async ( mockUser: false }; useUserStore.getState().registerPassportData(passportData) - const sigAlgName = getSignatureAlgorithm(pem); - const circuitName = getCircuitName("prove", sigAlgName.signatureAlgorithm, sigAlgName.hashFunction); + const { signatureAlgorithm, hashFunction } = getSignatureAlgorithm(pem); + const circuitName = getCircuitName("prove", signatureAlgorithm, hashFunction); downloadZkey(circuitName as any); useNavigationStore.getState().setSelectedTab("next"); } catch (e: any) { @@ -191,10 +176,6 @@ const handleResponseAndroid = async ( ) => { const { mrz, - signatureAlgorithm, - modulus, - curveName, - publicKeyQ, eContent, encryptedDigest, photo, @@ -210,22 +191,9 @@ const handleResponseAndroid = async ( //amplitude.track('Sig alg before conversion: ' + signatureAlgorithm); const pem = "-----BEGIN CERTIFICATE-----" + documentSigningCertificate + "-----END CERTIFICATE-----" - - const cert = forge.pki.certificateFromPem(pem); - console.log('cert', cert); - const publicKey = cert.publicKey; - console.log('publicKey', publicKey); - const passportData: PassportData = { mrz: mrz.replace(/\n/g, ''), - signatureAlgorithm: toStandardName(signatureAlgorithm), dsc: pem, - pubKey: { - modulus: modulus, - exponent: (publicKey as any).e.toString(10), - curveName: curveName, - publicKeyQ: publicKeyQ, - }, dataGroupHashes: JSON.parse(encapContent), eContent: JSON.parse(eContent), encryptedDigest: JSON.parse(encryptedDigest), @@ -240,8 +208,6 @@ const handleResponseAndroid = async ( }, null, 2)); console.log('mrz', passportData.mrz); - console.log('signatureAlgorithm', passportData.signatureAlgorithm); - console.log('pubKey', passportData.pubKey); console.log('dataGroupHashes', passportData.dataGroupHashes); console.log('eContent', passportData.eContent); console.log('encryptedDigest', passportData.encryptedDigest); @@ -255,8 +221,8 @@ const handleResponseAndroid = async ( console.log("documentSigningCertificate", documentSigningCertificate) useUserStore.getState().registerPassportData(passportData) - const sigAlgName = getSignatureAlgorithm(pem); - const circuitName = getCircuitName("prove", sigAlgName.signatureAlgorithm, sigAlgName.hashFunction); + const { signatureAlgorithm, hashFunction } = getSignatureAlgorithm(pem); + const circuitName = getCircuitName("prove", signatureAlgorithm, hashFunction); downloadZkey(circuitName as any); useNavigationStore.getState().setSelectedTab("next"); }; diff --git a/app/src/utils/qrCode.ts b/app/src/utils/qrCode.ts index 61fc3f5a7..a4920bc7b 100644 --- a/app/src/utils/qrCode.ts +++ b/app/src/utils/qrCode.ts @@ -56,7 +56,7 @@ const handleQRCodeScan = (result: string, toast: any, setSelectedApp: any, setSe console.log(result); const parsedJson = JSON.parse(result); const app: AppType = reconstructAppType(parsedJson); - const dsc = useUserStore.getState().passportData?.dsc; + const dsc = useUserStore.getState().passportData.dsc; const sigAlgName = getSignatureAlgorithm(dsc!); const circuitName = getCircuitName(app.circuit, sigAlgName.signatureAlgorithm, sigAlgName.hashFunction); downloadZkey(circuitName as any); diff --git a/circuits/tests/ofac/ofac.test.ts b/circuits/tests/ofac/ofac.test.ts index 8375d3a86..e1bf9a479 100644 --- a/circuits/tests/ofac/ofac.test.ts +++ b/circuits/tests/ofac/ofac.test.ts @@ -137,7 +137,6 @@ describe('OFAC - Passport number match', function () { expect.fail('Expected an error but none was thrown.'); } catch (error) { expect(error.message).to.include('Assert Failed'); - expect(error.message).to.include('line: 43'); expect(error.message).to.not.include('SMTVerify'); } }); @@ -225,7 +224,6 @@ describe('OFAC - Name and DOB match', function () { expect.fail('Expected an error but none was thrown.'); } catch (error) { expect(error.message).to.include('Assert Failed'); - expect(error.message).to.include('line: 54'); expect(error.message).to.not.include('SMTVerify'); } }); @@ -313,7 +311,6 @@ describe('OFAC - Name match', function () { expect.fail('Expected an error but none was thrown.'); } catch (error) { expect(error.message).to.include('Assert Failed'); - expect(error.message).to.include('line: 46'); expect(error.message).to.not.include('SMTVerify'); } }); diff --git a/circuits/tests/register.test.ts b/circuits/tests/register.test.ts index 6f942e66b..d1d081788 100644 --- a/circuits/tests/register.test.ts +++ b/circuits/tests/register.test.ts @@ -28,7 +28,7 @@ sigAlgs.forEach(({ sigAlg, hashFunction }) => { const secret = BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString(); const dscSecret = BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString(); - const { modulus, x, y } = getSignatureAlgorithm(passportData.dsc as string); + const { modulus, x, y } = getSignatureAlgorithm(passportData.dsc); const inputs = generateCircuitInputsRegister( secret, diff --git a/common/scripts/passportData/sha256_sha1mrz_rsa_65537.ts b/common/scripts/passportData/sha256_sha1mrz_rsa_65537.ts deleted file mode 100644 index 3cfaa530c..000000000 --- a/common/scripts/passportData/sha256_sha1mrz_rsa_65537.ts +++ /dev/null @@ -1,81 +0,0 @@ -import assert from "assert"; -import { PassportData } from "../../src/utils/types"; -import { hash, assembleEContent, formatAndConcatenateDataHashes, formatMrz, hexToDecimal, arraysAreEqual, findSubarrayIndex } from "../../src/utils/utils"; -import * as forge from 'node-forge'; -import { writeFileSync, readFileSync } from "fs"; -import { mock_dsc_key_sha256_rsa_4096 } from "../../src/constants/mockCertificates"; -import { sampleDataHashes_large } from "../../src/constants/sampleDataHashes"; - -const sampleMRZ = "P c.charCodeAt(0)); - - return { - mrz: sampleMRZ, - signatureAlgorithm: signatureAlgorithm, - pubKey: { - modulus: hexToDecimal(modulus), - exponent: '65537', - }, - dataGroupHashes: concatenatedDataHashes, - eContent: eContent, - encryptedDigest: signatureBytes, - photoBase64: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..." - } -} - -function verify(passportData: PassportData): boolean { - const { mrz, signatureAlgorithm, pubKey, dataGroupHashes, eContent, encryptedDigest } = passportData; - const formattedMrz = formatMrz(mrz); - const mrzHash = hash("sha1WithRSAEncryption", formattedMrz); - const dg1HashOffset = findSubarrayIndex(dataGroupHashes, mrzHash) - console.log('dg1HashOffset', dg1HashOffset); - assert(dg1HashOffset !== -1, 'MRZ hash index not found in dataGroupHashes'); - - const concatHash = hash(signatureAlgorithm, dataGroupHashes) - assert( - arraysAreEqual( - concatHash, - eContent.slice(eContent.length - hashLen) - ), - 'concatHash is not at the right place in eContent' - ); - - const modulus = new forge.jsbn.BigInteger(pubKey.modulus, 10); - const exponent = new forge.jsbn.BigInteger(pubKey.exponent, 10); - const rsaPublicKey = forge.pki.rsa.setPublicKey(modulus, exponent); - - const md = forge.md.sha256.create(); - md.update(forge.util.binary.raw.encode(new Uint8Array(eContent))); - - const signature = Buffer.from(encryptedDigest).toString( - 'binary', - ); - - return rsaPublicKey.verify(md.digest().bytes(), signature); -} - -const mockPassportData = genMockPassportData_sha256WithRSAEncryption_sha1MRZ_65537(); -console.log("Passport Data:", JSON.stringify(mockPassportData, null, 2)); -console.log("Signature valid:", verify(mockPassportData)); - -writeFileSync(__dirname + '/passportData.json', JSON.stringify(mockPassportData, null, 2)); \ No newline at end of file diff --git a/common/src/utils/formatNames.ts b/common/src/utils/formatNames.ts deleted file mode 100644 index 0f69bab0e..000000000 --- a/common/src/utils/formatNames.ts +++ /dev/null @@ -1,84 +0,0 @@ -// we use the sig alg / hash function names returned in modulus extractor and the OID reference -// Example for https://oidref.com/1.2.840.113549.1.1.11: sha256WithRSAEncryption -// the jmrtd lib returns other names (ex: SHA256withRSA), see this page: https://github.com/E3V3A/JMRTD/blob/master/jmrtd/src/org/jmrtd/lds/SODFile.java -// Sometimesm, iOS module too (ex rsaEncryption instead of sha256WithRSAEncryption) -// So we translate here - -export function toStandardName(jmrtdName: string): string { - switch (jmrtdName) { - - // hash functions - case "SHA-1": - case "SHA1": - return "sha1"; - case "SHA-224": - case "SHA224": - return "sha224"; - case "SHA-256": - case "SHA256": - return "sha256"; - case "SHA-384": - case "SHA384": - return "sha384"; - case "SHA-512": - case "SHA512": - return "sha512"; - - // sig algs - case "SHA1withECDSA": - return "ecdsa-with-SHA1"; - case "SHA224withECDSA": - return "ecdsa-with-SHA224"; - case "SHA256withECDSA": - return "ecdsa-with-SHA256"; - case "SHA384withECDSA": - return "ecdsa-with-SHA384"; - case "SHA512withECDSA": - return "ecdsa-with-SHA512"; - case "MD2withRSA": - return "md2WithRSAEncryption"; - case "MD4withRSA": - return "md4WithRSAEncryption"; - case "MD5withRSA": - return "md5WithRSAEncryption"; - case "SHA1withRSA": - return "sha1WithRSAEncryption"; - case "SHA224withRSA": - return "sha224WithRSAEncryption"; - case "SHA256withRSA": - return "sha256WithRSAEncryption"; - case "SHA384withRSA": - return "sha384WithRSAEncryption"; - case "SHA512withRSA": - return "sha512WithRSAEncryption"; - - case "SAwithRSA/PSS": - case "SSAwithRSA/PSS": - case "RSASSA-PSS": - case "rsassa-pss": - case "rsassaPss": - case "rsassapss": - case "rsapss": - case "SHA256withRSAandMGF1": - case "id-mgf1": - return "sha256WithRSASSAPSS"; - // we call it sha256WithRSASSAPSS even if specs says rsassaPss because there are multiple hash functions used - // e.g. Italy uses sha512 with it - - - // added this one for iOS - case "RSA": - case "rsaEncryption": - // for security - case "SHA256WITHRSA": - case "SHA256withRSA": - case "sha256withRSA": - case "sha256withrsa": - case "sha256WithRSAEncryption": - case "SHA256WITHRSAENCRYPTION": - return "sha256WithRSAEncryption"; - default: - console.log(`JMRTD sig alg or hash function ${jmrtdName} not found in mapping, returning it as it is`); - return jmrtdName; - } -} \ No newline at end of file diff --git a/common/src/utils/generateInputs.ts b/common/src/utils/generateInputs.ts index 25cb48523..47588021b 100644 --- a/common/src/utils/generateInputs.ts +++ b/common/src/utils/generateInputs.ts @@ -37,7 +37,8 @@ export function generateCircuitInputsRegister( passportData: PassportData, n_dsc: number, k_dsc: number, - mocks: PassportData[] = mockPassportDatas + // mocks: PassportData[] = mockPassportDatas + mocks?: PassportData[] ) { const { mrz, dsc, dataGroupHashes, eContent, encryptedDigest } = passportData; diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index e765061e6..42366fc6a 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -1,8 +1,6 @@ export type PassportData = { mrz: string; - signatureAlgorithm?: string; - dsc?: string; - pubKey?: { modulus?: string, exponent?: string, curveName?: string, publicKeyQ?: string }; + dsc: string; dataGroupHashes: number[]; eContent: number[]; encryptedDigest: number[]; diff --git a/common/src/utils/utils.ts b/common/src/utils/utils.ts index 030fa0b4a..b2b6d6f9e 100644 --- a/common/src/utils/utils.ts +++ b/common/src/utils/utils.ts @@ -16,23 +16,6 @@ export function formatMrz(mrz: string) { return mrzCharcodes; } -export function parsePubKeyString(pubKeyString: string) { - const modulusMatch = pubKeyString.match(/modulus: ([\w\d]+)\s*public/); - const publicExponentMatch = pubKeyString.match(/public exponent: (\w+)/); - - const modulus = modulusMatch ? modulusMatch[1] : null; - const exponent = publicExponentMatch ? publicExponentMatch[1] : null; - - if (!modulus || !exponent) { - throw new Error('Could not parse public key string'); - } - - return { - modulus, - exponent, - }; -} - export function formatAndConcatenateDataHashes( dataHashes: [number, number[]][], hashLen: number, @@ -220,13 +203,6 @@ export function toUnsignedByte(signedByte: number) { return signedByte < 0 ? signedByte + 256 : signedByte; } -export function formatSigAlgNameForCircuit(sigAlg: string, exponent?: string) { - // replace - by _, for instance for ecdsa-with-SHA256 - sigAlg = sigAlg.replace(/-/g, '_'); - // add exponent, for instance for sha256WithRSAEncryption - return exponent ? `${sigAlg}_${exponent}` : sigAlg; -} - export function bigIntToChunkedBytes( num: BigInt | bigint, bytesPerChunk: number,