From c01bd780dca04602f2d3fc18d8cb1aacb1daf1f6 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 31 Dec 2019 00:12:20 +0000 Subject: [PATCH] Implement radix-32 precomputed scalar multiplication tables. --- src/edwards.rs | 14 +++++++++++++- src/scalar.rs | 8 ++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/edwards.rs b/src/edwards.rs index b64e4a3..3f21e96 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -118,6 +118,7 @@ use backend::serial::curve_models::ProjectiveNielsPoint; use backend::serial::curve_models::ProjectivePoint; use window::LookupTableRadix16; +use window::LookupTableRadix32; use window::LookupTableRadix64; use window::LookupTableRadix128; use window::LookupTableRadix256; @@ -899,6 +900,7 @@ impl Debug for $name { // The number of additions required is ceil(256/w) where w is the radix representation. impl_basepoint_table! {Name = EdwardsBasepointTable, LookupTable = LookupTableRadix16, Point = EdwardsPoint, Radix = 4, Additions = 64} +impl_basepoint_table! {Name = EdwardsBasepointTableRadix32, LookupTable = LookupTableRadix32, Point = EdwardsPoint, Radix = 5, Additions = 52} impl_basepoint_table! {Name = EdwardsBasepointTableRadix64, LookupTable = LookupTableRadix64, Point = EdwardsPoint, Radix = 6, Additions = 43} impl_basepoint_table! {Name = EdwardsBasepointTableRadix128, LookupTable = LookupTableRadix128, Point = EdwardsPoint, Radix = 7, Additions = 37} impl_basepoint_table! {Name = EdwardsBasepointTableRadix256, LookupTable = LookupTableRadix256, Point = EdwardsPoint, Radix = 8, Additions = 33} @@ -927,11 +929,18 @@ macro_rules! impl_basepoint_table_conversions { } } +impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix32} impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix64} impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix128} impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix256} + +impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix64} +impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix128} +impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix256} + impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix128} impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix256} + impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix128, RHS = EdwardsBasepointTableRadix256} impl EdwardsPoint { @@ -1236,18 +1245,21 @@ mod test { let a = A_SCALAR; let table_radix16 = EdwardsBasepointTableRadix16::create(&P); + let table_radix32 = EdwardsBasepointTableRadix32::create(&P); let table_radix64 = EdwardsBasepointTableRadix64::create(&P); let table_radix128 = EdwardsBasepointTableRadix128::create(&P); let table_radix256 = EdwardsBasepointTableRadix256::create(&P); let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress(); let aP16 = (&table_radix16 * &a).compress(); + let aP32 = (&table_radix32 * &a).compress(); let aP64 = (&table_radix64 * &a).compress(); let aP128 = (&table_radix128 * &a).compress(); let aP256 = (&table_radix256 * &a).compress(); assert_eq!(aP, aP16); - assert_eq!(aP16, aP64); + assert_eq!(aP16, aP32); + assert_eq!(aP32, aP64); assert_eq!(aP64, aP128); assert_eq!(aP128, aP256); } diff --git a/src/scalar.rs b/src/scalar.rs index 3e70367..21b801c 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -994,6 +994,7 @@ impl Scalar { let digits_count = match w { 4 => (256 + w - 1)/w as usize, + 5 => (256 + w - 1)/w as usize, 6 => (256 + w - 1)/w as usize, 7 => (256 + w - 1)/w as usize, // See comment in to_radix_2w on handling the terminal carry. @@ -1005,14 +1006,13 @@ impl Scalar { digits_count } - /// Creates a representation of a Scalar in radix 64, 128 or 256 for use with the Pippenger algorithm. + /// Creates a representation of a Scalar in radix 32, 64, 128 or 256 for use with the Pippenger algorithm. /// For lower radix, use `to_radix_16`, which is used by the Straus multi-scalar multiplication. /// Higher radixes are not supported to save cache space. Radix 256 is near-optimal even for very /// large inputs. /// - /// Radix below 64 or above 256 is prohibited. + /// Radix below 32 or above 256 is prohibited. /// This method returns digits in a fixed-sized array, excess digits are zeroes. - /// The second returned value is the number of digits. /// /// ## Scalar representation /// @@ -1024,7 +1024,7 @@ impl Scalar { /// with \\(-2\^w/2 \leq a_i < 2\^w/2\\) for \\(0 \leq i < (n-1)\\) and \\(-2\^w/2 \leq a_{n-1} \leq 2\^w/2\\). /// pub(crate) fn to_radix_2w(&self, w: usize) -> [i8; 64] { - debug_assert!(w == 4 || w >= 6); + debug_assert!(w >= 4); debug_assert!(w <= 8); if w == 4 {