From 6c82228dd1c702b71991c9159de84319d1819572 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Tue, 31 Mar 2026 17:22:06 +0400 Subject: [PATCH] Fix EC-SRP5 server: use stored gamma parity, not hardcoded true The gamma point's y-parity depends on the random salt. Using hardcoded parity=true caused ~50% of auth attempts to fail (whenever the actual parity was 0). Now stored from key derivation and used correctly. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/ecsrp5.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ecsrp5.rs b/src/ecsrp5.rs index 8894cbb..d8d0e13 100644 --- a/src/ecsrp5.rs +++ b/src/ecsrp5.rs @@ -469,6 +469,7 @@ pub async fn client_authenticate( pub struct EcSrp5Credentials { salt: [u8; 16], x_gamma: [u8; 32], + gamma_parity: bool, } impl EcSrp5Credentials { @@ -477,10 +478,11 @@ impl EcSrp5Credentials { let salt: [u8; 16] = rand::random(); let w = WCurve::new(); let i = w.gen_password_validator_priv(username, password, &salt); - let (x_gamma, _parity) = w.gen_public_key(&i); + let (x_gamma, parity) = w.gen_public_key(&i); Self { salt, x_gamma, + gamma_parity: parity != 0, } } } @@ -555,7 +557,7 @@ pub async fn server_authenticate( // gamma = lift_x(x_gamma, parity=1) — the raw validator public key point // (NOT redp1 — that's used for blinding W_b, not for verification) let w_a = w.lift_x(&BigUint::from_bytes_be(&x_w_a), x_w_a_parity); - let gamma = w.lift_x(&BigUint::from_bytes_be(&creds.x_gamma), true); + let gamma = w.lift_x(&BigUint::from_bytes_be(&creds.x_gamma), creds.gamma_parity); let j_gamma = gamma.scalar_mul(&j_int); let sum = w_a.add(&j_gamma); let z_point = sum.scalar_mul(&s_b_int);