Merge branch 'feature/scalarmult-lhs' into develop

This commit is contained in:
Isis Lovecruft 2017-05-14 09:35:15 +00:00
commit 4a646806b8
Failed to extract signature
3 changed files with 137 additions and 2 deletions

View file

@ -84,6 +84,8 @@ use core::ops::{Mul, MulAssign};
use core::ops::Index;
use constants;
#[cfg(feature = "yolocrypto")]
use decaf::DecafPoint;
use field::FieldElement;
use scalar::Scalar;
use subtle::arrays_equal_ct;
@ -445,6 +447,15 @@ impl CTAssignable for AffineNielsPoint {
}
}
impl CTAssignable for ExtendedPoint {
fn conditional_assign(&mut self, other: &ExtendedPoint, choice: u8) {
self.X.conditional_assign(&other.X, choice);
self.Y.conditional_assign(&other.Y, choice);
self.Z.conditional_assign(&other.Z, choice);
self.T.conditional_assign(&other.T, choice);
}
}
// ------------------------------------------------------------------------
// Constant-time Equality
// ------------------------------------------------------------------------
@ -817,6 +828,29 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint {
}
}
impl<'a, 'b> Mul<&'b ExtendedPoint> for &'a Scalar {
type Output = ExtendedPoint;
/// Scalar multiplication: compute `self * point`.
///
/// Uses a window of size 4. Note: for scalar multiplication of
/// the basepoint, `basepoint_mult` is approximately 4x faster.
fn mul(self, point: &'b ExtendedPoint) -> ExtendedPoint {
point * &self
}
}
#[cfg(feature = "yolocrypto")]
impl<'a, 'b> Mul<&'b DecafPoint> for &'a Scalar {
type Output = DecafPoint;
/// Scalar multiplication: compute `self * scalar`.
fn mul(self, point: &'b DecafPoint) -> DecafPoint {
DecafPoint(self * &point.0)
}
}
/// Precomputation
#[derive(Clone)]
pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]);
@ -870,6 +904,39 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable {
}
}
impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar {
type Output = ExtendedPoint;
/// Construct an `ExtendedPoint` by via this `Scalar` times
/// a the basepoint, `B` included in a precomputed `basepoint_table`.
///
/// Precondition: this scalar must be reduced.
///
/// The computation proceeds as follows, as described on page 13
/// of the Ed25519 paper. Write this scalar `a` in radix 16 with
/// coefficients in [-8,8), i.e.,
///
/// a = a_0 + a_1*16^1 + ... + a_63*16^63,
///
/// with -8 ≤ a_i < 8. Then
///
/// a*B = a_0*B + a_1*16^1*B + ... + a_63*16^63*B.
///
/// Grouping even and odd coefficients gives
///
/// a*B = a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B
/// + a_1*16^1*B + a_3*16^3*B + ... + a_63*16^63*B
/// = (a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B)
/// + 16*(a_1*16^0*B + a_3*16^2*B + ... + a_63*16^62*B).
///
/// 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.
fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> ExtendedPoint {
basepoint_table * &self
}
}
impl EdwardsBasepointTable {
/// Create a table of precomputed multiples of `basepoint`.
pub fn create(basepoint: &ExtendedPoint) -> EdwardsBasepointTable {
@ -1150,6 +1217,8 @@ pub mod vartime {
#[cfg(test)]
mod test {
#[cfg(feature = "yolocrypto")]
use decaf::DecafPoint;
use field::FieldElement;
use scalar::Scalar;
use subtle::CTAssignable;
@ -1459,6 +1528,29 @@ mod test {
}
}
#[test]
fn scalarmult_extended_point_works_both_ways() {
let G: ExtendedPoint = constants::ED25519_BASEPOINT;
let s: Scalar = A_SCALAR;
let P1 = &G * &s;
let P2 = &s * &G;
assert!(P1.compress_edwards().to_bytes() == P2.compress_edwards().to_bytes());
}
#[test]
#[cfg(feature = "yolocrypto")]
fn scalarmult_decafpoint_works_both_ways() {
let P: DecafPoint = DecafPoint(constants::ED25519_BASEPOINT);
let s: Scalar = A_SCALAR;
let P1 = &P * &s;
let P2 = &s * &P;
assert!(P1.compress().as_bytes() == P2.compress().as_bytes());
}
mod vartime {
use super::super::*;
use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT};

View file

@ -271,6 +271,14 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a DecafBasepointTable {
}
}
impl<'a, 'b> Mul<&'a DecafBasepointTable> for &'b Scalar {
type Output = DecafPoint;
fn mul(self, basepoint_table: &'a DecafBasepointTable) -> DecafPoint {
DecafPoint(self * &basepoint_table.0)
}
}
impl DecafBasepointTable {
/// Create a precomputed table of multiples of the given `basepoint`.
pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable {
@ -283,6 +291,38 @@ impl DecafBasepointTable {
}
}
// ------------------------------------------------------------------------
// Constant-time conditional assignment
// ------------------------------------------------------------------------
impl CTAssignable for DecafPoint {
/// Conditionally assign `other` to `self`, if `choice == 1u8`.
///
/// # Example
///
/// ```
/// # use curve25519_dalek::curve::Identity;
/// # use curve25519_dalek::decaf::DecafPoint;
/// # use curve25519_dalek::subtle::CTAssignable;
/// # use curve25519_dalek::constants;
/// let A = DecafPoint::identity();
/// let B = constants::DECAF_ED25519_BASEPOINT;
///
/// let mut P = A;
///
/// P.conditional_assign(&B, 0u8);
/// assert!(P == A);
/// P.conditional_assign(&B, 1u8);
/// assert!(P == B);
/// ```
fn conditional_assign(&mut self, other: &DecafPoint, choice: u8) {
self.0.X.conditional_assign(&other.0.X, choice);
self.0.Y.conditional_assign(&other.0.Y, choice);
self.0.Z.conditional_assign(&other.0.Z, choice);
self.0.T.conditional_assign(&other.0.T, choice);
}
}
// ------------------------------------------------------------------------
// Debug traits
// ------------------------------------------------------------------------

View file

@ -775,10 +775,11 @@ mod test {
assert_eq!(should_be_one, Scalar::one());
}
#[allow(non_snake_case)]
#[test]
fn impl_mul() {
let should_be_X_TIMES_Y = &X * &Y;
assert_eq!(should_be_X_TIMES_Y, X_TIMES_Y);
let should_be_X_times_Y = &X * &Y;
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
}
#[test]
@ -809,6 +810,7 @@ mod test {
}
}
#[allow(non_snake_case)]
#[test]
fn invert() {
let inv_X = X.invert();
@ -817,6 +819,7 @@ mod test {
}
// Negating a scalar twice should result in the original scalar.
#[allow(non_snake_case)]
#[test]
fn neg_twice_is_identity() {
let negative_X = -&X;