Skip to content

Commit 4dc34f0

Browse files
committed
ed448-goldilocks: account for oddness in Scalar divisions
1 parent f7878cc commit 4dc34f0

File tree

2 files changed

+20
-31
lines changed

2 files changed

+20
-31
lines changed

ed448-goldilocks/src/edwards/extended.rs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -338,34 +338,7 @@ impl EdwardsPoint {
338338
scalar_div_four.div_by_four();
339339

340340
// Use isogeny and dual isogeny to compute phi^-1((s/4) * phi(P))
341-
let partial_result = variable_base(&self.to_twisted(), &scalar_div_four).to_untwisted();
342-
// Add partial result to (scalar mod 4) * P
343-
partial_result.add(&self.scalar_mod_four(scalar))
344-
}
345-
346-
/// Returns (scalar mod 4) * P in constant time
347-
pub(crate) fn scalar_mod_four(&self, scalar: &EdwardsScalar) -> Self {
348-
// Compute compute (scalar mod 4)
349-
let s_mod_four = scalar[0] & 3;
350-
351-
// Compute all possible values of (scalar mod 4) * P
352-
let zero_p = EdwardsPoint::IDENTITY;
353-
let one_p = self;
354-
let two_p = one_p.double();
355-
let three_p = two_p.add(self);
356-
357-
// Under the reasonable assumption that `==` is constant time
358-
// Then the whole function is constant time.
359-
// This should be cheaper than calling double_and_add or a scalar mul operation
360-
// as the number of possibilities are so small.
361-
// XXX: This claim has not been tested (although it sounds intuitive to me)
362-
let mut result = EdwardsPoint::IDENTITY;
363-
result.conditional_assign(&zero_p, Choice::from((s_mod_four == 0) as u8));
364-
result.conditional_assign(one_p, Choice::from((s_mod_four == 1) as u8));
365-
result.conditional_assign(&two_p, Choice::from((s_mod_four == 2) as u8));
366-
result.conditional_assign(&three_p, Choice::from((s_mod_four == 3) as u8));
367-
368-
result
341+
variable_base(&self.to_twisted(), &scalar_div_four).to_untwisted()
369342
}
370343

371344
/// Add two points

ed448-goldilocks/src/field/scalar.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use elliptic_curve::{
1313
Array, ArraySize,
1414
typenum::{Prod, Unsigned},
1515
},
16-
bigint::{Limb, NonZero, U448, U896, Word, Zero},
16+
bigint::{Integer, Limb, NonZero, U448, U896, Word, Zero},
1717
consts::U2,
1818
ff::{Field, helpers},
1919
ops::{Invert, Reduce, ReduceNonZero},
@@ -662,6 +662,18 @@ impl<C: CurveWithScalar> Scalar<C> {
662662
/// This is used in the 2-isogeny when mapping points from Ed448-Goldilocks
663663
/// to Twisted-Goldilocks
664664
pub(crate) fn div_by_four(&mut self) {
665+
let s_mod_4 = self[0] & 3;
666+
667+
let s_plus_l = self.scalar + ORDER;
668+
let s_plus_2l = s_plus_l + ORDER;
669+
let s_plus_3l = s_plus_2l + ORDER;
670+
671+
self.scalar.conditional_assign(&s_plus_l, s_mod_4.ct_eq(&1));
672+
self.scalar
673+
.conditional_assign(&s_plus_2l, s_mod_4.ct_eq(&2));
674+
self.scalar
675+
.conditional_assign(&s_plus_3l, s_mod_4.ct_eq(&3));
676+
665677
self.scalar >>= 2;
666678
}
667679

@@ -778,8 +790,12 @@ impl<C: CurveWithScalar> Scalar<C> {
778790
}
779791

780792
/// Halves a Scalar modulo the prime
781-
pub const fn halve(&self) -> Self {
782-
Self::new(self.scalar.shr_vartime(1))
793+
pub fn halve(&self) -> Self {
794+
let is_odd = self.scalar.is_odd();
795+
let if_odd = self.scalar + *ORDER;
796+
let scalar = U448::conditional_select(&self.scalar, &if_odd, is_odd);
797+
798+
Self::new(scalar >> 1)
783799
}
784800

785801
/// Attempt to construct a `Scalar` from a canonical byte representation.

0 commit comments

Comments
 (0)