From ae8f2c8e6374b4ced1e564be5edf82dcfe7cf898 Mon Sep 17 00:00:00 2001 From: vishal Date: Mon, 10 Nov 2025 19:17:04 +0530 Subject: [PATCH] feat: constrain s to be 251 bit --- .../circuits/register/register_kyc.circom | 5 ++- .../circuits/utils/kyc/verifySignature.circom | 34 +++++++++++-------- circuits/tests/register/register_kyc.test.ts | 2 +- common/src/utils/kyc/generateInputs.ts | 4 +-- common/src/utils/kyc/types.ts | 2 +- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/circuits/circuits/register/register_kyc.circom b/circuits/circuits/register/register_kyc.circom index 381d16e29..75d786463 100644 --- a/circuits/circuits/register/register_kyc.circom +++ b/circuits/circuits/register/register_kyc.circom @@ -22,7 +22,7 @@ template REGISTER_KYC() { signal input Ty; signal input pubKeyX; signal input pubKeyY; - signal input r_inv[4]; + signal input neg_r_inv[4]; signal input secret; signal input attestation_id; @@ -33,7 +33,6 @@ template REGISTER_KYC() { } //msg_hash bit decomposition - //TODO: should we add msg_hash_bits [254] & [255] == 0? component bit_decompose = Num2Bits(256); bit_decompose.in <== msg_hasher.out; signal msg_hash_bits[256] <== bit_decompose.out; @@ -54,7 +53,7 @@ template REGISTER_KYC() { component verifyIdCommSig = VERIFY_KYC_SIGNATURE(); verifyIdCommSig.s <== s; - verifyIdCommSig.r_inv <== r_inv; + verifyIdCommSig.neg_r_inv <== neg_r_inv; verifyIdCommSig.msg_hash_limbs <== msg_hash_limbs; verifyIdCommSig.Tx <== Tx; verifyIdCommSig.Ty <== Ty; diff --git a/circuits/circuits/utils/kyc/verifySignature.circom b/circuits/circuits/utils/kyc/verifySignature.circom index 4cae87d05..b8b12b388 100644 --- a/circuits/circuits/utils/kyc/verifySignature.circom +++ b/circuits/circuits/utils/kyc/verifySignature.circom @@ -12,7 +12,7 @@ include "../crypto/bigInt/bigInt.circom"; template VERIFY_KYC_SIGNATURE(){ signal input s; - signal input r_inv[4]; + signal input neg_r_inv[4]; signal input msg_hash_limbs[4]; signal input Tx; signal input Ty; @@ -20,7 +20,7 @@ template VERIFY_KYC_SIGNATURE(){ signal input pubKeyY; - var SUBGROUP_ORDER = 2736030358979909402780800718157159386076813972158567259200215660948447373041; + var SUBGROUP_ORDER = 2736030358979909402780800718157159386076813972158567259200215660948447373041; //(251 bits) var BASE8[2] = [ 5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203 @@ -29,12 +29,18 @@ template VERIFY_KYC_SIGNATURE(){ component computes2bits = Num2Bits(254); computes2bits.in <== s; + // asserts s is a 251 bit number + for(var i = 0; i < 3; i++){ + computes2bits.out[251 + i] === 0; + } + + // Check s should be less than SUBGROUPT_ORDER - 1 component compConst = CompConstant(SUBGROUP_ORDER - 1); compConst.in <== computes2bits.out; compConst.out === 0; - // Check if s is not 0 + // Check if s is 0 signal is_s_zero <== IsZero()(s); is_s_zero === 0; @@ -48,11 +54,11 @@ template VERIFY_KYC_SIGNATURE(){ //Check is - r_inv < scalar_mod component scalar_range_check = BigLessThan(64,4); - scalar_range_check.a <== r_inv; + scalar_range_check.a <== neg_r_inv; scalar_range_check.b <== scalar_mod; scalar_range_check.out === 1 ; - //msg_hash % SUBORDER + //msg_hash % SUBORDER component msgReduced = BigMultModP(64, 4, 4, 4); for(var i = 0; i < 4; i++){ msgReduced.in1[i]<== msg_hash_limbs[i]; @@ -65,29 +71,29 @@ template VERIFY_KYC_SIGNATURE(){ msgReduced.modulus[i]<== scalar_mod[i]; } - // calculates (-r_inv * msg_hash) % SUBGROUP_ORDER - component r_inv_msg_hash = BabyScalarMul(); + // calculates (- r_inv * msg_hash) % SUBGROUP_ORDER + component neg_r_inv_msg_hash = BabyScalarMul(); for(var i = 0 ;i < 4 ;i++) { - r_inv_msg_hash.in1[i] <== r_inv[i]; - r_inv_msg_hash.in2[i] <== msgReduced.mod[i]; + neg_r_inv_msg_hash.in1[i] <== neg_r_inv[i]; + neg_r_inv_msg_hash.in2[i] <== msgReduced.mod[i]; } - signal r_inv_msg_hash_bits[256]; + signal neg_r_inv_msg_hash_bits[256]; component num2bits[4]; - // convert r_inv_msg_hash limbs to bits + // convert neg_r_inv_msg_hash limbs to bits for (var i = 0; i < 4; i++){ num2bits[i]= Num2Bits(64); - num2bits[i].in <==r_inv_msg_hash.out[i]; + num2bits[i].in <== neg_r_inv_msg_hash.out[i]; for(var j = 0; j < 64; j++){ - r_inv_msg_hash_bits[i * 64 +j] <== num2bits[i].out[j]; + neg_r_inv_msg_hash_bits[i * 64 +j] <== num2bits[i].out[j]; } } component mulFix = EscalarMulFix(254, BASE8); for (var i = 0; i < 254; i++) { - mulFix.e[i] <== r_inv_msg_hash_bits[i]; + mulFix.e[i] <== neg_r_inv_msg_hash_bits[i]; } component ecdsa = BabyJubJubECDSA(); diff --git a/circuits/tests/register/register_kyc.test.ts b/circuits/tests/register/register_kyc.test.ts index 0bf53786a..35ad0f301 100644 --- a/circuits/tests/register/register_kyc.test.ts +++ b/circuits/tests/register/register_kyc.test.ts @@ -116,7 +116,7 @@ describe('REGISTER KYC Circuit Tests', () => { it('should fail if r_inv is greater than scalar field', async function () { this.timeout(0); input = generateMockKycRegisterInput(null, true, undefined); - input.r_inv = ["7454187305358665460", "12339561404529962506", "3965992003123030795", "435874783350371333"]; + input.neg_r_inv = ["7454187305358665460", "12339561404529962506", "3965992003123030795", "435874783350371333"]; try { const w = await circuit.calculateWitness(input); diff --git a/common/src/utils/kyc/generateInputs.ts b/common/src/utils/kyc/generateInputs.ts index a272f47f8..966c09241 100644 --- a/common/src/utils/kyc/generateInputs.ts +++ b/common/src/utils/kyc/generateInputs.ts @@ -92,7 +92,7 @@ export const generateMockKycRegisterInput = (secretKey?: bigint, ofac?: boolean, console.assert(inCurve(U), 'Point U not on curve'); const rInv = modInv(sig.R[0], subOrder); - const rInvLimbs = bigintTo64bitLimbs(modulus(-rInv, subOrder)); + const neg_rInvLimbs = bigintTo64bitLimbs(modulus(-rInv, subOrder)); const kycRegisterInput: KycRegisterInput = { data_padded: msgPadded.map((x) => x.toString()), @@ -101,7 +101,7 @@ export const generateMockKycRegisterInput = (secretKey?: bigint, ofac?: boolean, Ty: T[1].toString(), pubKeyX: pk[0].toString(), pubKeyY: pk[1].toString(), - r_inv: rInvLimbs.map((x) => x.toString()), + neg_r_inv: neg_rInvLimbs.map((x) => x.toString()), secret: secret || "1234", attestation_id: attestationId || '4', }; diff --git a/common/src/utils/kyc/types.ts b/common/src/utils/kyc/types.ts index 11ed86677..7e9e0005d 100644 --- a/common/src/utils/kyc/types.ts +++ b/common/src/utils/kyc/types.ts @@ -46,7 +46,7 @@ export type KycRegisterInput = { Ty: string, pubKeyX: string, pubKeyY: string, - r_inv: string[], + neg_r_inv: string[], secret: string, attestation_id: string, }