Skip to content

Commit d68fa29

Browse files
authored
Improved recovery-function of ecdsa. (#8690)
1 parent 37eb040 commit d68fa29

File tree

5 files changed

+8660
-9161
lines changed

5 files changed

+8660
-9161
lines changed

corelib/src/ec.cairo

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,7 @@ pub impl EcStateImpl of EcStateTrait {
184184
#[inline]
185185
fn sub(ref self: EcState, p: NonZeroEcPoint) {
186186
// TODO(orizi): Have a `ec_neg` for NonZeroEcPoint as well, or a `ec_state_sub`.
187-
let p: EcPoint = p.into();
188-
let p_neg = ec_neg(p);
189-
let p_neg_nz = p_neg.try_into().unwrap();
190-
ec_state_add(ref self, p_neg_nz);
187+
ec_state_add(ref self, -p);
191188
}
192189

193190
/// Adds the product `p * scalar` to the state.

corelib/src/ecdsa.cairo

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! * x = 0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca
1414
//! * y = 0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f
1515

16-
use crate::ec::{self, EcPoint, EcPointTrait, EcStateTrait};
16+
use crate::ec::{self, EcPointTrait, EcStateTrait};
1717
use crate::math;
1818
#[allow(unused_imports)]
1919
use crate::option::OptionTrait;
@@ -160,15 +160,8 @@ pub fn check_ecdsa_signature(
160160
pub fn recover_public_key(
161161
message_hash: felt252, signature_r: felt252, signature_s: felt252, y_parity: bool,
162162
) -> Option<felt252> {
163-
let mut signature_r_point = EcPointTrait::new_from_x(signature_r)?;
164-
let y: u256 = signature_r_point.try_into()?.y().into();
165-
// If the actual parity of the actual y is different than requested, flip the parity.
166-
if (y.low & 1 == 1) != y_parity {
167-
signature_r_point = -signature_r_point;
168-
}
169-
170-
// Retrieve the generator point.
171-
let gen_point = EcPointTrait::new(ec::stark_curve::GEN_X, ec::stark_curve::GEN_Y)?;
163+
let r_point = EcPointTrait::new_nz_from_x(signature_r)?;
164+
let gen_point = EcPointTrait::new_nz(ec::stark_curve::GEN_X, ec::stark_curve::GEN_Y)?;
172165

173166
// a Valid signature should satisfy:
174167
// zG + rQ = sR.
@@ -184,13 +177,23 @@ pub fn recover_public_key(
184177
// Q.x = ((s/r)R - (z/r)G).x.
185178
let r_nz: u256 = signature_r.into();
186179
let r_nz = r_nz.try_into()?;
187-
const ORD_U256: u256 = ec::stark_curve::ORDER.into();
180+
use ec::stark_curve::ORDER as ORD;
181+
const ORD_U256: u256 = ORD.into();
188182
const ORD_NZ: NonZero<u256> = ORD_U256.try_into().unwrap();
189183
let r_inv = math::u256_inv_mod(r_nz, ORD_NZ)?.into();
190184
let s_div_r: felt252 = math::u256_mul_mod_n(signature_s.into(), r_inv, ORD_NZ).try_into()?;
191185
let z_div_r: felt252 = math::u256_mul_mod_n(message_hash.into(), r_inv, ORD_NZ).try_into()?;
192-
let s_div_rR: EcPoint = signature_r_point.mul(s_div_r);
193-
let z_div_rG: EcPoint = gen_point.mul(z_div_r);
194-
195-
Some((s_div_rR - z_div_rG).try_into()?.x())
186+
let mut state = EcStateTrait::init();
187+
let ord = ORD;
188+
state.add_mul(ord - z_div_r, gen_point);
189+
// Checking if the actual parity of the point's y is different than the requested, and if so,
190+
// flipping the multiplier instead of negating the point to match the requested parity.
191+
let y: u256 = r_point.y().into();
192+
let r_multiplier = if (y.low & 1 != 0) ^ y_parity {
193+
ord - s_div_r
194+
} else {
195+
s_div_r
196+
};
197+
state.add_mul(r_multiplier, r_point);
198+
Some(state.finalize_nz()?.x())
196199
}

0 commit comments

Comments
 (0)