From 59453d755d26e4051edc19671d9c368b977aea3a Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 16:43:15 -0700 Subject: [PATCH 1/6] Implement Mul for scalar multiplication --- src/curve.rs | 24 ++++++++++++++---------- src/decaf.rs | 17 +++++++++++++---- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 26a9ede..cc30d7f 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -79,7 +79,9 @@ use core::fmt::Debug; use core::iter::Iterator; -use core::ops::{Add, Sub, Neg, Index}; +use core::ops::{Add, Sub, Neg}; +use core::ops::{Mul, MulAssign}; +use core::ops::Index; use constants; use field::FieldElement; @@ -789,18 +791,20 @@ impl<'a> Neg for &'a AffineNielsPoint { // Scalar multiplication // ------------------------------------------------------------------------ -/// Trait for scalar multiplication of an arbitrary point. -pub trait ScalarMult { - /// Compute `scalar * self`. - fn scalar_mult(&self, scalar: &S) -> Self; +impl<'b> MulAssign<&'b Scalar> for ExtendedPoint { + fn mul_assign(&mut self, scalar: &'b Scalar) { + let result = (self as &ExtendedPoint) * scalar; + *self = result; + } } -impl ScalarMult for ExtendedPoint { +impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint { + type Output = ExtendedPoint; /// Scalar multiplication: compute `scalar * self`. /// /// Uses a window of size 4. Note: for scalar multiplication of /// the basepoint, `basepoint_mult` is approximately 4x faster. - fn scalar_mult(&self, scalar: &Scalar) -> ExtendedPoint { + fn mul(self, scalar: &'b Scalar) -> ExtendedPoint { let A = self.to_projective_niels(); let mut As: [ProjectiveNielsPoint; 8] = [A; 8]; for i in 0..7 { @@ -1369,7 +1373,7 @@ mod test { /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] fn scalar_mult_vs_ed25519py() { - let aB = constants::ED25519_BASEPOINT.scalar_mult(&A_SCALAR); + let aB = &constants::ED25519_BASEPOINT * &A_SCALAR; assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } @@ -1454,7 +1458,7 @@ mod test { // N.B. each scalar_mult does 1407 field mults, 1024 field squarings, // so this does ~ 1M of each operation. for _ in 0..1_000 { - P = P.scalar_mult(&A_SCALAR); + P *= &A_SCALAR; } } @@ -1501,7 +1505,7 @@ mod bench { #[bench] fn scalar_mult(b: &mut Bencher) { let bp = constants::ED25519_BASEPOINT; - b.iter(|| bp.scalar_mult(&A_SCALAR)); + b.iter(|| &bp * &A_SCALAR); } #[bench] diff --git a/src/decaf.rs b/src/decaf.rs index bb73132..6e4d2c6 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -30,6 +30,7 @@ use subtle::CTAssignable; use subtle::CTNegatable; use core::ops::{Add, Sub, Neg}; +use core::ops::{Mul, MulAssign}; #[cfg(all(not(feature = "std"), feature = "basepoint_table_creation"))] use collections::boxed::Box; @@ -40,7 +41,6 @@ use curve; use curve::ExtendedPoint; use curve::EdwardsBasepointTable; use curve::BasepointMult; -use curve::ScalarMult; use curve::Identity; use scalar::Scalar; @@ -250,9 +250,18 @@ impl<'a> Neg for &'a DecafPoint { } } -impl ScalarMult for DecafPoint { - fn scalar_mult(&self, scalar: &Scalar) -> DecafPoint { - DecafPoint(self.0.scalar_mult(scalar)) +impl<'b> MulAssign<&'b Scalar> for DecafPoint { + fn mul_assign(&mut self, scalar: &'b Scalar) { + let result = (self as &DecafPoint) * scalar; + *self = result; + } +} + +impl<'a, 'b> Mul<&'b Scalar> for &'a DecafPoint { + type Output = DecafPoint; + /// Scalar multiplication: compute `scalar * self`. + fn mul(self, scalar: &'b Scalar) -> DecafPoint { + DecafPoint(&self.0 * scalar) } } From 0678e619cc3396d8d704d5cb7ec86deb0c9ff6d5 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 18:52:45 -0700 Subject: [PATCH 2/6] Implement Mul for basepoint tables --- src/constants.rs | 11 ++++++ src/curve.rs | 93 +++++++++++++++++++++--------------------------- src/decaf.rs | 67 +++++++++++----------------------- 3 files changed, 72 insertions(+), 99 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 50879da..2d3c790 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -24,6 +24,8 @@ use curve::ExtendedPoint; use curve::AffineNielsPoint; use curve::CompressedEdwardsY; use curve::EdwardsBasepointTable; +#[cfg(feature = "yolocrypto")] +use decaf::{DecafPoint, DecafBasepointTable}; use scalar::Scalar; #[cfg(feature="radix_51")] @@ -136,6 +138,10 @@ pub const BASE_CMPRSSD: CompressedEdwardsY = 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); +/// The Ed25519 basepoint, as a `DecafPoint`. +#[cfg(feature = "yolocrypto")] +pub const DECAF_ED25519_BASEPOINT: DecafPoint = DecafPoint(ED25519_BASEPOINT); + /// Basepoint has y = 4/5. #[cfg(not(feature="radix_51"))] pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{ @@ -384,6 +390,11 @@ pub const bi: [AffineNielsPoint; 8] = [ } ]; +#[cfg(feature = "yolocrypto")] +/// The Ed25519 basepoint +pub const DECAF_ED25519_BASEPOINT_TABLE: DecafBasepointTable + = DecafBasepointTable(ED25519_BASEPOINT_TABLE); + /// Table containing precomputed multiples of the basepoint `B = (x,4/5)`. /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, diff --git a/src/curve.rs b/src/curve.rs index cc30d7f..c56dd25 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -826,27 +826,8 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint { #[derive(Clone)] pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]); -impl EdwardsBasepointTable { - /// Create a table of precomputed multiples of `basepoint`. - #[cfg(feature="basepoint_table_creation")] - pub fn create(basepoint: &ExtendedPoint) -> Box { - // Create the table storage - // XXX can we be assured that this is not allocated on the stack? - // XXX can we skip the initialization without too much unsafety? - let mut table = box EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); - let mut P = basepoint.clone(); - for i in 0..32 { - // P = (16^2)^i * B - let mut jP = P.to_affine_niels(); - for j in 1..9 { - // table[i][j-1] is supposed to be j*(16^2)^i*B - table.0[i][j-1] = jP; - jP = (&P + &jP).to_extended().to_affine_niels(); - } - P = P.mult_by_pow_2(8); - } - return table - } +impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable { + type Output = ExtendedPoint; /// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by /// computing the multiple `aB` of the basepoint `B`. @@ -873,7 +854,7 @@ impl EdwardsBasepointTable { /// We then use the `select_precomputed_point` function, which /// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`, /// and returns `x * 16^2i * B` in constant time. - pub fn basepoint_mult(&self, scalar: &Scalar) -> ExtendedPoint { + fn mul(self, scalar: &'b Scalar) -> ExtendedPoint { let e = scalar.to_radix_16(); let mut h = ExtendedPoint::identity(); let mut t: CompletedPoint; @@ -894,21 +875,26 @@ impl EdwardsBasepointTable { } } -/// Trait for scalar multiplication of a distinguished basepoint. -pub trait BasepointMult { - /// Return the basepoint `B`. - fn basepoint() -> Self; - /// Compute `scalar * B`. - fn basepoint_mult(scalar: &S) -> Self; -} - -impl BasepointMult for ExtendedPoint { - fn basepoint() -> ExtendedPoint { - constants::ED25519_BASEPOINT - } - - fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint { - constants::ED25519_BASEPOINT_TABLE.basepoint_mult(scalar) +impl EdwardsBasepointTable { + /// Create a table of precomputed multiples of `basepoint`. + #[cfg(feature="basepoint_table_creation")] + pub fn create(basepoint: &ExtendedPoint) -> Box { + // Create the table storage + // XXX can we be assured that this is not allocated on the stack? + // XXX can we skip the initialization without too much unsafety? + let mut table = box EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); + let mut P = basepoint.clone(); + for i in 0..32 { + // P = (16^2)^i * B + let mut jP = P.to_affine_niels(); + for j in 1..9 { + // table[i][j-1] is supposed to be j*(16^2)^i*B + table.0[i][j-1] = jP; + jP = (&P + &jP).to_extended().to_affine_niels(); + } + P = P.mult_by_pow_2(8); + } + return table } } @@ -1286,7 +1272,7 @@ mod test { /// Test that computing 1*basepoint gives the correct basepoint. #[test] fn basepoint_mult_one_vs_basepoint() { - let bp = ExtendedPoint::basepoint_mult(&Scalar::one()); + let bp = &constants::ED25519_BASEPOINT_TABLE * &Scalar::one(); let compressed = bp.compress_edwards(); assert_eq!(compressed, constants::BASE_CMPRSSD); } @@ -1338,7 +1324,7 @@ mod test { #[test] fn to_affine_niels_clears_denominators() { // construct a point as aB so it has denominators (ie. Z != 1) - let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); + let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; let aB_affine_niels = aB.to_affine_niels(); let also_aB = (&ExtendedPoint::identity() + &aB_affine_niels).to_extended(); assert_eq!( aB.compress_edwards(), @@ -1348,14 +1334,15 @@ mod test { /// Test basepoint_mult versus a known scalar multiple from ed25519.py #[test] fn basepoint_mult_vs_ed25519py() { - let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); + let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } /// Test that multiplication by the basepoint order kills the basepoint #[test] fn basepoint_mult_by_basepoint_order() { - let should_be_id = ExtendedPoint::basepoint_mult(&constants::l); + let B = &constants::ED25519_BASEPOINT_TABLE; + let should_be_id = B * &constants::l; assert!(should_be_id.is_identity()); } @@ -1364,10 +1351,9 @@ mod test { #[cfg(feature="basepoint_table_creation")] fn test_precomputed_basepoint_mult() { let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); - let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR); - let aB_2 = table.basepoint_mult(&A_SCALAR); - assert_eq!(aB_1.compress_edwards(), - aB_2.compress_edwards()); + let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; + let aB_2 = &(*table) * &A_SCALAR; + assert_eq!(aB_1.compress_edwards(), aB_2.compress_edwards()); } /// Test scalar_mult versus a known scalar multiple from ed25519.py @@ -1388,7 +1374,7 @@ mod test { #[test] fn basepoint_mult_two_vs_basepoint2() { let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; - let bp2 = ExtendedPoint::basepoint_mult(&Scalar(two_bytes)); + let bp2 = &constants::ED25519_BASEPOINT_TABLE * &Scalar(two_bytes); assert_eq!(bp2.compress_edwards(), BASE2_CMPRSSD); } @@ -1454,7 +1440,7 @@ mod test { /// the type system and prove correctness). #[test] fn monte_carlo_overflow_underflow_debug_assert_test() { - let mut P = ExtendedPoint::basepoint(); + let mut P = constants::ED25519_BASEPOINT; // N.B. each scalar_mult does 1407 field mults, 1024 field squarings, // so this does ~ 1M of each operation. for _ in 0..1_000 { @@ -1499,13 +1485,14 @@ mod bench { #[bench] fn basepoint_mult(b: &mut Bencher) { - b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR)); + let B = &constants::ED25519_BASEPOINT_TABLE; + b.iter(|| B * &A_SCALAR); } #[bench] fn scalar_mult(b: &mut Bencher) { - let bp = constants::ED25519_BASEPOINT; - b.iter(|| &bp * &A_SCALAR); + let B = &constants::ED25519_BASEPOINT; + b.iter(|| B * &A_SCALAR); } #[bench] @@ -1569,7 +1556,7 @@ mod bench { #[cfg(feature="basepoint_table_creation")] #[bench] fn create_basepoint_table(b: &mut Bencher) { - let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); + let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; b.iter(|| EdwardsBasepointTable::create(&aB)); } @@ -1590,8 +1577,8 @@ mod bench { // Create 10 random scalars let scalars: Vec<_> = (0..10).map(|_| Scalar::random(&mut csprng)).collect(); // Create 10 points (by doing scalar mults) - let points: Vec<_> = scalars.iter() - .map(|s| ExtendedPoint::basepoint_mult(s)).collect(); + let B = &constants::ED25519_BASEPOINT_TABLE; + let points: Vec<_> = scalars.iter().map(|s| B * &s).collect(); // XXX Currently Rust's benchmarking implementation doesn't // allow you to specify a sequence of random inputs, but only diff --git a/src/decaf.rs b/src/decaf.rs index 6e4d2c6..1023b26 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -40,7 +40,6 @@ use std::boxed::Box; use curve; use curve::ExtendedPoint; use curve::EdwardsBasepointTable; -use curve::BasepointMult; use curve::Identity; use scalar::Scalar; @@ -265,22 +264,17 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a DecafPoint { } } -impl BasepointMult for DecafPoint { - // XXX is this actually in the image of the isogeny, - // or do we need a different basepoint? - fn basepoint() -> DecafPoint { - DecafPoint(ExtendedPoint::basepoint()) - } - - fn basepoint_mult(scalar: &Scalar) -> DecafPoint { - DecafPoint(ExtendedPoint::basepoint_mult(scalar)) - } -} - - /// Precomputation #[derive(Clone)] -pub struct DecafBasepointTable(EdwardsBasepointTable); +pub struct DecafBasepointTable(pub EdwardsBasepointTable); + +impl<'a, 'b> Mul<&'b Scalar> for &'a DecafBasepointTable { + type Output = DecafPoint; + + fn mul(self, scalar: &'b Scalar) -> DecafPoint { + DecafPoint(&self.0 * scalar) + } +} impl DecafBasepointTable { /// Create a precomputed table of multiples of the given `basepoint`. @@ -289,11 +283,6 @@ impl DecafBasepointTable { let edwards_table = EdwardsBasepointTable::create(&basepoint.0); box DecafBasepointTable(*edwards_table) } - - /// Use the precomputed table to quickly compute `scalar * basepoint` - pub fn basepoint_mult(&self, scalar: &Scalar) -> DecafPoint { - DecafPoint(self.0.basepoint_mult(scalar)) - } } // ------------------------------------------------------------------------ @@ -350,7 +339,6 @@ mod test { use constants; use curve::CompressedEdwardsY; use curve::ExtendedPoint; - use curve::BasepointMult; use curve::Identity; use super::*; @@ -376,17 +364,17 @@ mod test { #[test] fn decaf_basepoint_roundtrip() { - let bp_compressed_decaf = DecafPoint::basepoint().compress(); + let bp_compressed_decaf = constants::DECAF_ED25519_BASEPOINT.compress(); let bp_recaf = bp_compressed_decaf.decompress().unwrap().0; // Check that bp_recaf differs from bp by a point of order 4 - let diff = &ExtendedPoint::basepoint() - &bp_recaf; - let diff4 = diff.mult_by_pow_2(4); + let diff = &constants::ED25519_BASEPOINT - &bp_recaf; + let diff4 = diff.mult_by_pow_2(4); // XXX this is wrong assert_eq!(diff4.compress_edwards(), CompressedEdwardsY::identity()); } #[test] fn decaf_four_torsion_basepoint() { - let bp = DecafPoint::basepoint(); + let bp = constants::DECAF_ED25519_BASEPOINT; let bp_coset = bp.coset4(); for i in 0..4 { assert_eq!(bp, DecafPoint(bp_coset[i])); @@ -396,8 +384,8 @@ mod test { #[test] fn decaf_four_torsion_random() { let mut rng = OsRng::new().unwrap(); - let s = Scalar::random(&mut rng); - let P = DecafPoint::basepoint_mult(&s); + let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let P = B * &Scalar::random(&mut rng); let P_coset = P.coset4(); for i in 0..4 { assert_eq!(P, DecafPoint(P_coset[i])); @@ -407,27 +395,14 @@ mod test { #[test] fn decaf_random_roundtrip() { let mut rng = OsRng::new().unwrap(); + let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; for _ in 0..100 { - let s = Scalar::random(&mut rng); - let P = DecafPoint::basepoint_mult(&s); + let P = B * &Scalar::random(&mut rng); let compressed_P = P.compress(); let Q = compressed_P.decompress().unwrap(); assert_eq!(P, Q); } } - - /// Test basepoint_mult versus a newly-generated DecafBasepointTable - #[test] - #[cfg(feature = "basepoint_table_creation")] - fn basepoint_mult_vs_decafbasepointtable() { - let table = DecafBasepointTable::create(&DecafPoint::basepoint()); - let mut rng = OsRng::new().unwrap(); - let s = Scalar::random(&mut rng); - let basepoint_mult_s = DecafPoint::basepoint_mult(&s); - let table_basepoint_mult_s = table.basepoint_mult(&s); - - assert_eq!(basepoint_mult_s, table_basepoint_mult_s); - } } #[cfg(all(test, feature = "bench"))] @@ -440,8 +415,8 @@ mod bench { #[bench] fn decompression(b: &mut Bencher) { let mut rng = OsRng::new().unwrap(); - let s = Scalar::random(&mut rng); - let P = DecafPoint::basepoint_mult(&s); + let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let P = B * &Scalar::random(&mut rng); let P_compressed = P.compress(); b.iter(|| P_compressed.decompress().unwrap()); } @@ -449,8 +424,8 @@ mod bench { #[bench] fn compression(b: &mut Bencher) { let mut rng = OsRng::new().unwrap(); - let s = Scalar::random(&mut rng); - let P = DecafPoint::basepoint_mult(&s); + let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let P = B * &Scalar::random(&mut rng); b.iter(|| P.compress()); } } From 127169c151f27b32ebd6e79d843307cb8cd29d05 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 21:55:19 -0700 Subject: [PATCH 3/6] Remove boxes --- Cargo.toml | 4 +--- src/curve.rs | 16 +++++----------- src/decaf.rs | 11 ++--------- src/lib.rs | 4 ++-- 4 files changed, 10 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c164472..556dd79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,12 +36,10 @@ version = "^0.6" version = "0.4" [features] -nightly = ["basepoint_table_creation", "radix_51"] +nightly = ["radix_51"] default = ["std"] std = ["rand"] yolocrypto = [] -# Needs nightly for placement new -basepoint_table_creation = [] bench = [] # Radix-51 arithmetic using u128 radix_51 = [] diff --git a/src/curve.rs b/src/curve.rs index c56dd25..3a5ab52 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -92,11 +92,6 @@ use subtle::CTAssignable; use subtle::CTEq; use subtle::CTNegatable; -#[cfg(all(not(feature = "std"), feature = "basepoint_table_creation"))] -use collections::boxed::Box; -#[cfg(all(feature = "std", feature = "basepoint_table_creation"))] -use std::boxed::Box; - // ------------------------------------------------------------------------ // Compressed points // ------------------------------------------------------------------------ @@ -877,12 +872,11 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable { impl EdwardsBasepointTable { /// Create a table of precomputed multiples of `basepoint`. - #[cfg(feature="basepoint_table_creation")] - pub fn create(basepoint: &ExtendedPoint) -> Box { + pub fn create(basepoint: &ExtendedPoint) -> EdwardsBasepointTable { // Create the table storage - // XXX can we be assured that this is not allocated on the stack? // XXX can we skip the initialization without too much unsafety? - let mut table = box EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); + // stick 30K on the stack and call it a day. + let mut table = EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); let mut P = basepoint.clone(); for i in 0..32 { // P = (16^2)^i * B @@ -894,7 +888,7 @@ impl EdwardsBasepointTable { } P = P.mult_by_pow_2(8); } - return table + table } } @@ -1352,7 +1346,7 @@ mod test { fn test_precomputed_basepoint_mult() { let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - let aB_2 = &(*table) * &A_SCALAR; + let aB_2 = &table * &A_SCALAR; assert_eq!(aB_1.compress_edwards(), aB_2.compress_edwards()); } diff --git a/src/decaf.rs b/src/decaf.rs index 1023b26..a0514ae 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -32,11 +32,6 @@ use subtle::CTNegatable; use core::ops::{Add, Sub, Neg}; use core::ops::{Mul, MulAssign}; -#[cfg(all(not(feature = "std"), feature = "basepoint_table_creation"))] -use collections::boxed::Box; -#[cfg(all(feature = "std", feature = "basepoint_table_creation"))] -use std::boxed::Box; - use curve; use curve::ExtendedPoint; use curve::EdwardsBasepointTable; @@ -278,10 +273,8 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a DecafBasepointTable { impl DecafBasepointTable { /// Create a precomputed table of multiples of the given `basepoint`. - #[cfg(feature = "basepoint_table_creation")] - pub fn create(basepoint: &DecafPoint) -> Box { - let edwards_table = EdwardsBasepointTable::create(&basepoint.0); - box DecafBasepointTable(*edwards_table) + pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable { + DecafBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) } } diff --git a/src/lib.rs b/src/lib.rs index 31e7177..40efe8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,10 +11,10 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(collections))] -#![cfg_attr(feature = "nightly", feature(box_syntax))] #![cfg_attr(feature = "nightly", feature(i128_type))] -#![allow(unused_features)] #![cfg_attr(feature = "bench", feature(test))] + +#![allow(unused_features)] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek From 0ae0d2b72a47cc17189b773fe1eeac17f68af584 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 3 May 2017 18:18:00 -0700 Subject: [PATCH 4/6] Add function to get the basepoint from a basepoint table --- src/curve.rs | 14 ++++++++++++++ src/decaf.rs | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 3a5ab52..ca3e4a1 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -890,6 +890,13 @@ impl EdwardsBasepointTable { } table } + + /// Get the basepoint for this table as an `ExtendedPoint`. + pub fn basepoint(&self) -> ExtendedPoint { + // self.0[0][0] has 1*(16^2)^0*B, but as an `AffineNielsPoint` + // Add identity to convert to extended. + (&ExtendedPoint::identity() + &self.0[0][0]).to_extended() + } } impl ExtendedPoint { @@ -1271,6 +1278,13 @@ mod test { assert_eq!(compressed, constants::BASE_CMPRSSD); } + /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint. + #[test] + fn basepoint_table_basepoint_function_correct() { + let bp = constants::ED25519_BASEPOINT_TABLE.basepoint(); + assert_eq!(bp.compress_edwards(), constants::BASE_CMPRSSD); + } + /// Test `impl Add for ExtendedPoint` /// using basepoint + basepoint versus the 2*basepoint constant. #[test] diff --git a/src/decaf.rs b/src/decaf.rs index a0514ae..9d1a830 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -276,6 +276,11 @@ impl DecafBasepointTable { pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable { DecafBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) } + + /// Get the basepoint for this table as a `DecafPoint`. + pub fn basepoint(&self) -> DecafPoint { + DecafPoint(self.0.basepoint()) + } } // ------------------------------------------------------------------------ From c6dc9d318d37629d7178615a9bb2b35f20998dcb Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Wed, 3 May 2017 19:06:41 -0700 Subject: [PATCH 5/6] Add a helper function to construct a Scalar from a u64 --- src/scalar.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/scalar.rs b/src/scalar.rs index 067f780..73b30f1 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -261,6 +261,15 @@ impl Scalar { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Construct a scalar from the given `u64`. + pub fn from_u64(x: u64) -> Scalar { + let mut s = Scalar::zero(); + for i in 0..8 { + s[i] = (x >> (i*8)) as u8; + } + s + } + /// Compute the multiplicative inverse of this scalar. pub fn invert(&self) -> Scalar { self.unpack().invert().pack() @@ -728,6 +737,20 @@ mod test { } } + #[test] + fn from_unsigned() { + let val = 0xdeadbeefdeadbeef; + let s = Scalar::from_u64(val); + assert_eq!(s[7], 0xde); + assert_eq!(s[6], 0xad); + assert_eq!(s[5], 0xbe); + assert_eq!(s[4], 0xef); + assert_eq!(s[3], 0xde); + assert_eq!(s[2], 0xad); + assert_eq!(s[1], 0xbe); + assert_eq!(s[0], 0xef); + } + #[test] fn scalar_multiply_by_one() { let one = Scalar::one(); From c18627f7c2d103a5dd232cf79b8202ade5361848 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 4 May 2017 00:02:29 -0700 Subject: [PATCH 6/6] Generalize k_fold_scalar_mult --- src/curve.rs | 20 ++++++++++++-------- src/decaf.rs | 9 +++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index ca3e4a1..78ff254 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1066,12 +1066,15 @@ pub mod vartime { /// /// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an /// error to call this function with two vectors of different lengths. - pub fn k_fold_scalar_mult(scalars: &Vec, - points: &Vec) -> ExtendedPoint { - assert_eq!(scalars.len(), points.len()); + pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> ExtendedPoint + where I: IntoIterator, J: IntoIterator + { + //assert_eq!(scalars.len(), points.len()); - let nafs: Vec<_> = scalars.iter().map(|c| c.non_adjacent_form()).collect(); - let odd_multiples: Vec<_> = points.iter().map(|P| OddMultiples::create(&P)).collect(); + let nafs: Vec<_> = scalars.into_iter() + .map(|c| c.non_adjacent_form()).collect(); + let odd_multiples: Vec<_> = points.into_iter() + .map(|P| OddMultiples::create(P)).collect(); let mut r = ProjectivePoint::identity(); @@ -1471,9 +1474,10 @@ mod test { #[test] fn k_fold_scalar_mult_vs_ed25519py() { let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let points = vec![A,constants::ED25519_BASEPOINT]; - let scalars = vec![A_SCALAR, B_SCALAR]; - let result = vartime::k_fold_scalar_mult(&scalars, &points); + let result = vartime::k_fold_scalar_mult( + &[A_SCALAR, B_SCALAR], + &[A, constants::ED25519_BASEPOINT] + ); assert_eq!(result.compress_edwards(), DOUBLE_SCALAR_MULT_RESULT); } } diff --git a/src/decaf.rs b/src/decaf.rs index 9d1a830..4fba23f 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -318,10 +318,11 @@ pub mod vartime { /// /// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an /// error to call this function with two vectors of different lengths. - pub fn k_fold_scalar_mult(scalars: &Vec, - points: &Vec) -> DecafPoint { - let extended_points: Vec = points.iter().map(|P| P.0).collect(); - DecafPoint(curve::vartime::k_fold_scalar_mult(scalars, &extended_points)) + pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> DecafPoint + where I: IntoIterator, J: IntoIterator + { + let extended_points = points.into_iter().map(|P| &P.0); + DecafPoint(curve::vartime::k_fold_scalar_mult(scalars, extended_points)) } }