diff --git a/src/backend/serial/scalar_mul/variable_base.rs b/src/backend/serial/scalar_mul/variable_base.rs index 588a84e..2471375 100644 --- a/src/backend/serial/scalar_mul/variable_base.rs +++ b/src/backend/serial/scalar_mul/variable_base.rs @@ -3,7 +3,7 @@ use traits::Identity; use scalar::Scalar; use edwards::EdwardsPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; +use backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint}; use window::LookupTable; /// Perform constant-time, variable-base scalar multiplication. @@ -23,10 +23,24 @@ pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { // s*P = P*s_0 + 16*(P*s_1 + 16*(P*s_2 + 16*( ... + P*s_63)...)) // // We sum right-to-left. - let mut Q = EdwardsPoint::identity(); - for i in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - Q = (&Q + &lookup_table.select(scalar_digits[i])).to_extended(); + + // Unwrap first loop iteration to save computing 16*identity + let mut tmp2 = ProjectivePoint::identity(); + let mut tmp3 = EdwardsPoint::identity(); + let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]); + // Now tmp1 = s_63*P in P1xP1 coords + for i in (0..63).rev() { + tmp2 = tmp1.to_projective(); // tmp2 = (prev) in P2 coords + tmp1 = tmp2.double(); // tmp1 = 2*(prev) in P1xP1 coords + tmp2 = tmp1.to_projective(); // tmp2 = 2*(prev) in P2 coords + tmp1 = tmp2.double(); // tmp1 = 4*(prev) in P1xP1 coords + tmp2 = tmp1.to_projective(); // tmp2 = 4*(prev) in P2 coords + tmp1 = tmp2.double(); // tmp1 = 8*(prev) in P1xP1 coords + tmp2 = tmp1.to_projective(); // tmp2 = 8*(prev) in P2 coords + tmp1 = tmp2.double(); // tmp1 = 16*(prev) in P1xP1 coords + tmp3 = tmp1.to_extended(); // tmp3 = 16*(prev) in P3 coords + tmp1 = &tmp3 + &lookup_table.select(scalar_digits[i]); + // Now tmp1 = s_i*P + 16*(prev) in P1xP1 coords } - Q + tmp1.to_extended() }