mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-06 20:41:14 +00:00
Merge branch 'feature/scalarmult-lhs' into develop
This commit is contained in:
commit
4a646806b8
3 changed files with 137 additions and 2 deletions
92
src/curve.rs
92
src/curve.rs
|
|
@ -84,6 +84,8 @@ use core::ops::{Mul, MulAssign};
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
|
|
||||||
use constants;
|
use constants;
|
||||||
|
#[cfg(feature = "yolocrypto")]
|
||||||
|
use decaf::DecafPoint;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
use subtle::arrays_equal_ct;
|
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
|
// 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
|
/// Precomputation
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]);
|
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 {
|
impl EdwardsBasepointTable {
|
||||||
/// Create a table of precomputed multiples of `basepoint`.
|
/// Create a table of precomputed multiples of `basepoint`.
|
||||||
pub fn create(basepoint: &ExtendedPoint) -> EdwardsBasepointTable {
|
pub fn create(basepoint: &ExtendedPoint) -> EdwardsBasepointTable {
|
||||||
|
|
@ -1150,6 +1217,8 @@ pub mod vartime {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
#[cfg(feature = "yolocrypto")]
|
||||||
|
use decaf::DecafPoint;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
use subtle::CTAssignable;
|
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 {
|
mod vartime {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT};
|
use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT};
|
||||||
|
|
|
||||||
40
src/decaf.rs
40
src/decaf.rs
|
|
@ -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 {
|
impl DecafBasepointTable {
|
||||||
/// Create a precomputed table of multiples of the given `basepoint`.
|
/// Create a precomputed table of multiples of the given `basepoint`.
|
||||||
pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable {
|
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
|
// Debug traits
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -775,10 +775,11 @@ mod test {
|
||||||
assert_eq!(should_be_one, Scalar::one());
|
assert_eq!(should_be_one, Scalar::one());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
#[test]
|
#[test]
|
||||||
fn impl_mul() {
|
fn impl_mul() {
|
||||||
let should_be_X_TIMES_Y = &X * &Y;
|
let should_be_X_times_Y = &X * &Y;
|
||||||
assert_eq!(should_be_X_TIMES_Y, X_TIMES_Y);
|
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -809,6 +810,7 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
#[test]
|
#[test]
|
||||||
fn invert() {
|
fn invert() {
|
||||||
let inv_X = X.invert();
|
let inv_X = X.invert();
|
||||||
|
|
@ -817,6 +819,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negating a scalar twice should result in the original scalar.
|
// Negating a scalar twice should result in the original scalar.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
#[test]
|
#[test]
|
||||||
fn neg_twice_is_identity() {
|
fn neg_twice_is_identity() {
|
||||||
let negative_X = -&X;
|
let negative_X = -&X;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue