From ac745bbf8fd65efb7af5e646ad5be92d36592be5 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 29 Aug 2025 17:28:42 +0200 Subject: [PATCH] moves validateDocument functions into the common package. (#977) * moves validateDocument functions into the common package. * fix build issues and lint * handle bad connections better in nullifiier * add an abort controler to nullifer fetcher, ignore fals positives * import types separately * take it as an arg --- .gitleaksignore | 4 + app/.eslintrc.cjs | 2 +- app/metro.config.cjs | 4 + app/src/providers/passportDataProvider.tsx | 8 +- .../recovery/AccountRecoveryChoiceScreen.tsx | 11 +- .../recovery/RecoverWithPhraseScreen.tsx | 11 +- app/src/stores/protocolStore.ts | 6 +- app/src/utils/proving/index.ts | 3 - app/src/utils/proving/provingMachine.ts | 28 +- app/src/utils/proving/validateDocument.ts | 255 +---------------- app/tsconfig.json | 1 + common/package.json | 5 + common/scripts/postBuild.mjs | 4 +- common/scripts/shimConfigs.js | 5 + common/src/constants/index.ts | 2 +- common/src/utils/appType.ts | 12 +- common/src/utils/index.ts | 18 +- common/src/utils/passports/validate.test.ts | 193 +++++++++++++ common/src/utils/passports/validate.ts | 256 ++++++++++++++++++ common/src/utils/types.ts | 20 +- common/tests/scope.test.ts | 2 +- common/tsup.config.ts | 1 + common/vitest.config.ts | 2 +- 23 files changed, 560 insertions(+), 293 deletions(-) create mode 100644 .gitleaksignore create mode 100644 common/src/utils/passports/validate.test.ts create mode 100644 common/src/utils/passports/validate.ts diff --git a/.gitleaksignore b/.gitleaksignore new file mode 100644 index 000000000..90d1f5adb --- /dev/null +++ b/.gitleaksignore @@ -0,0 +1,4 @@ +1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:54 +1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:55 +1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:73 +1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:74 diff --git a/app/.eslintrc.cjs b/app/.eslintrc.cjs index 70b76e1e8..e2e0d0c4f 100644 --- a/app/.eslintrc.cjs +++ b/app/.eslintrc.cjs @@ -144,7 +144,7 @@ module.exports = { // General JavaScript Rules // Warn on common issues but don't block development - 'no-console': 'warn', + 'no-console': 'off', 'no-empty-pattern': 'off', 'prefer-const': 'warn', '@typescript-eslint/no-explicit-any': 'warn', diff --git a/app/metro.config.cjs b/app/metro.config.cjs index b97935f76..38c16c168 100644 --- a/app/metro.config.cjs +++ b/app/metro.config.cjs @@ -104,6 +104,10 @@ const extraNodeModules = { commonPath, 'dist/esm/src/utils/passports/format.js', ), + '@selfxyz/common/utils/passports/validate': path.resolve( + commonPath, + 'dist/esm/src/utils/passports/validate.js', + ), '@selfxyz/common/utils/passportMock': path.resolve( commonPath, 'dist/esm/src/utils/passports/mock.js', diff --git a/app/src/providers/passportDataProvider.tsx b/app/src/providers/passportDataProvider.tsx index 2dedc89b4..6803fc6d7 100644 --- a/app/src/providers/passportDataProvider.tsx +++ b/app/src/providers/passportDataProvider.tsx @@ -59,12 +59,8 @@ import type { DocumentMetadata, PassportData, } from '@selfxyz/common/utils/types'; -import { - DocumentsAdapter, - getAllDocuments, - SelfClient, - useSelfClient, -} from '@selfxyz/mobile-sdk-alpha'; +import type { DocumentsAdapter, SelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { getAllDocuments, useSelfClient } from '@selfxyz/mobile-sdk-alpha'; import { unsafe_getPrivateKey, useAuth } from '@/providers/authProvider'; diff --git a/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx b/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx index fecd34a94..4e9decabb 100644 --- a/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx +++ b/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx @@ -6,6 +6,7 @@ import React, { useCallback, useState } from 'react'; import { Separator, View, XStack, YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; +import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; @@ -23,10 +24,10 @@ import { loadPassportDataAndSecret, reStorePassportDataWithRightCSCA, } from '@/providers/passportDataProvider'; +import { useProtocolStore } from '@/stores/protocolStore'; import { useSettingStore } from '@/stores/settingStore'; import { STORAGE_NAME, useBackupMnemonic } from '@/utils/cloudBackup'; import { black, slate500, slate600, white } from '@/utils/colors'; -import { isUserRegisteredWithAlternativeCSCA } from '@/utils/proving/validateDocument'; const AccountRecoveryChoiceScreen: React.FC = () => { const { trackEvent } = useSelfClient(); @@ -60,6 +61,14 @@ const AccountRecoveryChoiceScreen: React.FC = () => { const { isRegistered, csca } = await isUserRegisteredWithAlternativeCSCA( passportData, secret, + { + getCommitmentTree(docCategory) { + return useProtocolStore.getState()[docCategory].commitment_tree; + }, + getAltCSCA(docCategory) { + return useProtocolStore.getState()[docCategory].alternative_csca; + }, + }, ); if (!isRegistered) { console.warn( diff --git a/app/src/screens/recovery/RecoverWithPhraseScreen.tsx b/app/src/screens/recovery/RecoverWithPhraseScreen.tsx index 4c2b004a8..bad183cda 100644 --- a/app/src/screens/recovery/RecoverWithPhraseScreen.tsx +++ b/app/src/screens/recovery/RecoverWithPhraseScreen.tsx @@ -9,6 +9,7 @@ import { Text, TextArea, View, XStack, YStack } from 'tamagui'; import Clipboard from '@react-native-clipboard/clipboard'; import { useNavigation } from '@react-navigation/native'; +import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; @@ -20,6 +21,7 @@ import { loadPassportDataAndSecret, reStorePassportDataWithRightCSCA, } from '@/providers/passportDataProvider'; +import { useProtocolStore } from '@/stores/protocolStore'; import { black, slate300, @@ -28,7 +30,6 @@ import { slate700, white, } from '@/utils/colors'; -import { isUserRegisteredWithAlternativeCSCA } from '@/utils/proving/validateDocument'; const RecoverWithPhraseScreen: React.FC = () => { const navigation = useNavigation(); @@ -65,6 +66,14 @@ const RecoverWithPhraseScreen: React.FC = () => { const { isRegistered, csca } = await isUserRegisteredWithAlternativeCSCA( passportData, secret as string, + { + getCommitmentTree(docCategory) { + return useProtocolStore.getState()[docCategory].commitment_tree; + }, + getAltCSCA(docCategory) { + return useProtocolStore.getState()[docCategory].alternative_csca; + }, + }, ); if (!isRegistered) { console.warn( diff --git a/app/src/stores/protocolStore.ts b/app/src/stores/protocolStore.ts index 252c761f2..b9560d4e1 100644 --- a/app/src/stores/protocolStore.ts +++ b/app/src/stores/protocolStore.ts @@ -20,7 +20,7 @@ import { IDENTITY_TREE_URL_STAGING, IDENTITY_TREE_URL_STAGING_ID_CARD, } from '@selfxyz/common/constants'; -import type { OfacTree } from '@selfxyz/common/utils/types'; +import type { DeployedCircuits, OfacTree } from '@selfxyz/common/utils/types'; import { fetchOfacTrees } from '@/utils/ofac'; @@ -29,7 +29,7 @@ interface ProtocolState { commitment_tree: any; dsc_tree: any; csca_tree: string[][] | null; - deployed_circuits: any; + deployed_circuits: DeployedCircuits | null; circuits_dns_mapping: any; alternative_csca: Record; ofac_trees: OfacTree | null; @@ -49,7 +49,7 @@ interface ProtocolState { commitment_tree: any; dsc_tree: any; csca_tree: string[][] | null; - deployed_circuits: any; + deployed_circuits: DeployedCircuits | null; circuits_dns_mapping: any; alternative_csca: Record; ofac_trees: OfacTree | null; diff --git a/app/src/utils/proving/index.ts b/app/src/utils/proving/index.ts index f3705d109..ca657c261 100644 --- a/app/src/utils/proving/index.ts +++ b/app/src/utils/proving/index.ts @@ -16,7 +16,4 @@ export { // From loadingScreenStateText - used in loading screen export { getLoadingScreenText } from '@/utils/proving/loadingScreenStateText'; -// From validateDocument - used in recovery and splash screens -export { isUserRegisteredWithAlternativeCSCA } from '@/utils/proving/validateDocument'; - export { useProvingStore } from '@/utils/proving/provingMachine'; diff --git a/app/src/utils/proving/provingMachine.ts b/app/src/utils/proving/provingMachine.ts index 8b9479987..13c176663 100644 --- a/app/src/utils/proving/provingMachine.ts +++ b/app/src/utils/proving/provingMachine.ts @@ -17,6 +17,13 @@ import { getSolidityPackedUserContextData, } from '@selfxyz/common/utils'; import { getPublicKey, verifyAttestation } from '@selfxyz/common/utils/attest'; +import { + checkDocumentSupported, + checkIfPassportDscIsInTree, + isDocumentNullified, + isUserRegistered, + isUserRegisteredWithAlternativeCSCA, +} from '@selfxyz/common/utils/passports/validate'; import { clientKey, clientPublicKeyHex, @@ -50,13 +57,6 @@ import { generateTEEInputsDSC, generateTEEInputsRegister, } from '@/utils/proving/provingInputs'; -import { - checkIfPassportDscIsInTree, - checkPassportSupported, - isDocumentNullified, - isUserRegistered, - isUserRegisteredWithAlternativeCSCA, -} from '@/utils/proving/validateDocument'; const { trackEvent } = analytics(); @@ -711,7 +711,10 @@ export const useProvingStore = create((set, get) => { if (!passportData) { throw new Error('PassportData is not available'); } - const isSupported = await checkPassportSupported(passportData); + const isSupported = await checkDocumentSupported(passportData, { + getDeployedCircuits: (documentCategory: DocumentCategory) => + useProtocolStore.getState()[documentCategory].deployed_circuits!, + }); if (isSupported.status !== 'passport_supported') { console.error( 'Passport not supported:', @@ -726,13 +729,15 @@ export const useProvingStore = create((set, get) => { actor!.send({ type: 'PASSPORT_NOT_SUPPORTED' }); return; } - + const getCommitmentTree = (documentCategory: DocumentCategory) => + useProtocolStore.getState()[documentCategory].commitment_tree; /// disclosure if (circuitType === 'disclose') { // check if the user is registered using the csca from the passport data. const isRegisteredWithLocalCSCA = await isUserRegistered( passportData, secret as string, + getCommitmentTree, ); if (isRegisteredWithLocalCSCA) { trackEvent(ProofEvents.VALIDATION_SUCCESS); @@ -750,6 +755,11 @@ export const useProvingStore = create((set, get) => { await isUserRegisteredWithAlternativeCSCA( passportData, secret as string, + { + getCommitmentTree, + getAltCSCA: docType => + useProtocolStore.getState()[docType].alternative_csca, + }, ); if (isRegistered) { reStorePassportDataWithRightCSCA(passportData, csca as string); diff --git a/app/src/utils/proving/validateDocument.ts b/app/src/utils/proving/validateDocument.ts index 817f4c4ad..bab692eac 100644 --- a/app/src/utils/proving/validateDocument.ts +++ b/app/src/utils/proving/validateDocument.ts @@ -2,26 +2,8 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import { poseidon2, poseidon5 } from 'poseidon-lite'; -import { LeanIMT } from '@openpassport/zk-kit-lean-imt'; - -import { - API_URL, - API_URL_STAGING, - ID_CARD_ATTESTATION_ID, - PASSPORT_ATTESTATION_ID, -} from '@selfxyz/common/constants'; -import type { DocumentCategory, PassportData } from '@selfxyz/common/types'; -import { parseCertificateSimple } from '@selfxyz/common/utils/certificates/parseSimple'; -import { getCircuitNameFromPassportData } from '@selfxyz/common/utils/circuitNames'; -import { packBytesAndPoseidon } from '@selfxyz/common/utils/hash/poseidon'; -import { hash } from '@selfxyz/common/utils/hash/sha'; -import { formatMrz } from '@selfxyz/common/utils/passportFormat'; -import { - generateCommitment, - generateNullifier, -} from '@selfxyz/common/utils/passports'; -import { getLeafDscTree } from '@selfxyz/common/utils/trees'; +import type { PassportData } from '@selfxyz/common/types'; +import { isUserRegistered } from '@selfxyz/common/utils/passports/validate'; import type { PassportValidationCallbacks } from '@selfxyz/mobile-sdk-alpha'; import { isPassportDataValid } from '@selfxyz/mobile-sdk-alpha'; import { DocumentEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; @@ -39,13 +21,6 @@ import analytics from '@/utils/analytics'; const { trackEvent } = analytics(); -export type PassportSupportStatus = - | 'passport_metadata_missing' - | 'csca_not_found' - | 'registration_circuit_not_supported' - | 'dsc_circuit_not_supported' - | 'passport_supported'; - /** * This function checks and updates registration states for all documents and updates the `isRegistered`. */ @@ -152,7 +127,11 @@ export async function checkAndUpdateRegistrationStates(): Promise { } const { secret } = JSON.parse(passportDataAndSecret); - const isRegistered = await isUserRegistered(migratedPassportData, secret); + const isRegistered = await isUserRegistered( + migratedPassportData, + secret, + docType => useProtocolStore.getState()[docType].commitment_tree, + ); // Update the registration state in the document metadata await updateDocumentRegistrationState(documentId, isRegistered); @@ -183,225 +162,7 @@ export async function checkAndUpdateRegistrationStates(): Promise { if (__DEV__) console.log('Registration state check and update completed'); } -export async function checkIfPassportDscIsInTree( - passportData: PassportData, - dscTree: string, -): Promise { - const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); - const tree = LeanIMT.import(hashFunction, dscTree); - const leaf = getLeafDscTree( - passportData.dsc_parsed!, - passportData.csca_parsed!, - ); - const index = tree.indexOf(BigInt(leaf)); - if (index === -1) { - console.warn('DSC not found in the tree'); - return false; - } - return true; -} - -export async function checkPassportSupported( - passportData: PassportData, -): Promise<{ - status: PassportSupportStatus; - details: string; -}> { - const passportMetadata = passportData.passportMetadata; - const document: DocumentCategory = passportData.documentCategory; - if (!passportMetadata) { - console.warn('Passport metadata is null'); - return { status: 'passport_metadata_missing', details: passportData.dsc }; - } - if (!passportMetadata.cscaFound) { - console.warn('CSCA not found'); - return { status: 'csca_not_found', details: passportData.dsc }; - } - const circuitNameRegister = getCircuitNameFromPassportData( - passportData, - 'register', - ); - const deployedCircuits = - useProtocolStore.getState()[document].deployed_circuits; // change this to the document type - if ( - !circuitNameRegister || - !( - deployedCircuits.REGISTER.includes(circuitNameRegister) || - deployedCircuits.REGISTER_ID.includes(circuitNameRegister) - ) - ) { - return { - status: 'registration_circuit_not_supported', - details: circuitNameRegister, - }; - } - const circuitNameDsc = getCircuitNameFromPassportData(passportData, 'dsc'); - if ( - !circuitNameDsc || - !( - deployedCircuits.DSC.includes(circuitNameDsc) || - deployedCircuits.DSC_ID.includes(circuitNameDsc) - ) - ) { - console.warn('DSC circuit not supported:', circuitNameDsc); - return { status: 'dsc_circuit_not_supported', details: circuitNameDsc }; - } - return { status: 'passport_supported', details: 'null' }; -} - -export function generateCommitmentInApp( - secret: string, - attestation_id: string, - passportData: PassportData, - alternativeCSCA: Record, -) { - const dg1_packed_hash = packBytesAndPoseidon(formatMrz(passportData.mrz)); - const eContent_packed_hash = packBytesAndPoseidon( - ( - hash( - passportData.passportMetadata!.eContentHashFunction, - Array.from(passportData.eContent), - 'bytes', - ) as number[] - ) - // eslint-disable-next-line no-bitwise - .map(byte => byte & 0xff), - ); - - const csca_list: string[] = []; - const commitment_list: string[] = []; - - for (const [cscaKey, cscaValue] of Object.entries(alternativeCSCA)) { - try { - const formattedCsca = formatCSCAPem(cscaValue); - const cscaParsed = parseCertificateSimple(formattedCsca); - - const commitment = poseidon5([ - secret, - attestation_id, - dg1_packed_hash, - eContent_packed_hash, - getLeafDscTree(passportData.dsc_parsed!, cscaParsed), - ]).toString(); - - csca_list.push(formatCSCAPem(cscaValue)); - commitment_list.push(commitment); - } catch (error) { - console.warn( - `Failed to parse CSCA certificate for key ${cscaKey}:`, - error, - ); - } - } - - if (commitment_list.length === 0) { - console.error('No valid CSCA certificates found in alternativeCSCA'); - } - - return { commitment_list, csca_list }; -} - -function formatCSCAPem(cscaPem: string): string { - let cleanedPem = cscaPem.trim(); - - if (!cleanedPem.includes('-----BEGIN CERTIFICATE-----')) { - cleanedPem = cleanedPem.replace(/[^A-Za-z0-9+/=]/g, ''); - try { - Buffer.from(cleanedPem, 'base64'); - } catch (error) { - throw new Error(`Invalid base64 certificate data: ${error}`); - } - cleanedPem = `-----BEGIN CERTIFICATE-----\n${cleanedPem}\n-----END CERTIFICATE-----`; - } - return cleanedPem; -} - -export async function isDocumentNullified(passportData: PassportData) { - const nullifier = generateNullifier(passportData); - const nullifierHex = `0x${BigInt(nullifier).toString(16)}`; - const attestationId = - passportData.documentCategory === 'passport' - ? '0x0000000000000000000000000000000000000000000000000000000000000001' - : '0x0000000000000000000000000000000000000000000000000000000000000002'; - console.log('checking for nullifier', nullifierHex, attestationId); - const baseUrl = passportData.mock === false ? API_URL : API_URL_STAGING; - const response = await fetch( - `${baseUrl}/is-nullifier-onchain-with-attestation-id`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - nullifier: nullifierHex, - attestation_id: attestationId, - }), - }, - ); - const data = await response.json(); - console.log('isDocumentNullified', data); - return data.data; -} - -export async function isUserRegistered( - passportData: PassportData, - secret: string, -) { - if (!passportData) { - return false; - } - const attestationId = - passportData.documentCategory === 'passport' - ? PASSPORT_ATTESTATION_ID - : ID_CARD_ATTESTATION_ID; - const commitment = generateCommitment(secret, attestationId, passportData); - const document: DocumentCategory = passportData.documentCategory; - const serializedTree = useProtocolStore.getState()[document].commitment_tree; - const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serializedTree); - const index = tree.indexOf(BigInt(commitment)); - return index !== -1; -} - -export async function isUserRegisteredWithAlternativeCSCA( - passportData: PassportData, - secret: string, -): Promise<{ isRegistered: boolean; csca: string | null }> { - if (!passportData) { - console.error('Passport data is null'); - return { isRegistered: false, csca: null }; - } - const document: DocumentCategory = passportData.documentCategory; - const alternativeCSCA = - useProtocolStore.getState()[document].alternative_csca; - const { commitment_list, csca_list } = generateCommitmentInApp( - secret, - document === 'passport' ? PASSPORT_ATTESTATION_ID : ID_CARD_ATTESTATION_ID, - passportData, - alternativeCSCA, - ); - - if (commitment_list.length === 0) { - console.error( - 'No valid CSCA certificates could be parsed from alternativeCSCA', - ); - return { isRegistered: false, csca: null }; - } - - const serializedTree = useProtocolStore.getState()[document].commitment_tree; - const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serializedTree); - for (let i = 0; i < commitment_list.length; i++) { - const commitment = commitment_list[i]; - const index = tree.indexOf(BigInt(commitment)); - if (index !== -1) { - return { isRegistered: true, csca: csca_list[i] }; - } - } - console.warn( - 'None of the following CSCA correspond to the commitment:', - csca_list, - ); - return { isRegistered: false, csca: null }; -} +// UNUSED? interface MigratedPassportData extends Omit { documentType?: string; diff --git a/app/tsconfig.json b/app/tsconfig.json index 939933e2a..7952fe1ff 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -9,6 +9,7 @@ "@env": ["./env.ts"], "@selfxyz/common": ["../common"], "@selfxyz/common/*": ["../common/*"], + "@selfxyz/common/utils/passports/*": ["../common/utils/passports/*"], "@selfxyz/mobile-sdk-alpha": [ "../packages/mobile-sdk-alpha/src", "../packages/mobile-sdk-alpha/dist" diff --git a/common/package.json b/common/package.json index 856e9c977..9f1b53f4c 100644 --- a/common/package.json +++ b/common/package.json @@ -271,6 +271,11 @@ "import": "./dist/esm/src/utils/passports/passport.js", "require": "./dist/cjs/src/utils/passports/passport.cjs" }, + "./utils/passports/validate": { + "types": "./dist/esm/src/utils/passports/validate.d.ts", + "import": "./dist/esm/src/utils/passports/validate.js", + "require": "./dist/cjs/src/utils/passports/validate.cjs" + }, "./utils/passports/genMockIdDoc": { "types": "./dist/esm/src/utils/passports/genMockIdDoc.d.ts", "import": "./dist/esm/src/utils/passports/genMockIdDoc.js", diff --git a/common/scripts/postBuild.mjs b/common/scripts/postBuild.mjs index 87f31b391..eddb49748 100644 --- a/common/scripts/postBuild.mjs +++ b/common/scripts/postBuild.mjs @@ -1,6 +1,7 @@ -import { writeFileSync, mkdirSync, readFileSync } from 'node:fs'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; + import { shimConfigs } from './shimConfigs.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -25,6 +26,7 @@ const distPackageJson = { '.': './esm/index.js', './constants': './esm/src/constants/index.js', './utils': './esm/src/utils/index.js', + './utils/passports/validate': './esm/src/utils/passports/validate.js', './types': './esm/src/types/index.js', }, }; diff --git a/common/scripts/shimConfigs.js b/common/scripts/shimConfigs.js index f6022df18..9334a0a63 100644 --- a/common/scripts/shimConfigs.js +++ b/common/scripts/shimConfigs.js @@ -214,6 +214,11 @@ export const shimConfigs = [ targetPath: '../../../esm/src/utils/passports/mockDsc.js', name: 'utils/passports/mockDsc', }, + { + shimPath: 'utils/passports/validate', + targetPath: '../../../esm/src/utils/passports/validate.js', + name: 'utils/passports/validate', + }, { shimPath: 'utils/passports/mockGeneration', targetPath: '../../../esm/src/utils/passports/mockGeneration.js', diff --git a/common/src/constants/index.ts b/common/src/constants/index.ts index f6015259d..0395194ed 100644 --- a/common/src/constants/index.ts +++ b/common/src/constants/index.ts @@ -21,8 +21,8 @@ export { ID_CARD_ATTESTATION_ID, PASSPORT_ATTESTATION_ID, PCR0_MANAGER_ADDRESS, - RPC_URL, REDIRECT_URL, + RPC_URL, RegisterVerifierId, SignatureAlgorithmIndex, TREE_URL, diff --git a/common/src/utils/appType.ts b/common/src/utils/appType.ts index fe4f3254b..5ce40d8d8 100644 --- a/common/src/utils/appType.ts +++ b/common/src/utils/appType.ts @@ -6,7 +6,13 @@ import type { UserIdType } from './circuits/uuid.js'; import { validateUserId } from './circuits/uuid.js'; import { formatEndpoint } from './scope.js'; +export interface DeferredLinkingTokenResponse { + campaign_id: string; + campaign_user_id: string; + self_app: string; // SelfApp is serialized as a string +} export type EndpointType = 'https' | 'celo' | 'staging_celo' | 'staging_https'; + export type Mode = 'register' | 'dsc' | 'vc_and_disclose'; export interface SelfApp { @@ -121,9 +127,3 @@ export class SelfAppBuilder { export function getUniversalLink(selfApp: SelfApp): string { return `${REDIRECT_URL}?selfApp=${encodeURIComponent(JSON.stringify(selfApp))}`; } - -export interface DeferredLinkingTokenResponse { - campaign_id: string; - campaign_user_id: string; - self_app: string; // SelfApp is serialized as a string -} diff --git a/common/src/utils/index.ts b/common/src/utils/index.ts index 08cf1d185..23a04161c 100644 --- a/common/src/utils/index.ts +++ b/common/src/utils/index.ts @@ -27,12 +27,21 @@ export { hash, packBytesAndPoseidon, } from './hash.js'; +export { + clientKey, + clientPublicKeyHex, + ec, + encryptAES256GCM, + getPayload, + getWSDbRelayerUrl, +} from './proving.js'; export { findStartPubKeyIndex, generateCommitment, generateNullifier, initPassportDataParsing, } from './passports/passport.js'; +export type { TEEPayload, TEEPayloadBase, TEEPayloadDisclose } from './proving.js'; export { formatMrz } from './passports/format.js'; export { genAndInitMockPassportData } from './passports/genMockPassportData.js'; export { @@ -50,12 +59,3 @@ export { getSKIPEM } from './csca.js'; export { initElliptic } from './certificate_parsing/elliptic.js'; export { parseCertificateSimple } from './certificate_parsing/parseCertificateSimple.js'; export { parseDscCertificateData } from './passports/passport_parsing/parseDscCertificateData.js'; -export { - clientKey, - clientPublicKeyHex, - ec, - encryptAES256GCM, - getPayload, - getWSDbRelayerUrl, -} from './proving.js'; -export type { TEEPayload, TEEPayloadBase, TEEPayloadDisclose } from './proving.js'; diff --git a/common/src/utils/passports/validate.test.ts b/common/src/utils/passports/validate.test.ts new file mode 100644 index 000000000..4d6f9aa72 --- /dev/null +++ b/common/src/utils/passports/validate.test.ts @@ -0,0 +1,193 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { API_URL, API_URL_STAGING } from '@selfxyz/common/constants'; + +import { PassportData } from '../types.js'; +import { + checkIfPassportDscIsInTree, + generateCommitmentInApp, + isDocumentNullified, +} from './validate.js'; + +const fakePassportData: PassportData = { + mrz: `P { + it('returns false when the DSC leaf is not found in the tree', async () => { + const result = await checkIfPassportDscIsInTree(fakePassportData, DSC_TREE); + expect(result).toBe(false); + }); + const DSC_TREE = + '[["15050717986081186900284402412680450615814660880074633789501222846708401423740","3069534999723762562409428262585862866699754006907317324567148051996311183099","21576603044631080321995279188143441908903381857622381619055899013244346266480","14284681215817593642785658309651697350973694095314685657394717026665916834653","13886105118423743168055115886948894336173423314961179869691414785524784262105","676121210568391847506228792210291708646700660225541494545338553462255636087","18409411196655284273608772935501207648384876108202214689750249443779972627153","7872180489108432212228035199334502894309164644710491244694199871196062229433","19949617842139611002723970286547027928029037335432843954167167340892256203730","7502269207650485592812463512496004833604545615399179815332697286274622940373","6862632611124160119114404709540782713975095895992375543524196440506963221621","1243074157058007271613828083989997308134672236169682220868319741148985990837","5425047092839350391718168660446094591577640226863484957228621722743219016575","10719356168209264326035764268280267428487984973542456568579827906977800069357","3916745547725731040768855007630947522951197588117442582792505306459738937816","17511367886381875635321954331157305596125483487207374864700369208979145389507","6896660597139955672102719188979856264938300973141309856383360459608605462252","17471972144902267375921404496584333010094933715953676564585902046720299012100","9144805513001428837782693766708320273535495656964734083092184159957147950313","16978804711453892332577491397341959122232646001553662409014564971509922511139","9274433449818715864634202432306527962210329607570313635996058055443915926102","3637608279890240113850467158461278047569691627665713225878008441825807840320","19432413097149357947567548615761084757102446838654445445329214471834565047445","18560055546600029790779738230925565762708017918771076008433257773433460600028","21195383168307361423213757877048637008727106968076043878184251136250760320630","5003784987675076010026521964198168062643473016194382429991297487472837064534","3808551573595911369894570677120746245074682812038613682031668924492412891112","6800667065810091964211450414678130795916559468414073868048169855462915000335","14847408787053542618904924289115865723863786142874861251732289788775564443068","6724451775902795360187933516611631496013377904397702128650810825458533178042","6856746914769398279499373037471392993266389797637709375965246287964790413914","16848558073263385467443729915645427339684325720740557324514820031882997627447","5345831818649402627319930694199172453205198325409751575226069081148786563304","3403610974430229557924454539178393767977120412868388618394429897283220346119","8769464642885870238417761846565242119076166267433914474707157190946429969933","13011924877748344930206524757464555355973177314751772538535181318047853254219","2693387088905761948864392249695265789791790471538551994942468830069295309264","10260747930335156296259057542460058716627305155017298894370903267249216620594","19667785705675704581044499854719836075517968142413458989461557313701754660294","1673656183710808973345467828586685734554078599529395159075341108097692608908","19845666213008601149093196470803384661111713462309800475343007245063642207482","16613460539557544847901633427096381096525467516619751652446085720773635293591","15658154913743478775804819805465043315402840819993918820843218647433499324916","3339377147706104184549204552790464758140316460305759795412234170068501758148","10122141193615057762708038856778790782135322664789329223238116367990007586437","14953070555170069272729037345759377674893715826299222196596883316588775269437","9060612895712299393870702104274511343944133437431419002906887662022620915904","6754956766877934910791259639157936661465114802375018764059717762235711673295","6763799484486653707582773745592715955385683933161626307469815120495889782504","17353200505259452120585256166266145683207634200791844281167928208737214696718","20359394506132807364183590981306738865993210767092379275073873500890576954075","1871741293484384490630081890270328561210226301717635460210348697187182591237","20172220033083054232940181438472389630080143348595621547013873376784524700527","1959870969927411480577319657483047957623598873034995895327971493057962874140","448159082335847199012816161577271532730440377188087194763530323179162378764","9204528011728805077083254915545533423026386781981065469002460969556469418421","12176530224727698140228678847732848831611080821000909991889900162072057276622","8586969831097831204525586182239332316386545200797674473690700317858958020297","20357625788159058663397581132706854664973455252887690648170554086933037060351","14554838961964317982470052777068717466287510487656051050852564158521373392315","16625118444760416277264290636091745793702349981732319353179175537311289473376","3500053808086549593902115372862888632800886237706990684172497068772463377558","17534109972307733258859076885615714991541618112443286617336587596506094298722","16352079745918774608396872044809739178222159232272545965716932578464794462108","8419214378792271789848141925316455881449841873446992977024069611336045870338","5569717141879208853869174889406888865716462258848604153009638309552804821506","18407986295557619599947213998753220161987034644481816938474694136330271840434","10541663756997881451459908271896693087517455956705848055099425809260581101390","8635112933784038632667328138440693878222293882824850790287927208872529590609","16462735380433108767412525956495932339354622936012305986236609733029425938981","13237186694047524725128369139403827349193159763657904416357649992304098037948","15051006928283869310729804077725456534271159469258213463540646835190457316356","254474450051126368630995512347227404324925389781293766606809479961482407041","10509276492675250727880722164230405035131225080269400690363103292140153683218","19656799308793038519739022055837220093649299863892242583610921386801866105626","20166082481368193203671708875079398714638118020846382172884433206053900716334","18033218035572991997853771151065799885421382311515526600645737565762842890861","13434218434465234282335748845683607921312322828475938180897680600478479373778","3770147658677414125452790437840207632242489706702594136063703230982677987252","7231171338208470231578418275831217113752912071050460015051224943681592308491","20059023285764961326500053077688877432976403618251902981427590410303787588936","4179712265534800178364708964228041388083739335247460563563420002410529037056","5100339989640762224851766551483462728799206404514478592727047127793673697848","6074195051728669731767223602949504421085675966485213660522102158016087574569","2576088132594770857633527322575046812762375580479544076330782232834942178372","14571288389804446119339483197584489014230494797500173136420188954890151962442","16363115108047606971421564226630036580453914558042121482225889811296961045586","13804125919431012641926990258630297953902662208414366752053673348320650297043","7269332254260199259421758724513242256361565735391248149303947275730801038117","12027143527913126739657558818352496191901527256689046269214327464951463305213","14770999392617894724402917499147029512091204977019434405027805112586726981054","10640091102822538035771533122114980185864760600132279043433513501181517928723","10138493604831033630673441199523631716639628284317170302286909954982873517671","18225913088464157835962118304467139785354286098298692170427881759350232277973","5829545975293912607059198260335912444449345728471121059252542984602231873056","12682814809883815124002260009934713509961690777080641703232619183368278756375","10140025267837030363945882732990637092691191624248089926329051500378946011556","10963946727262701012912471259582514570347778128295446329039458572201764601072","8923497009064089403262575124992342065170226872142855860938518026060521498653","6497030269593946297522741903512895858500239715827906409958946823056662183046","6919468646754352986251044201261417923641339357253004928485911626355339971490","19549280262380595284954537238869733075392680401490880896395041512452497861599","12066305209630887396375757052799118348874441637026452002789272260188513521665","14817062103075218312134585071680732050306452572384369511697654810268396246798","15992442271511636286059668221281101151796763806844128961054869642386761104792","16991257759483159220044435057048609854157244336752991847513954495256411464320","17089611107031708099738630227898845924773611737195373515739619432142984547111","876439003745679817628171162461470070428793483026137954121272496537883843479","8744499129424119554356067364385087540603797438792442427704134805249827561999","5561827157997466316755059963742840643730650083903883901598900163144358013749","19757797985438982950943616864798115974521156440249736411556721323056818005589","19586202260804739958592073556880047997016932131224755893682947620850946559633","10091569553373224119203404025341444236505946195968000638556963804098858472331","17560712773816203076151701676523533885959400419987598581753605642010063381254","7975983161153595858671777490563294042002508542873835977514657673272157799840","17811996914342816224616189225309935458806622711653724669855847101059037501679","1199345311120273310930670048961064347714922683660780052214205737529601939120","625827757704013091547798718663349572897423107268723364020631873566533442684","9125910640334011456310699152582570847471252983382505558745130334307147943872","20148230236900928261550123109232000493433105159495752681185893808702890965787","12666376153627622284424711099476788434308201495780263281211383604206012681056","10408151193771983864148109328665692702833773418512940468723296229178525800611","14848600670481545924065567167449046986173754477575186660387090892438790524840","14420518206194293831441697814220532805235992313700619538211060995018480215753","16927864429828210897658112752452548777546920715979434183730987006926539437553","20376295673030904607359804011046289355100506519535194177183234160473624293597","7700318064381154759308235412892913704136361304746579295208954542444925728087","5087316903055968061954673083584075574041334890484881000715779316048457915442","5514083367129563052897645791120386944655030908126298528674267409911215221756","2751161973383585522298415323464795351940187798820327060097731175555980374146","16114717182338716214631065047073854594103392988981821337435484249291466532113","10622564440293681285882856760218192150236887030225597534307886614677951000001","9666691684084825460482382229411617971335284591498176259225374890221115151032","12930499930646644181956921728713012724708971413811626440486618918699824696237","6884998715479503996843150775694268356228903584196082083585081136448883105374","205791164293731404212502709576920650813014425960790212271030074328660428883","18614306110315456429800914697335678299090742178133806593219062998007344591793","4319272072941562669602707871882396441346139874323651916441747521554176004573","20751994648326713872521806758778712366691736985203599267513396728305391640710","6702906058430044167296032397091440791550388783287352188866976285574221088996","2274223572069267647162481629322941786424279348978875264170690143680040277531","12695300971701533233321600519499344386723189997639221069166240847726734439989","7603584768511443429363075702051510298658452094745323781282091716093734137862","11677366558742135701310630937452933982710956636033846515607127899828125895772","16406528267810825809794331529944337177151865905069479533136675017006659842227","2086483781255564211743632640144104089931981091324345317584534036865347398448","1006013951497211161730545809851053435101460285303962849482849545316773258705","4706480712538224233425908103098454284316588013874697281593953177923594779155","5776736989527424558253245619390510154154066737237734845159429134750921271203","20882326221910247034943722192051080401822469345668955318155856329933055873217","2006579096195308549826051051791112823167220159361839333410433172577497831567","17529692068740859711866419802368310793751572254900720759847435801682633574271","10498184700859411619712787706885771887829005108734861533495707395642733206724","4159013048927924706022647263647601587348438767419362857988194518736026848064","9276440441120804519873726361245758496706466253645237420283916254261559764850","11823523894937654087368896070818354936813705564354355832948619594340182586743","2873106040053573237547820236120672318885195584791601691126399186266619194730","13146293358725249224933628478480793607865391616293181676432600031129192560865","7137989565659482055746335633355208602339344397637284106427956549580526063471","864576349275101498105372635263993290148642208429590223660535972461355983988","10036535233540293171266507639795096463441286032658485473521240309994007920834","14232082538793949183627768991142205019076239251421057019680330527136371344670","15387148982280719943788036716078462647394719976115443376288959619927852266070","2967300600901921424910300626646626881317630694142561381212900345386398585208","21060153327133640365844789117055324862310143880115935669080595012352711745248","4924606814679934955626663940355687020449144295685399297393566996916166451953","1868877270424319802680394903441569740839062807526746072573441238349082630204","6442819239645365043539095988638495649030952965818653485035585241709404433968","9869901600457415267361603061833684738918146292575586065374586437667414820978","6323665654522781277067822830832342134001906064227050852948635897489855889965","14140876440223547776408798597485363220669083308643185587625588312156822301590","16746870775233195677565896429063754760052844273715477387578510830326324725561","16671726334859376296192512244832108213996221417713695045383039057054100073130","11455518882928053663422740236190037781438093716963834290859380094776986168155","21075841551128847325307001492609160762422805760254975975100456853793602825230","10457661107067470577667790010808646756857594780906967253325103827464534961259","6712888527150702995882657772110396176426631412420852579794884793882113327144","3713870585935102709417139079657215894067378773177237991720613113831092870813","16600877393276469414342728851482998177598056479899936488286131063635832878959","10608018533822477753705784558205127458103319726875756635303696640564334832949","9250835708380238503174456385672913944582152210841660504175108669722444730389","10779356712464243070541357407526901581192832690064355857564010233405137506782","3354178698151951453266791377237978414002342032803640707980245961465638254651","1806040186200596927793171792658251530795886660994262138475915546730408723416","18546647602629048695255036864908428760636985738273173098355870229232451403162","9466014801096728882603037002310862319468274026649431647662941249982559209057","12162445166682433114395766827680456053557249982897406543535001823071070407853","10421411074148324930836285076333937763063201301118439374288248209219475496006","9369735101697616055629480536286641553616873319834756103393670954015085233952","8778920089574763553829003059203115531872465204323408693590312286671041123803","8959939667989212295116639832131492090537577835884621693904874615809545448413","324916823840557418088412117156327369386917894839749218652196265629109908825","5064182860485698295922901632038800880558979720222883841038529669373703058580","6497673245789292222405349927039899939680664725809956322063213305021809850725","3262579014781001187208446022822170817465338399312254504043452652464520985613","19424882317623817516162733393100959793175940681323984462601103210436106501015","2597973553946372903280199982552229219162013686242765855254856062052143470859","15270331621709378387281754081136441908123632909659673870088172835636409068601","1363077614361890886028628144272905730708048887365984179624070866007223817250","6229106340232410702823898076853589365370733124945646724231311987273679847571","14758722871142103388338298402646350691130131787682589291119715516123289701647","3654987692666788028799266331158425513946109093325791233435917673902738642773","21414773132777913552053489610964499272811438067249149961037674593514192248971","10468418302945044247932525937189150982868205243626756971417276932361805143393","1053137708604141682842856053792997395067045945865395068431054424554421883716","4346584165129563378251313217390221485407048096264471714725817712799935455440","4254654525670761288237089238930941497857047583910579565007310946859764310769","21343570112033239643976671040628328410495894825738814070121796072306299998205","12091321793426747360044408287801945925548365504882783123843467662493529894387","11431312560122772837094719241862714208217509175996932007594373581818034344506","20229453410070235288937107026650540759001214964538975605933192731850562758492","17391309478523876161287594111882942193899364336288699336702149672024712006594","18581840027589820473858338291756839907210006505402180895942485119352286403780","4255948444007655991706173697181926081089215276256046077121090307471075010221","14944034639922856837283786584389977985784354905461712465138826799099991493382","21512833202462235067511770425816865592128266818264664612739481024537568613728","21481321835122607379267402855909024501438623289508408900857669772940544628942","16989486573424889346955718157856765034017122656119009659200535878377068132114","295091259400799596794304619425970293414912138234638152327868221488080250875","10850107883233628619710175149144923693338721245774844957977385498515267744132","11092083567296075241867132153834305467509351171858827525460070704047585817866","17741679527546208856472416590435880865321458676121174538244002859922764272788","20710849494381330454739035018956202927929711125922345825335274452837334122700","7953946433210406285621684741929014228773127950767672317186669456522623538697","19769491683733779047868632979181220121869656739261231328543052063585290403472","9510107055080740213267562982418924525672623152889083081033381509893521735608","5164471963023494260297236129036664613330195980701886783168762034373541335962","5408786558339446510488901171351807685363091959542624419038222148522676135403","8501131214541607742429276372790469269122048159068252797949725532225414859805","13849846155350677894825915924134733153008944435043155655531141667976999326352","8310090916306958744311823011762086336222930628069974476260030849638620214248","2136763777188243272147270467411640251081321145715885822271615242560334703206","21448847280070879187946899906029665499235017691507473807559803412580199513524","19068989100773877542602251358326678163757555764585113585748416128988635816113","4814673738750539123334380789022965159768864219601194919310049376239601217292","4620257944504679824968945962615665488942614020748836121521046883772294407628","13007063599971630100804466395943999887653721137718469479903431764627867551389","14397989891599210483761049177458577463362537629135706850393908956120363194645","17319643559067502900612584823124197306753701240401327224784534417580394200966","14007677194698490084118438637036037925885695285573930710235349246981261705358","12949794735048727370261294528945329810840619247877707605017151938419184511500","13612739477480210381180489295132846858493132080975357021920914293210668552929","11045436327919835649112023556657342276610603907635302546122786772770486593332","4743705681069573745869852142308023817339391705594618492189075029553832280821","15239576556086896503979711960049358754661603804462465062829275429554253753691","14747136239074234806096767241121328621765603238217150934130460025993415852981","14172217131417653447137860346403206646285093018612573743824194133317379726408","19529979498156589741479169318571911713768380014881998885544678960705842565259","15530715805827965655234412096782344922145115858640488911768085386597327018564","15708796257264137874262670251037626249750891797848914550064305651469241817313","5283158235101619479766990976969096813353825928077371171156145834420270971189","8312056981137956294727298064430843934721773178044341040766970596882608523427","817447555341001216358924557267408596041307093846084907701327727298767067922","15068076601905076802918210480816432768545855577500081910408189314324115690754","1360544256761134869128491760149948244700777372929525563576315750781995026078","9306553113811079383093597299935150266382226451575785166122743013959655461091","11435051421218763621235393114014402897550543610331699671986630062362273915233","11594954258156331913080176291924609398812962727799386469912395725967944340552","8961125395806301817938332106756637547418146730112087631805815385601364785100","3999931454853716661711582264072925269143260558205776298743478212380435192937","2120949636659624956328627430858642327065397309841116461255767113418445640159","18800436408155203534955135506591841508862137254070909996392460520450420368789","13152113626836358543196484243047274091143092779521666006781229308846979121574","620474083548043674666486917420455853672953097820140398436915304905585193536","1457047474903904626738983583836467727351535644338637144756169854747332632451","1126957580121466869374448170628261411260442883624547841978687326244133907648","484562069470424558599556918766020159550567240618373511608236451950627591107","1721209102517373350324342857942440061733081150534859821837121767959169505216","15661835651848789289465880187920521360877371253128333787421937353763144910006","4520124478859650024901112994030326264200826145392898475486797058537212115912","5655123664523515506711889969534893029670044591987577043220920498648977774081","10500282967203384417903843149183478244158927619055641104537732414331968855652","14386943260778194370346465143058847202859825481312765610877239593836705511731","2263629538097009902606098874564690624920053022906041220204295126825014400823","12896304684467455716481493682555639817679150986786951072581086421654510420705","11392112764014863471321446125838246903320432343501359754537231998681086234976","21711071132772651795692876518788562954968102083043681284306423398658061348086","20202588648438963191307934882420774974662412593284383956515205763324229578374","10522496631603774456541845357334797083782267747854423864998121998795031987923","19576626322549403723014991394351819446685271999246769569173070763098722684641","20123589829766377941501000035170770858373579529332891015067080428945004765557","21778403242403736390890074788485854752712768180530197304693315514892748395835","17758597150527386384521685112423567778630112338796275237549369449451357588869","16109542667643300646973697822615225474375304563985293093912818917088066716516","5516516802954523641247234363794741538458517460204259523158780474469518643149","10624707970701767164278882987674642019081260273031875533031114179756011430213","9327575299019019186963630050381026736455289030555975576202168457924141659983","5833824323307874368077638046910158000979770953767901219666895690685227214424","21523573831868487252952572955200063379728550896618817721620339289592282428266","15362413229750855002855672064512480658236654015213335815222272233394291280174","13602136941266270629684089237257417036415796223269636146899429924329690849320","14946490386878200298116606941506945722316319979553356870298342263202745834985","14413849934384049861248672608915515425555774356037741522468789079867850707224","6171737855930232456291560498026368668091887462935381609519009023884512567340","10212156223304927846275209849300785459872729384437208965226738494528672721704","21127068783447003193659062013731035546978174535918765538543237307789814538759","20468444991289824446434624404672307466238479728959330507727799267927949515598","20132282792874458912713414358063072520423345744025126102490298870142608016679","1591449786085715183201300053795379182933282672365701242788775783977327704551","8804554727524340002874855069863757671153505631639457347139136186584441025643","21194158113382539045953878483402007957526759314104425191793655009741045018731","5334663458520395353047563282094728594753687268775670334176379272254220432991","20618862004337291119835052887804815068933063528006385906328896539324355379234","16899668343986650981437946169082316563666076915239885648147206148130175749213","19707596260800493663007683787306301837042920460387196022855080452659084038062","21606613759772413064414618903053818905345804226696904807967337399288207853438","18100009621116940222303697582391002635249984898921416059860855766354986660376","3878085975473735012556404968834392888443503966760589597551370682688910686876","15836188276295787443858846745509216728250697486561425938448561131476441793295","815693495132565615537267749578203716706290215330576968589859616305831254570","18079922385805373091249693662178316405492430090255261882315457721979978269251","19491610588642504774472852090119207326777749501674110508443302525070683630458","20283485749536068360586394215103771047128779385637738231145624682906060706675","3441124486827728629956862945186281984899110901423959031112003552242664024675","20404207238916258199306812370625674615021548080557129858957119686511615328651","17602936956731797999567382016369281868523796085256783250106202957855604630638","18068462794036409338945674297570777708273308350054249352183855233230612590817","3424890813467506051642350736713940724258474154595170523969942168984064504569","15350625890460573337553806145700129347736009545173909008154010370640648445051","12558467840544049748456117821632100897036771514803105946658583123586429630610","14520137806619001284815907891902531302440217653605811250912381726360829463617","2929458705500308013830299939549733149930863657799454694011529374548052980596","8231595334440398973739794977493067599233950152973751177583133638653729032465","16719978498573771499657811446412226306796947472032425963537609712846135171883","21822761219683616956094949681766591044115296730796004580142582059278565955290","18675459758058077383225675608218035643456571819706674915562978362176144546605","12440409925189714105989632897613613212964615910999033997967024183522881571086","21296969836581017343516823825247524925123307139764696763617548014019747180518","21180134291009431442043704539850848938218398186535336243575099367326193900867","14109088757421357023685252805997463258797493667133238292404778503833084192005","5823441600575436838782792065065443395313109832217097271519567516211377894271","20110335282968172771202350373275471234293987696039841443686917422747244982737","20419464038429222097092590885374097087105426009847841847977765839914250280239","16054750803023203472986403291418833538085572787196103679887984437857876817284","3218192691999779063695498039947474562133642119820139865387056773087063274240","4096809742474759938479769937651382697385391990814086963672916723275129324787","19510937462961241028836880394034669471619554240568476485420255994106251074142","14236785106664653422012533367848421174052713424342881382910491900384592127933","20915266245595008282669223746938509501325129476296451898908124133856179500336","20858235200577425927391196465944312782192981768453426144271313821087922470335","6765054140169395785366762586906426069461521994335341593386958966270618701669","16927315890091031271536870781112722333355379624642055877600307579564517238852","20911272494962475976162981264734077344110993715496752549226664611066853367699","13621064907597050837099664639927743476026577740207373668302027372233270354699","6419894221164757939336390845817165619463197692704187260020290462984635822291","19185617536619262124019263432168942614592301033269359847677251684435200152916","18035034024972527012857071382162807476969169500415988890800375793962926921817","7104213630906016855480680119049871895348676064323331709239609896647942327826","15348592204056533770980465609448326894860650412980754777226182632150873045314","18387769867941016483281410169925461906323155219951975464127705061766939388681","14457107479993169858962471211026551566578009244474435930758128992252571086993","2378685550745327809236335419012164065770793282406778395468169574826166125265","15289221402830028367046454729260030403411909459702740342776095725029536848138","903998872284206830766617280947800421686004227896542434801578385016560286864","12528277831494605684314956222408527920440672407458048038339426475386600041099","12204066729878542786955567300970057833049404171570483334708358872463253640496","476608785513900200896996793683950915904770429966331351003166385501737018156","2753275003504100341690803001874608711624074664981369655027851145967489423238","18665935565376226970566715992220106016983620973183674610778158919238418959287","9805415701788863065551694797084136059560956617664976786405136608371985342914","2074342194630755474495624734718287760155356119096552651414538310100990248177","10481423319854421820363290400306511606208851937139017884947172880744086586011","8759785280868941473177844264513128117237496236235355199375564946228555073389","17536871393329476253194140881734251841407203438670827448709747903819136506104","1515058287946081120882222234504943467792821584889718162085712428873719162357","8815131461736431497737468390560482118321070286206954124354447148564081225974","6578106416511381070417422008714106214944142679245649511959016200070554981783","5145689456524141713078391906007315176896098973000816641381734416019586118883","14938523063867633408435871563211511168138741924911701796350026579695912427281","21847761370025024467674444959986347017312629224651896485707895844778597557186","19436157476210091329874977076140103182885596988489630337245099818364755810235","14697802737965435420591385449735935861359170357821407262965333093176517142954","7004238536651320417390115065822214028412247344588628692313077572822084428683","15618749690717332812202942517101049693149952379610612455421275437661671598702","9606749302517497019364525153224631732627059523773803035208865531313030765202","8089075911688638740851360366496965502117711584598044669863388069274505685101","20669042177702305023191384748208429981612442070721280501728900974482457714835","11009539454009133900205432452818118804099071336434672745119746470068380559517","469559867557089954386208811180856078302597377393302645082806515689861282219","3161266207368009017763990143759161200185277903541716834692198400534329458093","10759769372542553655350720190767027956200314292521744161760862921869985758769","12724672260599377699932945679463214907095931546164705279566259782241385245714","17402021092083388342379130520834358294921531641598335982418991721541247755577","8932974322507949682189843734770079107346838937719365149732973371103738320970","20957549425286773188307214483462118022430960679339620830831587172118999877001","1487769542810322230905534289803334311343604442951501373132451889871911001175","14032407463669314968046094605776208801234502665275155606628405196779277024592","3029673657345524487721456186459945897470537842200658992803045146386065661811","2129347705757047719473943234249772959232325795749377908554401180339031814295","9751077262757674765130010351057757264076413743076791349011934998203292255521","18294633228983264591066293062724515752046494678527729053700660845797502757573","18925248211266582644696863047528499131717766888383444364917677146025324088514","10166607818392883252211971746893951650341188619047869379508158905454643318584","810705956641393533125808068250321545468489535331207739480616007958529996291","8509657335643791176160467497644474778255213664787898969664825702650290234400","360058398379460583341675734714750727798815527286855891130455487163897608638","11694371442094348977004641467205941252522723763573084574030280035861099126268","1059290338819351317287165590012876964737039437559279029803279202218929550406","7206768484540926834218163283891163406027296915194192375745415799662748193038","9955659230839594207363439978470813343156935522434589937457377516701537277366","6841154390480087180181825930111317868687710378577179111345833706630478680643","21850302235124533052810306562987994058519438284868805650900554232660445406114","21864150857865741888633975004014736982818062034625001799844081861959397433825","20387647629340665324744005597435258142511100081626749650248921896259436739515","10130861536173457455951371741643972774584901006958342283129172260634797843667","8078702307545680766440208149404634459089198677274451482519412952732604478688","18552052561219144411178080383642500945137605347407937607816021297620747651371","1801286205927575992411716257226167679790190965315566080317439750208781923132","20257647260120053311384979166276789627672126146967870682768498606583511631188","20673504653723356369108033582143262104930991685455758975001620245939292692640","20199552401662630551586937505695435644406214032124286981987495275328807578724","20838346878216305028298537363214027325882345159944459281140359656943131023628","5070982090836773490780030570441942686324593182798472245941886653456642924755","8096669617216081245843041117571155687262549377202933739941545341687119153419","622244702604012293348097190828152409422769729625371443684822107784374875339","17771075752149662018903409282759301996365077476815668661410169336830090668359","14076312052530370339180300771830710705409804609029585355297659109464266438256","3204479791416570103833167832573833044751618161661353551637626282503813317352","3090238067965123991324646256226219835802838256737232553201646758560784219725","14504427391423546129133435494576360616806479139406766660809651830922083750516","11766717719175904916596333335853752964341235646195187738768247264690882958570","10413052120141836376484051379305429392140502931451495115784701465900608465357","16359922090667021475484616801430690413431476834475649071340182602447475634911","11414079161786936914631517980846234961523553037855716034251671299758671277171","1974884400842537089073586188177840876087362653738233798691985527259975541004","5881309768664417159444257083435658580439655938878526219807658372366475635012","4342536102756859849204964986335743150569652288101932223958246630841884826906","1940615272192747195969590128890306965588978540998867249211101480283406561313","8692207928399738948656932542206970034560590031245111935986773933625204605348","15637608476416401869024882238850972110833372037089777109893228088381070867336","12669598204312494473375073619877238350402945043293977570771511745611574832382","16616334625605176936980567982911162418468364490818995142903696985331911631917","1163200834805568140126700653756062203626328506237611307425250628210219525751","16041610680863194061192088972899120981403420072826095569108928189788820236190","1485762688270866341593102795846224135723956353869278510672453827372608470129","10465591192775317367399850220617549140835208588647063682168092729147098738834","628480199067443905553454924506713639209496632594088262104562612743482317317","7210896877414993295406088137202622580452838879777852359077871191438481498101","11911835907742250961294087805844907693452066859627391949608058092315019935774","2093810900034073789854713467831765389689217207207435832827102797378515246454","7316332248888955471691079886668562640307065532660633721227877230740628020368","7804446746702391652537124203793383279157356337501099468677395646011809002855","18910440429970308879020694056972184798217526005233763076386677985579732780960","9610975349131040604985022571983951666149074870170942534201688003881320917838","17957610691765510846224620449273827083035090852425476724064040238248935806114","17910007962144492288966445879508805020266816019619525944582842532644165685687","9610922204238464266045892723877028700073630228721218433482102617177004327058","21663624777984908390121169741990276519059909920550321944053456972411735152413","10453951435939157456972619605233310317770690567623085396555439358106180300582","394402585784474755255010678877146277721999058812959032441238214071498698479","317019630085891281982007112400164898470415460760853681199455982017606785513","5734106043994788494416401755415258833224830355233607451477356834340906098877","20439467734505476876508057572893354673071652865464984187467899751949944425506","19263997470335962360853396704155796719772222128210770085160825437299656359536","3048218307014570030280552695477431051318771588295405123436502364809818248365","17830144725609578701920711768335274330232537828131956303357587600396635693866","16806340409427346601010611571850590936688209828901814191327225439914395928526","17476277874956884192255553909550607089065695214720398232656738720463118538300","8011886289793219620837309163815820711965007948484205770400002090864920676663","10528027359464829644873629593431556966885297629756628001404921067217334486788","10118027992416514474538346210951596829926735129756446922418577321458416848636","15816136336066729655689709139614358417346063662559471132895916002846901098936","11844212074487401188957668494483788392269782775451623578396932927982160850598","11694352810615130705606637622302698599819463349909487585742080081349181584309","6343689103802924977280083088777909622863587188742490700942354335972932141451","3422507383668651214654673786054488510333384059451819412470451697840918005509","11347550471072464290438864842897632797811318629831345897732551644506296995261","13904221862691652281194502404678977447718880417080730769015289577362390052168","11244408132569189190213857539646448151088742189054597804958148347897987545943","14597133172171261615062363621614179218470366587557874030722494854937627702396","21876868357927215227870271385803188591397930323321195522597046558711324659381","9450720603313752600679931320164431716239818757813929439713523293809790243662","5437583872445302575260942054712271838317388387266962455080509566588732716848","6092453604757014418945184558450014958918944629870856297968892634890721923197","5348266935131174030560202423263539338328512606301335901792610217523637732248","11193747367003828097339011066107202840997053047252955961683259317563576878881","12104234118443180762458893556206328992379117535659696483082764905269458921368","9944059037714308508689520849314326319292606930950099403068792489261553095256","7231090157664902397325664177857839098783657771561794203002721217819798557990","652609056599967690644815478101156293162253052803191419340070158796213988016","20385633130559346216035967978953363490656894626058553401138267224557519672247","17765125468024678617016631124952257643602733691144491557816014408617923076512","7049346842308821464681443792277795697054627424544966401852822571712486632382","8889225179067909487727148215144128458569175394373548341075425710131497449393","16059969452653419192222428898239151603844890452356496903051558421733977522752","4117080929162929350773995346942624997229256283553604686371287520669768380750"],["18969435646043482120634638651933026262222324680044720458537140185274432642506","17103432614426877473417609659901345529008348024930656766812241844871979907207","5698505345006933345670092894572991610101663528414196956568144671484406674425","9303109746073819705761957280793549470901238467055318421080578551049345554561","12970429173973220342611857453626352927671879418741313074919119007949977314030","224182755111522568279027822256620034975073304536518441204806633067422353771","3593307288055783823763975664133712881451255420575462499439082138908733220949","20240180591290375835644180613238585154152878776542760909004528109311529758253","10368083960167625780837059768015153211848410927296385885005860590978721591646","12977839569205419557994210383671203212787119152807278718413211525902194434270","11996545598840495997221408477028260975353256634424115754292546540941301173416","17184582510092750873452968396735059764428809335614447452226968960940576232170","6239444493269126580760495617969890195614918370310632240604601773843225041572","17998840056875140719979691854538018438359349857706291139836434186441821321116","7280102798394657836300252467333470432262559400947561396028680728108872046059","21178765581970765480397206929946055989036575759673931807673874190867881633945","12054573646209183654938580804913999979270355495778670801479612923110633843067","7110400354960349693886059183968744053242282030299916564864027376391345168072","16232584308139152504486718024900629003830416428125626171574998896697794838348","11331163847475686417385101014904203949808576776729722837415233289835735572885","7116056769600052254149232810813106652197545884852323868174393655453996107949","9663891884016174494459748723230744901018005497719746998707868790162763275569","567173495698615610154445749939652573715651558772186006481126260038542520529","17161857651861283741925293981698913166221811317404875034999021955931858973010","6045363269180122881254828230951348380655800054285003372554146883080165408562","11141508300721582673062432453064186721789290688711294306103033837397427286013","3115878310317572353506592031988628410100628940540951526182579873999136619092","14322104345722223109394836097176571505582341467457595519129528979305184132786","4577449710317233666632543864534440387058223802412223795444279668844113847694","11525838301688954968259852417990553831563714102399389709461243049861353234765","4012572579155643091591107861381947212161341325440826278749780800387504878817","19651512153393013912963576895000627339867290918677959569477306624675160025540","12682296904515717252322021146610115513646789634281499404806622819543280000887","6178165206106810880821656837975095871718379514259562595249090137881905586587","13573510438955789929045571220146437273672190776489806620543526815530659471562","4436863564387007135073434410534524614270601038294814880355255236700627359586","11183755836078581864432648916887494334739489285497171695499458418452377740498","14631015051692201884199681264061174611387583296736667571167989098385955746957","5885758923310231517955230435604574288382448480786574244072266244293660560080","2979946568356137469016126964960318381653616324479508082829435590745495745439","16242417866285951270118629150379254009644658872829001562102568538665898271911","8215560779716239862484848152356727553468473646997222822172883484839749077207","897378910873429118957429667044056757376728946536751627974758278610599183708","2582668374327803959616281358656127191503967444320757769148597805288806476928","19283532067245251138229236979060099868808379559300223547514638890956647210493","12925349280448620363846545900815419437642218683311162147555075242422723953583","473988874945623551740537999131034395052918826150136221554648611651633306111","14055863508606973896427869464491490346786951133600579775540562453566655604285","1213655127841860110337347991967832355498741665674336705823907216576303977773","8602209293170162276975004286078100992189350711325674036078164225390045166680","17063515512365462175177019492179480821711471560116721112222315020134648003789","12728529986577754860363443573072142591289785036186339255023241157662198063789","20099387503329734595628374980285713568221338753684454709834603175380638814792","1238855512763839218577295866714349808254284907152502457039881163775045084469","10902241016023899463915032217063144455323247427787341143173708379568360231368","17641165524485669586686527516414237665595904389337984095504700548670942438206","9989642729990046171498194640762227628678838726587747219542107289954929159873","743480212457175351815916176660427438225028844378168895391426041250977841332","16984569938756916799615269379730492004014356217827963664030646759909623038109","14916437880254136670460493718847114526708168507498211879488227456873122115404","2209750398723302829913629215887516078344425740739225508214444526821649195104","16544727595528068882270730708821409049957380799468889117255651122284213176771","4923303365223269470730332090121542788648840909760759442623873549890710401","5999654658803632539009339540202640818569587242176811689438015299160287577770","5455632054928279534256185559152540523596212052474620164089620371125193644690","16252328573255789932914522194025611834785603593544259480867571408313812746892","1329070051249193472871744197328594506906530278844530050210818759411781273538","1417767276129879851831341014115331057889890002235734717467202493235618061166","13409036826569138491394872397344872030116770809791988813995097344485564545260","10450480736447055508841802153160460797398326773905835053182678311383940517012","12062299537423390959236241446016110095894181704400916918696604296773657631050","18260131960680045545569341557185904758974511293892467536088275537529932750138","10545406234079636910070521915357063902463489914925688702932318209309208281570","9734164281870552038502487333617286269021126857677710455417566131473547520653","21429343555173138815228628627308095629997404685528128170972282833076352917900","16239406483564999765310398221778890449768277427162287131632643892840020865274","5807451467660644434304362767911000791690953555440952882578652501427000319384","3146140254767826965196625964878327004822416376106169734363134365065245163926","11939091624606862204818206096204798051194345879240825595694838106805026151846","2760148423780882446401574475973807246239871477211095071990644317551857746656","8837272169582483349933719692209343021612366962505326122959793719335718723146","1703740925840902857641880818188029844588261260954220969291413282583187169378","6243795664309306901064749707401202569456963087775992806979377588766515806991","2529139874030382378610847672890559601082743563569956605232884205495411633527","6212240863409351239342954375771232899283549930708540328977904148967535114844","20332949288987622630776958449543783683909031450644714425999950961637693544997","19909896879961990669792211297698122680013040944707274270365383074783245593222","18079479148064310027631716063285187800983262694052677145890967126498288846813","21171032340932158186823531905361209050281518380244691584260324603442521077540","4848933943431877615324366591467430010756396329162495491661863619875973866797","12774013747971002510887410107643763667935188139759292980475948439030165784996","5521552506661611952832788177060411055288024873654623943611851918436959902016","16164881557321639547528630424864684506452840067026690764624358696227304122869","15088224165813631344331771906574604573485553794033413770999039745667059160000","980434936618836748265005252338374627502492397360303371156949884051676706999","18603620142161516213758020910462867128958290927040096923618593625979876137904","21001595857200637852411535109344013803241240897394910419465228379600071969740","12732333621496139908115472914822532686767504042620292789747518356774047335413","20335143841942733497423845557315657705287964461091768819325830179091625232935","13202112835644315014104620252497558926027180846014239690025435346346186015369","18116499930093766802640305077656919846710308219451582605079701826883659147366","5961945477197513304392056081487311623855668929268386357379995406333101950537","19642107996607170129270323074722303702205329970277504103558381115481086029844","21780434943289128038729943751720440639795341804055938207939433817003963963776","4581216462525880747130350067721742693141128199469333587462437854612273376246","21602846685766543262880785246883620685585654938046574512893738131493787216234","585134328921796339767981973990113064056188458938555111835102367561168245459","16261106069729474715395175041526536639581117585973493397796692932821349691043","11083187298689796741868379030983695998245437392226708160851752660432758791465","16088180857612505805607891539864298235969630492300727800438495631961797047321","109021134022304466376933045663568166315851813792580697487141582286847787403","4302992633351445772199943790870488785841677822649737387651103086028893540155","10407670135367926693181526857927767667610919046360055624682758606161876404239","17148051590983340176527705771718389424887928636602952667634133476739929633082","13416355366032253031070946385225866630707543177652565161448830342530517800940","15695769162982583973025303350528216294750686446053607423132332142988170006059","10114333353732801592737208656786858025279736253850406987412311582934464589034","7064560534224282501588608638720523922715845779226518333690028178282457713698","14763909181758837498623807129504170610923137702598282788324655302456545461018","1733825302507239775757030680344138116729178993372845005773894155125631409832","6390467913109856271987445945899790976151055221575187194974575251225745914675","14401216804685995096005930983206000107641217939280833013967483818201048401550","6358218860937033204161693482786913241710674931493147707043278079401623242570","9661482524994495858846276600253857394951627331088619579118293869586943860942","12988065713396440534925941344087886963993123959368239120666546835423981584749","2437186541917982171786091597818910934926076147416651845520999215915310455385","2675211847531063711926406368627832647216322043941170171217184181074995009587","7633350072654104140294028144945851509193545998560387360542054221009339344803","17443455183428196451920016094841483987753016505195256717427056788100632180393","11367678866706311999744123836486085025778400825165946477260699972883855412378","21582889169618495350275521397442167085087644197585924716093361886602971147165","4707593138334739010400428293446093109841553810115894878120776017375111450582","19280303189907769182758540652697237921348583607908133860566102457620260968720","9627044109546546139536665073847139217151357865050486785625770651260842610108","19144366409151978612369446009148936918757040306458688109373156725522401179647","8521495181897760367023198310013033243935117186788654873631938982791125230248","15879814861232652282359484386082215582270143476632289802863491037528347325366","16264852368877057573068459393625857300688838087213167476683042713622003070045","91699440990169206951875306606933099894620475061183058470453915743974099824","10948993782658142883600573106629635483924733568022735728465381169858183516494","19024306099009625217398787099886707701713294301539237699423491474478128756957","1940516774768355213059630714556345969071859057766140067005516383898719598878","17113210138891309644401748733280667736655791600722737227593342771234914294126","3348309593610055973701524947553675791747621003197622489783721791289497534261","8013119824175733900316130521895087524398577973455687850802453507794684251084","19470604871263745111103615508325755689700111882043783069013576256903197293562","10507157168593118385085257898275916785917236541698748448003489087256841768314","5848677714464496330425870998390238095677947353935105132218899159536879970808","16122755065803152143556549561139727146503160286831509235767297832391999723337","8728353203468591568401660408962126239084375688209208781078314861054571666364","8783815327475538357679947471840076797979072584259159261795042579391969399199","13840882436035603154777414265380417891125679683991606798753286335589731244012","20181122072254010527753846982290461100223347363439899291547607129279670511770","10671689496317607198182050976254794321482563463350205448274937985617975524119","10149227218977374290896139389466078297393822109905988161387872864711623086716","7084028375042571777540656284649900123650243685205695055201939840164629713612","5401973923927438623350232195236004101194197887642573161021846511602802494496","3832274208665016490671856924813751446244214692933133038366253110631333510275","8319624212838917951172641192255889821610501354173359879521283466597511208819","21237906291812420729330292734615960911008171585658471203597919856699164876048","9851662759407993557240599226997377901343187474162842694296249473009507483470","15421297264368699800518575269226028158045175313916812847559857442746464102603","15939238937734494624060847497579896202005612616314634119589693599880823487193","5480776240473741158852767498224306009679397762394285486087434512854513986750","12442134322716527024208205258800179776945235136141049093891296696926433099185","17898480765223420297727846819407591439947619173401010973103336860354411246448","16130201314601780313111925692441180585375631006133364793370779167307934986088","12171530438909287640312467398258531021435921130568049046251005565947196861828","19066777117609684282314906705080066337156266726423303341941054660036534683828","16707366966336488522839580485687265530989448897978901313667672756760149014480","1786281497380954254232767590052132462411655033696182829522770019995987669","2851527361413247748645152755477850253224415778897394734137775092737743984865","21051625332393268198990518619678204075667562338174101349907432441880903462662","19959950675661031296776030038659302704508682515089456475507490021206276914967","15774938064686630921323371961727556204871353759645135199632989883478579340769","18590192041314308501671694866227238693992977637412986436546629185448447637791","9950985759106301596576903220600119421581868448295805069215603119966151055397","4305166310142384958189247914229231247457855659501220849237014855040450579524","11942927788619601884006062108348627002581319717225623633171259524527436612010","293529154466784719900830447906423223290259959979995400329107237661671630991","21834822919232512268490324716095810404301176288563326650825312494694606554973","20649939525550943879973327670654852885657868047378627611911246799241213860792","6247073092425887137883927318846506508236134161009573109257639881385126831633","6693242225860668027087547137069302551383032056911526571693152705956664664295","3565357948887355555832034003803494448884142378752739982898093740894546163124","18653864054141631240131672437025898803340333150277450995038675906143617762471","21387294514701134530888350083873742585020741421108788967756685676969308333045","8061251682238249924726809960669187601807668937408839822500163210838328905332","17917800994385352811590693308126731939732464362727102867175367422865623482797","5627973463950683068604223017253443783357374880833064524050440390298914418079","3225287631093289119845158717284892432248127319311477502096042136257466805122","3134663584928048034465051745128731406860905907694209656452793632330648729956","13419119327520271175013807975372081284470888590668224091364887814180568716803","4223586498148962705740136127960179574391135750947718490522788066072143447465","11634669727494109563871726360784603286778575782752655901933795749550927053919","21292563664236705245021709055496898629865645366562484350026487816593286262256","8925429951088100408911805111080484683181555684876020289253541863404707523229","19951981593094774604613851887896571377369190159764293639319214670797406707046","10362892097893561540236333676682113522015750827139249452999663223441553813775","7092115579898161278093001072051679413332713829562929548504231362800837832691","14263955794899719250846160437025680334636622926890774491087105842430447588783","9990798689202191696592782375682922759255639332044274480689351501036292810883","4327356111684554701971750660462936891146743102566173142044441187514812033489","7853381349147059260934578079500638550124728381335068960459142265274432136542","20989943930255401158872919934985332534437915567961267142438126105225286042479","19075230009179054888223336581138727736213599659408504073808522387226814943183","15882084722413318926112156458847038700761140258164309814253269542618643032324","21802406430984572797120017865211017163938438580638800529569432524746694145072","4704060214303784116033931632114815438105622335706049907937586565121175931766","20038583376503416262758156227355171331608341892694133960649391877754560813210","11661746212777118901231630882381345258115373193579830067147831971353301397161","3762315078896907099111442450322945535974066198623855000659177788758847372622","20041690111970755084606625888733970130066665962242781360020678009904819675628","11021640600907415474360058717866864326818221094045326616990182030128361704627","10593428601257059022763083921325555917296903112603280091669892552102539333860","7410541106976822781537653722321446256429462596045232643848562621219942668059","17666529707821657519967152344408380821626156599795214423104127169395459841127","1786726684058573644572614129147190008479780412945195324949606408792387900657","12159122179772338045754640736395182036272814913050717145553658861586827992647","10824962380901782018194730863249161682006513723542063741261245519290247181769","19708832701583763971829245900723976465025073332691126702726739485395604906833","6535479533883514430889391725484588306414624885918757925226527794123281496007","21537825743277536243748694212683728486766121431031752539837232123053249475189","10849282675482115477924751655764175784976948630314538337145012361861170842951","11746621727193388581942203028164861416698167945295047631347237773370563666390","6784146125940179432654847772942395741201028940471899701094993900380382409795","7297868669723970723450266686858283386955396020409836824049763913161957481763","11031963113738686438083814680721820866699934108673819492951283903109509235193","9094406855743155227440212974241715966420226479205657357127348808836157726034","19619511556903023096385985690003646080967101982499765977493745460482328170544","7735086589410289860074350346449418301995455206284742737964584644660755033646","3979061985473860329261860855109699768260440637068184183314495597567036540708","14547966341355329005219855032685254718079243940143150963493190392892534491495","15720653032305457676625777702860379694045245764387142905695020019998826761488","14903988152807952234427288178889056011694681512621882550662997572756368840234","1436923158995765369610781242645756779965483467877654210097010240559794100894","271148599935568202911017090154177116579550792758711911111173466395166022943","14344643994536654625267812101246206117742913132460566212150014153505576364558","7415311834313069976285230866480921010048914607327490037006279941231817318925","17632355002885688870371030268408898110937780966506286635600502633299130363343","20073482445067269536244395177112046899950530759944155164451420123052395902676","16365532509875302658677214586621620516113468980321009436862895084027209384844","14002240887827514337225114739505471327030961375858530715399048300547826320800"],["16148385635794502006656993876456453477156893519202553337774528851284399165587","18695248079578135667791503906788793193113592948992482227483029667717899306931","20710186437534107967133757641580239939126722671465624702714142447426616793058","8874284363144170684109095939875781811593532853002866553715870598109458920153","13630427291993099866916288230179590685647201006572316593093224339632811911568","13613068297277094437111011825730167088683609332835206191139809026234188891910","20899255664387763854405526399956252351224818203978413978878302383803690947464","6703098528628238616196233820489015963696310619447846044786687110754086569097","2540478323095836099850277459574338655400333388783335125696259511531500742043","6298796096192433046437929297694144084306071389408290915823081998551623596476","3732035749061838214639253437891028758502317456215976859226444911408751746135","7764740467473113540606825966889031117326410817425136956125871082764509897384","18237025778927068894521039618849760591939407007880480514959406960325199890631","7091662862732350905516707372491238802910127606378442599082165188901824334072","162177154043579751316565905887856816682453881328035207672775259201245468054","3085549414535743331864416373164162763585240978562045245523688531922253920840","4542775876504690618660017550024057935132012183168999615557869055557902365748","5321572984919803125005017276762893470602741010171256605794521964292741815381","8700105926515134307573583482260976054239119582423190028651679329496462821242","18265522165360240333278271542976885394418130479225688588207800615333064187581","20364813231689891945122545026048619231413837858043774229227298958728743671013","1607110233775009964588837314022834156411143341949718441609543851413144540441","3553252130700152028658387197814761452952701356815035508146805333387702766214","20359509605864933293928410785796142583416321532886548269404826597164492659346","11111776472925193878830605990703786983195258747070013545244844996398810135144","8384548569305939434053129821234213747163425254984031754887767032498978989767","6040224765246892738777358037412699865277334244709467335193990744213533092563","18096188389921337223932585803693551609898860876908740803954755499349080170182","15377066712113889433881026230775224035280606433291023745425001735271200738858","18878741555525613044624249617273252504229817984336477433359146344564077100018","17106082251054010456037267794668741976798565180206322754020291178923172316542","10861402842682255351471744909738976988540351627541064180500927649024004654423","13659628174694376929184637691412791823794495356075595491766296935821231432348","5958024166102129015681193639386373327827604309437643952209675306640102074010","17555263756531184570213157389723887410115228646866071146885373364866060141768","1083276485666841020180736778142884218186550518008571076299334965171730686044","17029177744167027220588739480120745311928687602549185294227938657375207609718","884660595921738920998116008707594240876568073041096146592498060282458745427","3751784769987747817382003571948375070405260393282750458664156099636212978738","13822788535198798264723831834101203597964409939006268803197191548922365213139","14196904159551675352303771436599152936742791725794746234994123985465341705122","8881731569018126422697668389748471407376559979642070756300284721932632109206","20731292075973356583178387331264028874263275679192792078317388964322342053007","2435098660590699866584915852775880507793567160998987887109433071980803545096","20174085171922311882343490792469229772663421025633398262139220570402983719279","11032809349800094329703075552065025661043512665362385725804778591803139629121","4010788596878125134896388195056787255040608853055437757348132403775933302061","15378874498151850743950983923579944296910571766195071374970563181443086543513","4626674690674533144587016472656311605759302154509196005993163214900312286239","7457086524483680118292648675060323947410586761559808339072471175727903306541","11219684857494773919365959370872387606683303339503868884681622918552384895393","9198479455599271183781463072934891535700131421274256276831010218844594869263","19360126553499269187344493371060102208053807281243046702565559963446110608429","711090668230036398754479731260248950687766459977982748009270807109079906461","14660421396862881160492607582369610152041069019865205423891167051370221518107","14611981593002334899297685454620765927792262402810965369305818698428577509167","9536411810214547698905728032089929472477130223296908057693326861744219203385","4132192415505341951748036159403067083898413947525187963451472677829759795370","15789062116157475059920859416618519706682181464110100964962841940398946419757","15040549395659643825575680401835338164496335089589242562126217171287695117962","6333867382617031603462360886779789330537520564379131029381592695365321765094","10816061615800027359017956351876276915807239604951695855616271637308450392271","18737325544424458939737078300712670356321606286020142666659891492268667507626","13076262876287250418932519737988219368117745975197313785793826704767118485366","15998196085573695824568158362242733642706508233807085141547825560123153699500","291058211261676840776403326532138529205357318099135055486898753586370326970","11744123224990962018275033156051068963559643810287636870678519821354661100337","6728151368913232114210717620347363451346167352556242422133467132759242020542","11598009910434224900821836364205295324974852548908599292187404412551538946459","21225599071003427731090622752859426000940992200127905119357507827184493803613","2791785570651216512210158542261795711020176614282284981172329835114709556486","10197292636267687282717077830472882945867553104221295751953107399790555670513","6843148015485022250343371779936814138322731170807425618657041958051250134680","20042176890402243638836112058073395399457479895339567167442302516039579093601","5166212409736583140272407275641575333032993177888051918470753929677339561050","2043239552449331143853703880377457067965630440355078552101757994884513747235","3316861361313844635272489114703092743597449472925216973284117093275726856777","17908168405716846268019752554389573715847813519263404969011201349157766830442","13447037172264775773890107733458023496273639607895641031055584731366514926699","6061517239121006186559148293051453610008828903347018513179776827464566785836","18961206099105169439485426351691509730567234870855800053489953259434118593656","6264420379758395500821028201255519013804644109070491063818224064306918614244","4118296022771410044669842458931485771492992845475878659184455888447469646109","9941772632295156050023206600155423335884709925635867727148712163356496715723","11146550411027423201234035120192643491528628532445128063357119174176480678975","5997329989194442779102972330027352620703081922241459963260947010608564948635","21789734765690613950521879167856331491997170825229358173040598538603717379621","12540969591398892861170968527989032080299409461966044971053703363146894058183","16362267881409794165015215267125350551427249277846021348659537819705429125812","8363078061883551189562879658887038248768914641894354817944599478018948447228","1801332773816804395852758228544136482657715221685804857356313326042698791905","12871454385614481293120945555110854641535466714843253940912941056440342760127","10041493594138323711738481211633082160953725071662545463703843089797560675817","20910454015352408839178485034715287122110645298732558313337901087274902517330","15671851606631990998202113654344552176751050129385670959814873732009079298339","18532392832949862715555426320501254969910865728774343591142288217145335414050","2258552921244621587167334881399919309675983740341608410030808970634760515196","8606071475532376170537382461820334293768136055619315815989819023144172092906","2866754918743256187393775495084238133382800352750983338113860498105324450175","3244450604726973850366290660322339781690759611390957024231415302756293335195","19987107087352371365464843534614538182701438093446951326956597850724106211359","21340624387796055871810255003040159684161101839655060787785313041716547962556","11297955962803432866889561820362394007817752904959819270307436163159401079993","21136438156107613758467955404745900089628936059077356835003897769588067113822","11455712548507121038477877501038555617057142569993525532299603437179002619671","12792454268636186527477154472384171481740627942439823798932215513544075851494","20354174376158405375373678490791567246120718519221653405328388513404776908976","21693605991425594444057521445771211084444288628841605839324469205555127614764","10865393566192881868276712233043859466729439366623223468982114687448346162122","11388924945526279310056062841876911579924704342547580113265664641587661611342","14615757032114568441587764561578625051156911546349996736293243756928883176190","14326867768832792823072959649925566156860174943590528255814006948645883851334","16548135135028115096478599858479130975377429765910969941486408062787659706414","14526246500000863910320685084661456315991869719696712493894081683163053744012","15357380349330953575129887530969878810727346141887184420258868992743346048835","18169572796088376794271312375158901774867684342821288786461982727875040945660","17579917374951115600968472119471551472702797633893162537298571873834613152454","269913161847811339585109130075583121995058294109714559316143817914406193258","3846686137727916276628741868171174523330136480870733767916071538207288236517","748062271479752282791051313637808755122546124622530614272405000333148994692","5575380332377002800922241042086835915208878388883916656436914523059749880061","14002240887827514337225114739505471327030961375858530715399048300547826320800"],["19629979615516702736408264077080614183151310490257214657936758672546548299829","3231200466342548981384144518372668945114895313423013416632295278409573893820","15159249073500724906069538777290316785976718707681593824036703597973324678967","12084034209207367813367111690763738404901602007373240631710342149275570777984","4731883595944007356479011431583850418479610673246369727415152601865027907410","3714699052063803190763840382262455059694257959243780071463187578274625580197","14754079566816147887538577110596147819220873543558719478887411469785099080477","7213556124268844086297221549426824853353210405186973988356771600323332453135","14501396088173608434081585400669312780202574839423222815369086469300935167186","5618108553471437835509423602001961456529679443609701005170146597118692687870","5885984339733704676522782169930052969123775987099960468194691376133928650880","3952220139849487607723775012719540051417177748971785929119090190034828425519","17476562808576784281040477105755450646394002037133357743835388338754445410363","11754320658917649678588061114068759839285349733857614535986214188781843269959","648627749185443549506054600465154435487570256893630763882130423930849194744","5064745588569680970074361447325683675130513161978987634847769710003237612658","19149709249238149530444337142877457259994017745607043160247424882480292402109","5433152701796179984548137241382760291250224723108852556318184659040572254101","6421761818518585269130456141616089138420608450787109329087711801737598914455","17614458331568000723695289286116289275451556289799992754498945468362836884086","21675822673231425383076748928840049192051931245577418173085989961854641370742","19373480772662852304951236565815444201294961208663669590214069487464714845035","12474871386938075976889788188677410369069502359672018711591831183381020234871","4311731972145545805041049029379514293476121542920508812312732326710354135289","4716546317571601163592592715086965668310241743617472918264669727188791935497","9764690665872660505289349869279899361942269697661536310745274049458900750801","2763876966280462772689259599063502037424920564718243832582047288988076594046","18935606115553796295803606528320261387585352142963487901190377686512083936005","19248567493246939240184304516866861338816019591372543089951304544377373859768","7425542667245304133988589746934497120768813672318340920603382593326972371815","522176225417492276093586202958312500479486244570978452663371360485991520452","9528289923633559297797105482440740699112880763537881060823410966893254285715","2351340045359453819112017544443583200912628005441909981044052313714870559456","610752120308719982350462412482989697901036447297114897204421552115524137663","13316283030382841018476340860067620998642348221574766899211775083625146021533","10301182401526354271633913486298066840176539108806917206008338155653257884696","6173747138276996082790430436941971327024419083405692564893318137021720730514","20200741158411860642393376991438033486022690756512178263243888115798353844018","10105167078843140134906153207883742720817309555679962171291426406401270862500","7428925066789467237958702464933871123488920551254252941369975315313550644894","16909041678656761669015348827547535046827420399669630214222864556481975893925","15883892122390680419257396919267560876004203606407462446114083237437919360797","20769621314214444662985424805752734632215468824941260068028731591878582707313","2185416948965976866504700985157295491115662998183070033384925272215269038674","16709368290726535252863041555512020242890595265525040124164733896265443019289","14653070022410084882235460317073279348114765350921853045909845846136888192109","1780570982777863233056570601813651604646777578547086321936635491946120781646","10401565469553580689383348652577447275814550794036106199272361623908506396266","9846123508419541384796642200699627602597870432423091407471038626944719436555","20812043390545421206210683029182292841764430701532875628200031365885866023744","15099019015898107303796813257931492081246630201646251420915271467028132882240","9542790339515666295745875970965245001619780974389725626407000886139111324479","7263561153502804322100821015132151950031591779234386134134101516342436554416","1100354358397781311617014594111403276781041086597574968744934042849283862484","19593210210386431505170168183025176567890549406770306644017743974749819116465","10639404260288754991150888223162163782691256488455781930935975640489458278740","19137700368037160859145173463166561484777379983415429967264119618628936356390","11465336067184424330235453482594899066240042198163613649548536394117438185670","14991772167224318096915533239585576754138473169493344169731091510389835039540","15535843735730895550566667637228451760338954052013598937532969077551445867335","923809028130978643530132044725154313874535628272415282699240125901120203659"],["13756231537354844784166578969061939488775523709479818982036120687405252420898","1491272584398706125659719638731880351422515003074015242618846491579359249921","259378523011206571296925919501091503838791253256459366649030057205376297142","20295436586900249862035068495316488462942615207975254978252323444281242141886","6192630542608615359461163506957242432415678776481136147858920338982074179742","8542789035257515878021972298916624061145454779848414798371510172842068461070","15889750588066991130892490032291108361720832857279154915514401269769717808960","11430648186249885254541794931696288684561149477773158637742228277472768712471","5782556716265264489759651827842104927399664109670444362368204802562241193533","5170836012513919648797604279191812693905708529463748895959940912553061995912","18425465194787988180708559751143034358762334616396069091634623864689325140598","20058694987712271572422584549349249167845633042013609424727553545294120122762","10681041613100856516705056988424432833516833253770003684304033703824584968785","13169871326810769000449562721942410326205217147130874572360080309893393609247","11256110101953394119568542984511812689589489589328011925146716442480428827904","15560675530811268646605025058564197068486533449674276185218410786392637700894","19947610835010558043439020152726762110211835970446356138800344546840495120703","2816825437711960314082093092621480152944627035713126694910255346294280466706","3936656748863785940020909332328769427595475112867999683425546491000672665653","16921510054575105701645488028996441942220540560815109627354699954075626533079","9270833461738756187068576836517582107866901832611345410375908946212619439600","9954481597120460781971565926114383038895909581136839112973142455746112004391","21644326859020343286728018203927345289091892015470885056326439938549081978543","380068220260162450166803579378045788896382576365481252501720267911795766412","21365667189324936564856874969583933541872863451940886834536159655135222592409","20433732436781716177454341790724233531497334666666667188744114514819435001491","20726614536714857479436848489592012678124490317941870288067308231562377996299","6826123070608564511641371750601584126139766527545152095163119366674402086321","15957373273319279590397137690738824354386912258706442292568775896792736402945","18093526627364800776862982310936289758996580585291364379582618465803902485796","923809028130978643530132044725154313874535628272415282699240125901120203659"],["212287803505405628971141680085459831418644646004291822855605711915448172555","16943650594370606555451147614877764840991203753998088424317041110881862457167","3035869152266239261157406370014806078228207163668207011014799230901312864520","20036866866838862786147126935279815568548115699715586509652929040122783191905","10982463714658806717661912359899482234871950701920566863487394453903339117254","2141335061154740922174389147419374003359038505095670275662119250898070694708","17179635388428924077379625485357692775106479490042717844379061705701575340639","20293267629216954874294229934455241022968273163405981983739534064510858528478","5269562625493102281170380998502032372192733502666966246985773609345903820937","15917698443015017402207564138256582155987379928574923814430803966750342321330","13744799619117477821419584291543313096371782876884358205807995607173915899991","18072540584595531578706261276233607902210509756156011470118919787967195643803","20696233402463343818278709698214380017514899376720549273977000841561314457989","20551627277466298219389492070811510476676911769990308027049733213648603298161","2275175786755922940763718251310980262113487049393101717631284248884005876390","923809028130978643530132044725154313874535628272415282699240125901120203659"],["13852533760477796356361670397020048120334284388068445871557336018287610500177","9527630879911506223483936264400467300726349067028297034542978183014062525584","1059350926303347763927811322883587348840747031248108565023085333743705240513","7439070021117502470676641455967914951606534844678456902734550172836290487356","11567023273932077386323158935307027757962314231438153859151995872571836366291","21235901845370979503256168030858550900589883197692798809763439068768103859846","7261177293363040942241643713491589808723865126281608176096651549357439066140","11990349835032046395091813654735540088228736921945567084142818610206846606441"],["18030911098454810451357836001429313993387026763605498739759472051187935049118","13689983928015408821670212635648960825704701946667434371811641526133796372375","19396912894394371684674554658920284743234675907868748799055727553068161213920","4195205376036446495551911501204244528506074570056226981532255019523131789668"],["18747745113791185158225750425204668682974678629289351503204624420567653479357","9504114532164569569785785049935700271662586918831416159907916428680430589426"],["3767281508729233884094493572399094381073853238678129901350955530554467389160"]]'; +}); + +describe('generateCommitmentInApp', () => { + it('returns empty lists when alternativeCSCA is an empty object', () => { + const secret = 'mysecret'; + const attestation_id = 'attestation1'; + const alternativeCSCA = {}; + + const result = generateCommitmentInApp( + secret, + attestation_id, + fakePassportData, + alternativeCSCA + ); + + expect(result.commitment_list.length).toBe(0); + expect(result.csca_list.length).toBe(0); + }); +}); + +describe('isDocumentNullified', () => { + let originalFetch: typeof globalThis.fetch; + + beforeEach(() => { + originalFetch = globalThis.fetch; + }); + + afterEach(() => { + globalThis.fetch = originalFetch; + vi.restoreAllMocks(); + }); + + it('returns true when the API responds with data: true', async () => { + const expectedNullifierHex = `0x244f31e3946a896108faa5b873f3389f6d202aa25029fb483c1003780868a55f`; + const expectedAttestation = + fakePassportData.documentCategory === 'passport' + ? '0x0000000000000000000000000000000000000000000000000000000000000001' + : '0x0000000000000000000000000000000000000000000000000000000000000002'; + const fakeResponse = { data: true }; + + globalThis.fetch = vi.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(fakeResponse), + } as Response) + ); + + const result = await isDocumentNullified(fakePassportData); + + // expect(globalThis.fetch).toHaveBeenCalledTimes(1); + const baseUrl = fakePassportData.mock === false ? API_URL : API_URL_STAGING; + expect(globalThis.fetch).toHaveBeenCalledWith( + `${baseUrl}/is-nullifier-onchain-with-attestation-id`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + nullifier: expectedNullifierHex, + attestation_id: expectedAttestation, + }), + signal: expect.any(AbortSignal), + } + ); + expect(result).toBe(true); + }); + + it('returns false when the API responds with data: false', async () => { + const expectedNullifierHex = `0x244f31e3946a896108faa5b873f3389f6d202aa25029fb483c1003780868a55f`; + const expectedAttestation = + fakePassportData.documentCategory === 'passport' + ? '0x0000000000000000000000000000000000000000000000000000000000000001' + : '0x0000000000000000000000000000000000000000000000000000000000000002'; + const fakeResponse = { data: false }; + + globalThis.fetch = vi.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(fakeResponse), + } as Response) + ); + + const result = await isDocumentNullified(fakePassportData); + + // expect(globalThis.fetch).toHaveBeenCalledTimes(1); + const baseUrl = fakePassportData.mock === false ? API_URL : API_URL_STAGING; + expect(globalThis.fetch).toHaveBeenCalledWith( + `${baseUrl}/is-nullifier-onchain-with-attestation-id`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + nullifier: expectedNullifierHex, + attestation_id: expectedAttestation, + }), + signal: expect.any(AbortSignal), + } + ); + expect(result).toBe(false); + }); +}); diff --git a/common/src/utils/passports/validate.ts b/common/src/utils/passports/validate.ts new file mode 100644 index 000000000..3e4bb6cab --- /dev/null +++ b/common/src/utils/passports/validate.ts @@ -0,0 +1,256 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import { poseidon2, poseidon5 } from 'poseidon-lite'; + +import { + API_URL, + API_URL_STAGING, + ID_CARD_ATTESTATION_ID, + PASSPORT_ATTESTATION_ID, +} from '../../constants/index.js'; +import { parseCertificateSimple } from '../../utils/certificate_parsing/parseSimple.js'; +import { getCircuitNameFromPassportData } from '../../utils/circuits/circuitsName.js'; +import { packBytesAndPoseidon } from '../../utils/hash/poseidon.js'; +import { hash } from '../../utils/hash/sha.js'; +import { formatMrz } from '../../utils/passports/format.js'; +import { getLeafDscTree } from '../../utils/trees.js'; +import { + AttestationIdHex, + type DeployedCircuits, + type DocumentCategory, + type PassportData, +} from '../types.js'; +import { generateCommitment, generateNullifier } from './passport.js'; + +import { LeanIMT } from '@openpassport/zk-kit-lean-imt'; + +export type PassportSupportStatus = + | 'passport_metadata_missing' + | 'csca_not_found' + | 'registration_circuit_not_supported' + | 'dsc_circuit_not_supported' + | 'passport_supported'; + +export async function checkDocumentSupported( + passportData: PassportData, + opts: { + getDeployedCircuits: (docCategory: DocumentCategory) => DeployedCircuits; + } +): Promise<{ + status: PassportSupportStatus; + details: string; +}> { + const passportMetadata = passportData.passportMetadata; + const document: DocumentCategory = passportData.documentCategory; + if (!passportMetadata) { + console.warn('Passport metadata is null'); + return { status: 'passport_metadata_missing', details: passportData.dsc }; + } + if (!passportMetadata.cscaFound) { + console.warn('CSCA not found'); + return { status: 'csca_not_found', details: passportData.dsc }; + } + const circuitNameRegister = getCircuitNameFromPassportData(passportData, 'register'); + const deployedCircuits = opts.getDeployedCircuits(passportData.documentCategory); + if ( + !circuitNameRegister || + !( + deployedCircuits.REGISTER.includes(circuitNameRegister) || + deployedCircuits.REGISTER_ID.includes(circuitNameRegister) + ) + ) { + return { + status: 'registration_circuit_not_supported', + details: circuitNameRegister, + }; + } + const circuitNameDsc = getCircuitNameFromPassportData(passportData, 'dsc'); + if ( + !circuitNameDsc || + !( + deployedCircuits.DSC.includes(circuitNameDsc) || + deployedCircuits.DSC_ID.includes(circuitNameDsc) + ) + ) { + console.warn('DSC circuit not supported:', circuitNameDsc); + return { status: 'dsc_circuit_not_supported', details: circuitNameDsc }; + } + return { status: 'passport_supported', details: 'null' }; +} + +export async function checkIfPassportDscIsInTree( + passportData: PassportData, + dscTree: string +): Promise { + const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]); + const tree = LeanIMT.import(hashFunction, dscTree); + const leaf = getLeafDscTree(passportData.dsc_parsed!, passportData.csca_parsed!); + const index = tree.indexOf(BigInt(leaf)); + if (index === -1) { + console.warn('DSC not found in the tree'); + return false; + } + return true; +} + +type AlternativeCSCA = Record; + +export function generateCommitmentInApp( + secret: string, + attestation_id: string, + passportData: PassportData, + alternativeCSCA: AlternativeCSCA +) { + const dg1_packed_hash = packBytesAndPoseidon(formatMrz(passportData.mrz)); + const eContent_packed_hash = packBytesAndPoseidon( + ( + hash( + passportData.passportMetadata!.eContentHashFunction, + Array.from(passportData.eContent), + 'bytes' + ) as number[] + ) + // eslint-disable-next-line no-bitwise + .map((byte) => byte & 0xff) + ); + + const csca_list: string[] = []; + const commitment_list: string[] = []; + + for (const [cscaKey, cscaValue] of Object.entries(alternativeCSCA)) { + try { + const formattedCsca = formatCSCAPem(cscaValue); + const cscaParsed = parseCertificateSimple(formattedCsca); + + const commitment = poseidon5([ + secret, + attestation_id, + dg1_packed_hash, + eContent_packed_hash, + getLeafDscTree(passportData.dsc_parsed!, cscaParsed), + ]).toString(); + + csca_list.push(formatCSCAPem(cscaValue)); + commitment_list.push(commitment); + } catch (error) { + console.warn(`Failed to parse CSCA certificate for key ${cscaKey}:`, error); + } + } + + if (commitment_list.length === 0) { + console.error('No valid CSCA certificates found in alternativeCSCA'); + } + + return { commitment_list, csca_list }; +} + +export async function isDocumentNullified(passportData: PassportData) { + const nullifier = generateNullifier(passportData); + const nullifierHex = `0x${BigInt(nullifier).toString(16)}`; + const attestationId = + passportData.documentCategory === 'passport' + ? AttestationIdHex.passport + : AttestationIdHex.id_card; + console.log('checking for nullifier', nullifierHex, attestationId); + const baseUrl = passportData.mock === false ? API_URL : API_URL_STAGING; + const controller = new AbortController(); + const t = setTimeout(() => controller.abort(), 30000); + try { + const response = await fetch(`${baseUrl}/is-nullifier-onchain-with-attestation-id`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ nullifier: nullifierHex, attestation_id: attestationId }), + signal: controller.signal, + }); + clearTimeout(t); + if (!response.ok) { + throw new Error(`isDocumentNullified non-OK response: ${response.status}`); + } + const data = await response.json(); + return Boolean(data?.data); + } catch (e) { + const erorr = e instanceof Error ? e : new Error(String(e)); + clearTimeout(t); + // re throw so our catcher can get this + throw new Error( + `isDocumentNullified request failed: ${erorr.name} ${erorr.message} \n ${erorr.stack}` + ); + } +} + +export async function isUserRegistered( + passportData: PassportData, + secret: string, + getCommitmentTree: (docCategory: DocumentCategory) => string +) { + if (!passportData) { + return false; + } + const attestationId = + passportData.documentCategory === 'passport' ? PASSPORT_ATTESTATION_ID : ID_CARD_ATTESTATION_ID; + const commitment = generateCommitment(secret, attestationId, passportData); + const document: DocumentCategory = passportData.documentCategory; + const serializedTree = getCommitmentTree(document); + const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serializedTree); + const index = tree.indexOf(BigInt(commitment)); + return index !== -1; +} + +export async function isUserRegisteredWithAlternativeCSCA( + passportData: PassportData, + secret: string, + { + getCommitmentTree, + getAltCSCA, + }: { + getCommitmentTree: (docCategory: DocumentCategory) => string; + getAltCSCA: (docCategory: DocumentCategory) => AlternativeCSCA; + } +): Promise<{ isRegistered: boolean; csca: string | null }> { + if (!passportData) { + console.error('Passport data is null'); + return { isRegistered: false, csca: null }; + } + const document: DocumentCategory = passportData.documentCategory; + const alternativeCSCA = getAltCSCA(document); + const { commitment_list, csca_list } = generateCommitmentInApp( + secret, + document === 'passport' ? PASSPORT_ATTESTATION_ID : ID_CARD_ATTESTATION_ID, + passportData, + alternativeCSCA + ); + + if (commitment_list.length === 0) { + console.error('No valid CSCA certificates could be parsed from alternativeCSCA'); + return { isRegistered: false, csca: null }; + } + + const serializedTree = getCommitmentTree(document); + const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serializedTree); + for (let i = 0; i < commitment_list.length; i++) { + const commitment = commitment_list[i]; + const index = tree.indexOf(BigInt(commitment)); + if (index !== -1) { + return { isRegistered: true, csca: csca_list[i] }; + } + } + console.warn('None of the following CSCA correspond to the commitment:', csca_list); + return { isRegistered: false, csca: null }; +} + +function formatCSCAPem(cscaPem: string): string { + let cleanedPem = cscaPem.trim(); + + if (!cleanedPem.includes('-----BEGIN CERTIFICATE-----')) { + cleanedPem = cleanedPem.replace(/[^A-Za-z0-9+/=]/g, ''); + try { + Buffer.from(cleanedPem, 'base64'); + } catch (error) { + throw new Error(`Invalid base64 certificate data: ${error}`); + } + cleanedPem = `-----BEGIN CERTIFICATE-----\n${cleanedPem}\n-----END CERTIFICATE-----`; + } + return cleanedPem; +} diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index 9f73ff6bd..2185bca58 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -1,15 +1,20 @@ import type { CertificateData } from './certificate_parsing/dataStructure.js'; import type { PassportMetadata } from './passports/passport_parsing/parsePassportData.js'; -export type DocumentCategory = 'passport' | 'id_card'; - -export type DocumentType = 'passport' | 'id_card' | 'mock_passport' | 'mock_id_card'; +export type DeployedCircuits = { + REGISTER: string[]; + REGISTER_ID: string[]; + DSC: string[]; + DSC_ID: string[]; +}; export interface DocumentCatalog { documents: DocumentMetadata[]; selectedDocumentId?: string; // This is now a contentHash } +export type DocumentCategory = 'passport' | 'id_card'; + export interface DocumentMetadata { id: string; // contentHash as ID for deduplication documentType: string; // passport, mock_passport, id_card, etc. @@ -19,6 +24,8 @@ export interface DocumentMetadata { isRegistered?: boolean; // whether the document is registered onChain } +export type DocumentType = 'passport' | 'id_card' | 'mock_passport' | 'mock_id_card'; + export type OfacTree = { passportNoAndNationality: any; nameAndDob: any; @@ -100,6 +107,13 @@ export type SignatureAlgorithm = | 'ecdsa_sha384_brainpoolP512r1_512' | 'ecdsa_sha512_brainpoolP512r1_512'; +// keys should match DocumentCategory +export enum AttestationIdHex { + invalid = '0x0000000000000000000000000000000000000000000000000000000000000000', + passport = '0x0000000000000000000000000000000000000000000000000000000000000001', + id_card = '0x0000000000000000000000000000000000000000000000000000000000000002', +} + export function castCSCAProof(proof: any): Proof { return { proof: { diff --git a/common/tests/scope.test.ts b/common/tests/scope.test.ts index 01ba215a0..ac907753a 100644 --- a/common/tests/scope.test.ts +++ b/common/tests/scope.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { bigIntToString, diff --git a/common/tsup.config.ts b/common/tsup.config.ts index 16a11bcfc..912d6659e 100644 --- a/common/tsup.config.ts +++ b/common/tsup.config.ts @@ -32,6 +32,7 @@ const entry = { 'src/utils/passports/index': 'src/utils/passports/index.ts', 'src/utils/passports/format': 'src/utils/passports/format.ts', 'src/utils/passports/mock': 'src/utils/passports/mock.ts', + 'src/utils/passports/validate': 'src/utils/passports/validate.ts', 'src/utils/passports/dg1': 'src/utils/passports/dg1.ts', 'src/utils/passports/genMockPassportData': 'src/utils/passports/genMockPassportData.ts', 'src/utils/passports/genMockIdDoc': 'src/utils/passports/genMockIdDoc.ts', diff --git a/common/vitest.config.ts b/common/vitest.config.ts index ba55739e1..ca3d2f045 100644 --- a/common/vitest.config.ts +++ b/common/vitest.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ test: { globals: true, environment: 'node', - include: ['tests/**/*.test.ts'], + include: ['**/*.test.ts'], setupFiles: ['./tests/setup.ts'], }, });