Merge branch 'release/0.16.4'

This commit is contained in:
Henry de Valence 2018-05-10 17:50:17 -07:00
commit 696e965c39
5 changed files with 186 additions and 6 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "curve25519-dalek"
version = "0.16.3"
version = "0.16.4"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
"Henry de Valence <hdevalence@hdevalence.ca>"]
readme = "README.md"
@ -41,7 +41,7 @@ harness = false
# match exactly, since the build.rs uses the crate itself as a library.
[dependencies]
byteorder = "1"
byteorder = {version = "1", default-features = false }
digest = "0.7"
generic-array = "0.9"
clear_on_drop = "=0.2.3"

View file

@ -149,8 +149,10 @@ impl ExtendedPoint {
// tmp0 = (0 0 2*S3 -S4)
let tmp0: u32x8 = _mm256_blend_epi32(S3_2.into_bits(), t1.0[i].into_bits(), 0b10100000).into_bits();
t0.0[i] = (avx2::constants::P_TIMES_2_MASKED.0[i] + tmp0) + S1;
t0.0[i] = t0.0[i] + _mm256_blend_epi32(zero, S2.into_bits(), 0b10100101).into_bits();
t0.0[i] = t0.0[i] - _mm256_blend_epi32(S2.into_bits(), zero, 0b10100101).into_bits();
let S2_pos: u32x8 = _mm256_blend_epi32(zero, S2.into_bits(), 0b10100101).into_bits();
let S2_neg: u32x8 = _mm256_blend_epi32(S2.into_bits(), zero, 0b10100101).into_bits();
t0.0[i] = t0.0[i] + S2_pos;
t0.0[i] = t0.0[i] - S2_neg;
}
let c0 = u32x8::new(4,0,6,2,4,0,6,2).into_bits(); // (ABCD) -> (CACA)

View file

