diff --git a/circuits/tests/register/register_kyc.test.ts b/circuits/tests/register/register_kyc.test.ts index a9e68cddd..f863a29fd 100644 --- a/circuits/tests/register/register_kyc.test.ts +++ b/circuits/tests/register/register_kyc.test.ts @@ -3,7 +3,7 @@ import { wasm as wasmTester } from 'circom_tester'; import path from 'path'; import { packBytesAndPoseidon } from '@selfxyz/common/utils/hash'; import { poseidon2 } from 'poseidon-lite'; -import { generateMockKycRegisterInput } from '@selfxyz/common/utils/kyc/generateInputs.js'; +import { generateKycRegisterInput, generateMockKycRegisterInput } from '@selfxyz/common/utils/kyc/generateInputs.js'; import { KycRegisterInput } from '@selfxyz/common/utils/kyc/types'; import { KYC_ID_NUMBER_INDEX, KYC_ID_NUMBER_LENGTH, KYC_ID_TYPE_INDEX, KYC_ID_TYPE_LENGTH } from '@selfxyz/common/utils/kyc/constants'; diff --git a/common/index.ts b/common/index.ts index 86e9db1ee..bac966259 100644 --- a/common/index.ts +++ b/common/index.ts @@ -138,6 +138,7 @@ export { generateMockKycRegisterInput, NON_OFAC_DUMMY_INPUT, OFAC_DUMMY_INPUT, + generateKycRegisterInput, } from './src/utils/kyc/generateInputs.js'; export { diff --git a/common/src/utils/kyc/api.ts b/common/src/utils/kyc/api.ts new file mode 100644 index 000000000..6e778ea6a --- /dev/null +++ b/common/src/utils/kyc/api.ts @@ -0,0 +1,40 @@ +//Helper function to destructure the kyc data from the api response +import { Point } from "@zk-kit/baby-jubjub"; +import { KYC_ADDRESS_INDEX, KYC_ADDRESS_LENGTH, KYC_COUNTRY_INDEX, KYC_COUNTRY_LENGTH, KYC_DOB_INDEX, KYC_DOB_LENGTH, KYC_EXPIRY_DATE_INDEX, KYC_EXPIRY_DATE_LENGTH, KYC_FULL_NAME_INDEX, KYC_FULL_NAME_LENGTH, KYC_GENDER_INDEX, KYC_GENDER_LENGTH, KYC_ID_NUMBER_INDEX, KYC_ID_NUMBER_LENGTH, KYC_ID_TYPE_INDEX, KYC_ID_TYPE_LENGTH, KYC_ISSUANCE_DATE_INDEX, KYC_ISSUANCE_DATE_LENGTH, KYC_PHONE_NUMBER_INDEX, KYC_PHONE_NUMBER_LENGTH, KYC_PHOTO_HASH_INDEX, KYC_PHOTO_HASH_LENGTH } from "./constants.js"; +import { KycData } from "./types.js"; + +//accepts a base64 signature and returns a signature object +export function deserializeSignature(signature: string): { R: Point; s: bigint} { + const [Rx, Ry, s] = Buffer.from(signature, 'base64').toString('utf-8').split(',').map(BigInt); + return { R: [Rx, Ry] as Point, s }; +} + +//accepts a base64 applicant info and returns a kyc data object +export function deserializeApplicantInfo(applicantInfoBase64: string): Omit { + const applicantInfo = Buffer.from(applicantInfoBase64, 'base64').toString('utf-8'); + const country = applicantInfo.slice(KYC_COUNTRY_INDEX, KYC_COUNTRY_INDEX + KYC_COUNTRY_LENGTH).replace(/\x00/g, ''); + const idType = applicantInfo.slice(KYC_ID_TYPE_INDEX, KYC_ID_TYPE_INDEX + KYC_ID_TYPE_LENGTH).replace(/\x00/g, ''); + const idNumber = applicantInfo.slice(KYC_ID_NUMBER_INDEX, KYC_ID_NUMBER_INDEX + KYC_ID_NUMBER_LENGTH).replace(/\x00/g, ''); + const issuanceDate = applicantInfo.slice(KYC_ISSUANCE_DATE_INDEX, KYC_ISSUANCE_DATE_INDEX + KYC_ISSUANCE_DATE_LENGTH).replace(/\x00/g, ''); + const expiryDate = applicantInfo.slice(KYC_EXPIRY_DATE_INDEX, KYC_EXPIRY_DATE_INDEX + KYC_EXPIRY_DATE_LENGTH).replace(/\x00/g, ''); + const fullName = applicantInfo.slice(KYC_FULL_NAME_INDEX, KYC_FULL_NAME_INDEX + KYC_FULL_NAME_LENGTH).replace(/\x00/g, ''); + const dob = applicantInfo.slice(KYC_DOB_INDEX, KYC_DOB_INDEX + KYC_DOB_LENGTH).replace(/\x00/g, ''); + const photoHash = applicantInfo.slice(KYC_PHOTO_HASH_INDEX, KYC_PHOTO_HASH_INDEX + KYC_PHOTO_HASH_LENGTH).replace(/\x00/g, ''); + const phoneNumber = applicantInfo.slice(KYC_PHONE_NUMBER_INDEX, KYC_PHONE_NUMBER_INDEX + KYC_PHONE_NUMBER_LENGTH).replace(/\x00/g, ''); + const gender = applicantInfo.slice(KYC_GENDER_INDEX, KYC_GENDER_INDEX + KYC_GENDER_LENGTH).replace(/\x00/g, ''); + const address = applicantInfo.slice(KYC_ADDRESS_INDEX, KYC_ADDRESS_INDEX + KYC_ADDRESS_LENGTH).replace(/\x00/g, ''); + + return { + country, + idType, + idNumber, + issuanceDate, + expiryDate, + fullName, + dob, + photoHash, + phoneNumber, + gender, + address + }; +} diff --git a/common/src/utils/kyc/generateInputs.ts b/common/src/utils/kyc/generateInputs.ts index 7fbc9a40a..45ccfc30e 100644 --- a/common/src/utils/kyc/generateInputs.ts +++ b/common/src/utils/kyc/generateInputs.ts @@ -14,6 +14,7 @@ import { signEdDSA } from './ecdsa/ecdsa.js'; import { LeanIMT } from '@openpassport/zk-kit-lean-imt'; import { packBytesAndPoseidon } from '../hash.js'; import { COMMITMENT_TREE_DEPTH } from '../../constants/constants.js'; +import { deserializeApplicantInfo, deserializeSignature } from './api.js'; export const OFAC_DUMMY_INPUT: KycData = { country: 'KEN', @@ -86,6 +87,26 @@ export const generateMockKycRegisterInput = async ( return kycRegisterInput; }; +export const generateKycRegisterInput = async (applicantInfoBase64: string, signatureBase64: string, pubkeyStr: [string, string], secret: string) => { + const applicantInfo = deserializeApplicantInfo(applicantInfoBase64); + const signature = deserializeSignature(signatureBase64); + const pubkey = [BigInt(pubkeyStr[0]), BigInt(pubkeyStr[1])] as [bigint, bigint]; + + const serializedData = serializeKycData(applicantInfo); + + const msgPadded = Array.from(serializedData, (x) => x.charCodeAt(0)); + + const kycRegisterInput: KycRegisterInput = { + data_padded: msgPadded.map((x) => Number(x)), + s: signature.s, + R: signature.R, + pubKey: pubkey, + secret, + }; + + return kycRegisterInput; +} + export const generateCircuitInputsOfac = (data: KycData, smt: SMT, proofLevel: number) => { const name = data.fullName; const dob = data.dob; diff --git a/common/src/utils/kyc/types.ts b/common/src/utils/kyc/types.ts index d4bcce6ea..297c4103c 100644 --- a/common/src/utils/kyc/types.ts +++ b/common/src/utils/kyc/types.ts @@ -19,11 +19,11 @@ export type KycData = { selector_older_than: string; }; -export const serializeKycData = (kycData: KycData) => { +export const serializeKycData = (kycData: Omit) => { //ensure max length of each field let serializedData = ''; - serializedData += kycData.country.toUpperCase().padEnd(constants.KYC_COUNTRY_LENGTH, '\0'); - serializedData += kycData.idType.toUpperCase().padEnd(constants.KYC_ID_TYPE_LENGTH, '\0'); + serializedData += kycData.country.padEnd(constants.KYC_COUNTRY_LENGTH, '\0'); + serializedData += kycData.idType.padEnd(constants.KYC_ID_TYPE_LENGTH, '\0'); serializedData += kycData.idNumber.padEnd(constants.KYC_ID_NUMBER_LENGTH, '\0'); serializedData += kycData.issuanceDate.padEnd(constants.KYC_ISSUANCE_DATE_LENGTH, '\0'); serializedData += kycData.expiryDate.padEnd(constants.KYC_EXPIRY_DATE_LENGTH, '\0');