fix: use raw bytes for KYC register circuit inputs (#1888)

* fix: use raw bytes for KYC register circuit inputs instead of deserialize+reserialize

The deserialize→reserialize path strips the namespace prefix from
id_type, producing different bytes than what the TEE signed. This
causes EdDSA signature verification to fail in the circuit.

Use raw base64-decoded bytes directly, matching the TEE's signed data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use raw bytes for KYC register circuit inputs in common and new-common

The deserialize→reserialize path strips the namespace prefix from
id_type (\x05didit), producing different bytes than what the TEE
signed. This causes EdDSA signature verification to fail in the
register_kyc circuit.

Use raw base64-decoded bytes directly in both common/ and new-common/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nesopie
2026-03-30 21:43:41 +05:30
committed by GitHub
parent 1f5d39a3f1
commit fe4eb3786a
2 changed files with 11 additions and 10 deletions

View File

@@ -251,16 +251,16 @@ export const generateKycRegisterInput = async (
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).padEnd(KYC_MAX_LENGTH, '\0');
const msgPadded = Array.from(serializedData, (x) => x.charCodeAt(0));
// Use raw bytes directly — deserialize→reserialize strips the namespace prefix
// from id_type, producing different bytes than the TEE signed.
const raw = Buffer.from(applicantInfoBase64, 'base64');
const dataPadded = [...Array.from(raw, (b) => Number(b)), ...new Array(Math.max(0, KYC_MAX_LENGTH - raw.length)).fill(0)];
const kycRegisterInput: KycRegisterInput = {
data_padded: msgPadded,
data_padded: dataPadded,
s: signature.s,
R: signature.R,
pubKey: pubkey,

View File

@@ -1,6 +1,6 @@
import { Base8, inCurve, mulPointEscalar, subOrder } from '@zk-kit/baby-jubjub';
import { deserializeApplicantInfo, deserializeSignature } from '../../documents/kyc/api.js';
import { deserializeSignature } from '../../documents/kyc/api.js';
import { KYC_MAX_LENGTH } from '../../documents/kyc/constants.js';
import type { KycRegisterInput } from '../../documents/kyc/types.js';
import { serializeKycData } from '../../documents/kyc/types.js';
@@ -13,15 +13,16 @@ export function generateKycRegisterInputs(
pubkeyStr: [string, string],
secret: string,
): KycRegisterInput {
const applicantInfo = deserializeApplicantInfo(applicantInfoBase64);
const signature = deserializeSignature(signatureBase64);
const pubkey = [BigInt(pubkeyStr[0]), BigInt(pubkeyStr[1])] as [bigint, bigint];
const serializedData = serializeKycData(applicantInfo).padEnd(KYC_MAX_LENGTH, '\0');
const msgPadded = Array.from(serializedData, x => x.charCodeAt(0));
// Use raw bytes directly — deserialize→reserialize strips the namespace prefix
// from id_type, producing different bytes than the TEE signed.
const raw = Buffer.from(applicantInfoBase64, 'base64');
const dataPadded = [...Array.from(raw, b => Number(b)), ...new Array(Math.max(0, KYC_MAX_LENGTH - raw.length)).fill(0)];
return {
data_padded: msgPadded,
data_padded: dataPadded,
s: signature.s,
R: signature.R,
pubKey: pubkey,