@ -98,6 +98,7 @@ use core::iter::Iterator;
use core::ops::{Add, Sub, Neg};
use core::ops::{AddAssign, SubAssign};
use core::ops::{Mul, MulAssign};
use core::iter::Sum;
use core::borrow::Borrow;
use subtle::ConditionallyAssignable;
@ -427,6 +428,19 @@ impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint {
define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
impl<T> Sum<T> for EdwardsPoint
where
T: Borrow<EdwardsPoint>
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = T>
{
iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow())
}
}
// ------------------------------------------------------------------------
// Negation
// ------------------------------------------------------------------------
@ -1092,6 +1106,38 @@ mod test {
assert_eq!(bp16.compress(), BASE16_CMPRSSD);
}
#[test]
fn impl_sum() {
// Test that sum works for non-empty iterators
let BASE = constants::ED25519_BASEPOINT_POINT;
let s1 = Scalar::from_u64(999);
let P1 = &BASE * &s1;
let s2 = Scalar::from_u64(333);
let P2 = &BASE * &s2;
let vec = vec![P1.clone(), P2.clone()];
let sum: EdwardsPoint = vec.iter().sum();
assert_eq!(sum, P1 + P2);
// Test that sum works for the empty iterator
let empty_vector: Vec<EdwardsPoint> = vec![];
let sum: EdwardsPoint = empty_vector.iter().sum();
assert_eq!(sum, EdwardsPoint::identity());
// Test that sum works on owning iterators
let s = Scalar::from_u64(2);
let mapped = vec.iter().map(|x| x * &s);
let sum: EdwardsPoint = mapped.sum();
assert_eq!(sum, &P1 * &s + &P2 * &s);
}
/// Test that the conditional assignment trait works for AffineNielsPoints.
#[test]
fn conditional_assign_for_affine_niels_point() {

View file

@ -169,6 +169,7 @@ use core::fmt::Debug;
use core::ops::{Add, Sub, Neg};
use core::ops::{AddAssign, SubAssign};
use core::ops::{Mul, MulAssign};
use core::iter::Sum;
use core::borrow::Borrow;
#[cfg(feature = "std")]
@ -732,6 +733,18 @@ impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint {
define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint);
impl<T> Sum<T> for RistrettoPoint
where
T: Borrow<RistrettoPoint>
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = T>
{
iter.fold(RistrettoPoint::identity(), |acc, item| acc + item.borrow())
}
}
impl<'a> Neg for &'a RistrettoPoint {
type Output = RistrettoPoint;
@ -1033,6 +1046,37 @@ mod test {
assert!(P1.compress().as_bytes() == P2.compress().as_bytes());
}
#[test]
fn impl_sum() {
// Test that sum works for non-empty iterators
let BASE = constants::RISTRETTO_BASEPOINT_POINT;
let s1 = Scalar::from_u64(999);
let P1 = &BASE * &s1;
let s2 = Scalar::from_u64(333);
let P2 = &BASE * &s2;
let vec = vec![P1.clone(), P2.clone()];
let sum: RistrettoPoint = vec.iter().sum();
assert_eq!(sum, P1 + P2);
// Test that sum works for the empty iterator
let empty_vector: Vec<RistrettoPoint> = vec![];
let sum: RistrettoPoint = empty_vector.iter().sum();
assert_eq!(sum, RistrettoPoint::identity());
// Test that sum works on owning iterators
let s = Scalar::from_u64(2);
let mapped = vec.iter().map(|x| x * &s);
let sum: RistrettoPoint = mapped.sum();
assert_eq!(sum, &P1 * &s + &P2 * &s);
}
#[test]
fn decompress_negative_s_fails() {
// constants::d is neg, so decompression should fail as |d| != d.

View file

@ -19,6 +19,8 @@ use core::ops::{Sub, SubAssign};
use core::ops::{Mul, MulAssign};
use core::ops::{Index};
use core::cmp::{Eq, PartialEq};
use core::iter::{Product, Sum};
use core::borrow::Borrow;
#[cfg(feature = "std")]
use rand::Rng;
@ -293,6 +295,30 @@ impl<'de> Deserialize<'de> for Scalar {
}
}
impl<T> Product<T> for Scalar
where
T: Borrow<Scalar>
{
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = T>
{
iter.fold(Scalar::one(), |acc, item| acc * item.borrow())
}
}
impl<T> Sum<T> for Scalar
where
T: Borrow<Scalar>
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = T>
{
iter.fold(Scalar::zero(), |acc, item| acc + item.borrow())
}
}
impl Scalar {
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
///
@ -540,7 +566,7 @@ impl Scalar {
/// $$
/// k = \sum\_{i=0}\^m k\_i 2^i,
/// $$
/// and split the sum as
/// and split the sum as
/// $$
/// k = \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i
/// $$
@ -581,7 +607,7 @@ impl Scalar {
let width = 1 << w;
let window_mask = width - 1;
let mut pos = 0;
let mut carry = 0;
while pos < 256 {
@ -912,6 +938,68 @@ mod test {
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
}
#[allow(non_snake_case)]
#[test]
fn impl_product() {
// Test that product works for non-empty iterators
let X_Y_vector = vec![X, Y];
let should_be_X_times_Y: Scalar = X_Y_vector.iter().product();
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
// Test that product works for the empty iterator
let one = Scalar::one();
let empty_vector = vec![];
let should_be_one: Scalar = empty_vector.iter().product();
assert_eq!(should_be_one, one);
// Test that product works for iterators where Item = Scalar
let xs = [Scalar::from_u64(2); 10];
let ys = [Scalar::from_u64(3); 10];
// now zs is an iterator with Item = Scalar
let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x * y);
let x_prod: Scalar = xs.iter().product();
let y_prod: Scalar = ys.iter().product();
let z_prod: Scalar = zs.product();
assert_eq!(x_prod, Scalar::from_u64(1024));
assert_eq!(y_prod, Scalar::from_u64(59049));
assert_eq!(z_prod, Scalar::from_u64(60466176));
assert_eq!(x_prod * y_prod, z_prod);
}
#[test]
fn impl_sum() {
// Test that sum works for non-empty iterators
let two = Scalar::from_u64(2);
let one_vector = vec![Scalar::one(), Scalar::one()];
let should_be_two: Scalar = one_vector.iter().sum();
assert_eq!(should_be_two, two);
// Test that sum works for the empty iterator
let zero = Scalar::zero();
let empty_vector = vec![];
let should_be_zero: Scalar = empty_vector.iter().sum();
assert_eq!(should_be_zero, zero);
// Test that sum works for owned types
let xs = [Scalar::from_u64(1); 10];
let ys = [Scalar::from_u64(2); 10];
// now zs is an iterator with Item = Scalar
let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x + y);
let x_sum: Scalar = xs.iter().sum();
let y_sum: Scalar = ys.iter().sum();
let z_sum: Scalar = zs.sum();
assert_eq!(x_sum, Scalar::from_u64(10));
assert_eq!(y_sum, Scalar::from_u64(20));
assert_eq!(z_sum, Scalar::from_u64(30));
assert_eq!(x_sum + y_sum, z_sum);
}
#[test]
fn square() {
let expected = &X * &X;