Skip to content

Commit b0bb83e

Browse files
committed
ed448-goldilocks: account for oddness in Scalar divisions
1 parent cfe844b commit b0bb83e

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
@@ -557,34 +557,7 @@ impl EdwardsPoint {
557557
scalar_div_four.div_by_four();
558558

559559
// Use isogeny and dual isogeny to compute phi^-1((s/4) * phi(P))
560-
let partial_result = variable_base(&self.to_twisted(), &scalar_div_four).to_untwisted();
561-
// Add partial result to (scalar mod 4) * P
562-
partial_result.add(&self.scalar_mod_four(scalar))
563-
}
564-
565-
/// Returns (scalar mod 4) * P in constant time
566-
pub(crate) fn scalar_mod_four(&self, scalar: &EdwardsScalar) -> Self {
567-
// Compute compute (scalar mod 4)
568-
let s_mod_four = scalar[0] & 3;
569-
570-
// Compute all possible values of (scalar mod 4) * P
571-
let zero_p = EdwardsPoint::IDENTITY;
572-
let one_p = self;
573-
let two_p = one_p.double();
574-
let three_p = two_p.add(self);
575-
576-
// Under the reasonable assumption that `==` is constant time
577-
// Then the whole function is constant time.
578-
// This should be cheaper than calling double_and_add or a scalar mul operation
579-
// as the number of possibilities are so small.
580-
// XXX: This claim has not been tested (although it sounds intuitive to me)
581-
let mut result = EdwardsPoint::IDENTITY;
582-
result.conditional_assign(&zero_p, Choice::from((s_mod_four == 0) as u8));
583-
result.conditional_assign(one_p, Choice::from((s_mod_four == 1) as u8));
584-
result.conditional_assign(&two_p, Choice::from((s_mod_four == 2) as u8));
585-
result.conditional_assign(&three_p, Choice::from((s_mod_four == 3) as u8));
586-
587-
result
560+
variable_base(&self.to_twisted(), &scalar_div_four).to_untwisted()
588561
}
589562

590563
/// Standard compression; store Y and sign of X

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)