diff --git a/src/montgomery.rs b/src/montgomery.rs index 232fc3254..dc53a9d3f 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -335,17 +335,23 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { W: FieldElement::one(), }; - let bits: [i8; 256] = scalar.bits(); - - for i in (0..255).rev() { - let choice: u8 = (bits[i + 1] ^ bits[i]) as u8; + // Go through the bits from most to least significant, using a sliding window of 2 + let mut bits = scalar.bits_le().rev(); + let mut prev_bit = bits.next().unwrap(); + for cur_bit in bits { + let choice: u8 = (prev_bit ^ cur_bit) as u8; debug_assert!(choice == 0 || choice == 1); ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into()); differential_add_and_double(&mut x0, &mut x1, &affine_u); + + prev_bit = cur_bit; } - ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8)); + // The final value of prev_bit above is scalar.bits()[0], i.e., the LSB of scalar + ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(prev_bit as u8)); + // Don't leave the bit in the stack + prev_bit.zeroize(); x0.as_affine() } diff --git a/src/scalar.rs b/src/scalar.rs index db4bf433f..3cdf0e300 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -847,16 +847,14 @@ impl Scalar { ret } - /// Get the bits of the scalar. - pub(crate) fn bits(&self) -> [i8; 256] { - let mut bits = [0i8; 256]; - #[allow(clippy::needless_range_loop)] - for i in 0..256 { - // As i runs from 0..256, the bottom 3 bits index the bit, - // while the upper bits index the byte. - bits[i] = ((self.bytes[i >> 3] >> (i & 7)) & 1u8) as i8; - } - bits + /// Get the bits of the scalar, in little-endian order + pub(crate) fn bits_le(&self) -> impl DoubleEndedIterator + '_ { + (0..256).map(|i| { + // As i runs from 0..256, the bottom 3 bits index the bit, while the upper bits index + // the byte. Since self.bytes is little-endian at the byte level, this iterator is + // little-endian on the bit level + ((self.bytes[i >> 3] >> (i & 7)) & 1u8) == 1 + }) } /// Compute a width-\\(w\\) "Non-Adjacent Form" of this scalar.