mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-08 21:00:40 +00:00
First working version
This commit is contained in:
parent
15b88be2d2
commit
4f6788c72d
2 changed files with 141 additions and 72 deletions
|
|
@ -49,53 +49,86 @@ impl<'a, 'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint {
|
||||||
use stdsimd::vendor::_mm256_permute2x128_si256;
|
use stdsimd::vendor::_mm256_permute2x128_si256;
|
||||||
use stdsimd::vendor::_mm256_permutevar8x32_epi32;
|
use stdsimd::vendor::_mm256_permutevar8x32_epi32;
|
||||||
use stdsimd::vendor::_mm256_blend_epi32;
|
use stdsimd::vendor::_mm256_blend_epi32;
|
||||||
|
use stdsimd::vendor::_mm256_shuffle_epi32;
|
||||||
|
|
||||||
let mut P: FieldElement32x4 = self.0;
|
let P: &FieldElement32x4 = &self.0;
|
||||||
let mut Q: FieldElement32x4 = other.0;
|
let Q: &FieldElement32x4 = &other.0;
|
||||||
let mut t0: FieldElement32x4 = self.0;
|
|
||||||
|
let mut t0 = FieldElement32x4::zero();
|
||||||
|
let mut t1 = FieldElement32x4::zero();
|
||||||
|
|
||||||
|
macro_rules! print_vec {
|
||||||
|
($x:ident) => {
|
||||||
|
let splits = $x.split();
|
||||||
|
println!("{}[0] = {:?}", stringify!($x), splits[0].to_bytes());
|
||||||
|
println!("{}[1] = {:?}", stringify!($x), splits[1].to_bytes());
|
||||||
|
println!("{}[2] = {:?}", stringify!($x), splits[2].to_bytes());
|
||||||
|
println!("{}[3] = {:?}", stringify!($x), splits[3].to_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
t0.0[i] = _mm256_permute2x128_si256(P.0[i].into(), Q.0[i].into(), 32).into();
|
t0.0[i] = _mm256_permute2x128_si256(P.0[i].into(), Q.0[i].into(), 32).into();
|
||||||
}
|
}
|
||||||
//println!("t0 = (X1, Y1, X2, Y2)");
|
//println!("t0 = (X1, Y1, X2, Y2)");
|
||||||
//println!("t0 = {:?}\n", t0.split());
|
//print_vec!(t0);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
let mut t1 = t0.diff_sum();
|
t0.diff_sum();
|
||||||
//println!("t1 = (S1 S3 S2 S4)");
|
|
||||||
//println!("t1 = {:?}\n", t1.split());
|
//println!("t0 = (S0 S1 S2 S3)");
|
||||||
|
//print_vec!(t0);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
Q.0[i] = _mm256_permute2x128_si256(t1.0[i].into(), Q.0[i].into(), 49).into();
|
t1.0[i] = _mm256_blend_epi32(t0.0[i].into(), P.0[i].into(), 0b11110000).into();
|
||||||
t1.0[i] = _mm256_blend_epi32(t1.0[i].into(), P.0[i].into(), 0b11110000).into();
|
t0.0[i] = _mm256_permute2x128_si256(t0.0[i].into(), Q.0[i].into(), 49).into();
|
||||||
}
|
}
|
||||||
//println!("Q = (S2 S4 Z2 T2)");
|
//println!("t0 = (S2 S3 Z2 T2)");
|
||||||
//println!("Q = {:?}\n", Q.split());
|
//print_vec!(t0);
|
||||||
//println!("t1 = (S1 S3 Z1 T1)");
|
//println!("");
|
||||||
//println!("t1 = {:?}\n", t1.split());
|
|
||||||
|
|
||||||
P = &t1 * &Q;
|
//println!("t1 = (S0 S1 Z1 T1)");
|
||||||
//println!("P = (S5 S6 S8 S7)");
|
//print_vec!(t1);
|
||||||
//println!("P = {:?}\n", P.split());
|
//println!("");
|
||||||
|
|
||||||
|
let mut t2 = &t0 * &t1;
|
||||||
|
//println!("t2 = (S4 S5 S6 S7)");
|
||||||
|
//print_vec!(t2);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
P.scale_by_curve_constants();
|
t2.scale_by_curve_constants();
|
||||||
//println!("P = (S5' S6' S10 S8)");
|
//println!("t2 = (S8 S9 S10 S11)");
|
||||||
//println!("P = {:?}\n", P.split());
|
//print_vec!(t2);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
|
for i in 0..5 {
|
||||||
|
let swapped = _mm256_shuffle_epi32(t2.0[i].into(), 0b10_11_00_01);
|
||||||
|
t2.0[i] = _mm256_blend_epi32(t2.0[i].into(), swapped, 0b11110000).into();
|
||||||
|
}
|
||||||
|
//println!("t2 = (S8 S9 S11 S10)");
|
||||||
|
//print_vec!(t2);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
Q = P.diff_sum();
|
t2.diff_sum();
|
||||||
//println!("Q = (S11 S14 S12 S13)");
|
//println!("t2 = (S12 S13 S14 S15)");
|
||||||
//println!("Q = {:?}\n", Q.split());
|
//print_vec!(t2);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
let c0 = u32x8::new(0,5,2,7,5,0,7,2); // (ABCD) -> (ADDA)
|
let c0 = u32x8::new(0,5,2,7,5,0,7,2); // (ABCD) -> (ADDA)
|
||||||
let c1 = u32x8::new(4,1,6,3,4,1,6,3); // (ABCD) -> (CBBC)
|
let c1 = u32x8::new(4,1,6,3,4,1,6,3); // (ABCD) -> (CBCB)
|
||||||
|
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
t0.0[i] = _mm256_permutevar8x32_epi32(Q.0[i], c0);
|
t0.0[i] = _mm256_permutevar8x32_epi32(t2.0[i], c0);
|
||||||
t1.0[i] = _mm256_permutevar8x32_epi32(Q.0[i], c1);
|
t1.0[i] = _mm256_permutevar8x32_epi32(t2.0[i], c1);
|
||||||
}
|
}
|
||||||
//println!("t0 = (S11 S13 S13 S11)");
|
//println!("t0 = (S11 S13 S13 S11)");
|
||||||
//println!("t0 = {:?}\n", t0.split());
|
//print_vec!(t0);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
//println!("t1 = (S12 S14 S14 S12)");
|
//println!("t1 = (S12 S14 S14 S12)");
|
||||||
//println!("t1 = {:?}\n", t1.split());
|
//print_vec!(t1);
|
||||||
|
//println!("");
|
||||||
|
|
||||||
ExtendedPoint(&t0 * &t1)
|
ExtendedPoint(&t0 * &t1)
|
||||||
}
|
}
|
||||||
|
|
@ -112,25 +145,51 @@ mod test {
|
||||||
let (X1, Y1, Z1, T1) = (P.X, P.Y, P.Z, P.T);
|
let (X1, Y1, Z1, T1) = (P.X, P.Y, P.Z, P.T);
|
||||||
let (X2, Y2, Z2, T2) = (Q.X, Q.Y, Q.Z, Q.T);
|
let (X2, Y2, Z2, T2) = (Q.X, Q.Y, Q.Z, Q.T);
|
||||||
|
|
||||||
|
macro_rules! print_var {
|
||||||
|
($x:ident) => {
|
||||||
|
println!("{} = {:?}", stringify!($x), $x.to_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let S0 = &Y1 - &X1; // R1
|
let S0 = &Y1 - &X1; // R1
|
||||||
let S1 = &Y1 + &X1; // R3
|
let S1 = &Y1 + &X1; // R3
|
||||||
let S2 = &Y2 - &X2; // R2
|
let S2 = &Y2 - &X2; // R2
|
||||||
let S3 = &Y2 + &X2; // R4
|
let S3 = &Y2 + &X2; // R4
|
||||||
|
print_var!(S0);
|
||||||
|
print_var!(S1);
|
||||||
|
print_var!(S2);
|
||||||
|
print_var!(S3);
|
||||||
|
println!("");
|
||||||
|
|
||||||
let S4 = &S0 * &S2; // R5 = R1 * R2
|
let S4 = &S0 * &S2; // R5 = R1 * R2
|
||||||
let S5 = &S1 * &S3; // R6 = R3 * R4
|
let S5 = &S1 * &S3; // R6 = R3 * R4
|
||||||
let S6 = &T1 * &T2; // R7
|
let S6 = &Z1 * &Z2; // R8
|
||||||
let S7 = &Z1 * &Z2; // R8
|
let S7 = &T1 * &T2; // R7
|
||||||
|
print_var!(S4);
|
||||||
|
print_var!(S5);
|
||||||
|
print_var!(S6);
|
||||||
|
print_var!(S7);
|
||||||
|
println!("");
|
||||||
|
|
||||||
let S8 = &S6 * &(-&FieldElement32([2*121665,0,0,0,0,0,0,0,0,0])); // R7
|
let S8 = &S4 * &FieldElement32([ 121666,0,0,0,0,0,0,0,0,0]); // R5
|
||||||
let S9 = &S7 * &FieldElement32([2*121666,0,0,0,0,0,0,0,0,0]); // R8
|
let S9 = &S5 * &FieldElement32([ 121666,0,0,0,0,0,0,0,0,0]); // R6
|
||||||
let S10 = &S4 * &FieldElement32([ 121666,0,0,0,0,0,0,0,0,0]); // R5
|
let S10 = &S6 * &FieldElement32([2*121666,0,0,0,0,0,0,0,0,0]); // R8
|
||||||
let S11 = &S5 * &FieldElement32([ 121666,0,0,0,0,0,0,0,0,0]); // R6
|
let S11 = &S7 * &(-&FieldElement32([2*121665,0,0,0,0,0,0,0,0,0])); // R7
|
||||||
|
print_var!(S8 );
|
||||||
|
print_var!(S9 );
|
||||||
|
print_var!(S10);
|
||||||
|
print_var!(S11);
|
||||||
|
println!("");
|
||||||
|
|
||||||
let S12 = &S11 - &S10; // R1
|
let S12 = &S9 - &S8; // R1
|
||||||
let S13 = &S11 + &S10; // R4
|
let S13 = &S9 + &S8; // R4
|
||||||
let S14 = &S9 - &S8; // R2
|
let S14 = &S10 - &S11; // R2
|
||||||
let S15 = &S9 + &S8; // R3
|
let S15 = &S10 + &S11; // R3
|
||||||
|
print_var!(S12);
|
||||||
|
print_var!(S13);
|
||||||
|
print_var!(S14);
|
||||||
|
print_var!(S15);
|
||||||
|
println!("");
|
||||||
|
|
||||||
let X3 = &S12 * &S14; // R1 * R2
|
let X3 = &S12 * &S14; // R1 * R2
|
||||||
let Y3 = &S15 * &S13; // R3 * R4
|
let Y3 = &S15 * &S13; // R3 * R4
|
||||||
|
|
@ -140,8 +199,22 @@ mod test {
|
||||||
edwards::ExtendedPoint{X: X3, Y: Y3, Z: Z3, T: T3}
|
edwards::ExtendedPoint{X: X3, Y: Y3, Z: Z3, T: T3}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn addition_test_helper(P: edwards::ExtendedPoint, Q: edwards::ExtendedPoint) {
|
||||||
|
let R1: edwards::ExtendedPoint = serial_add(P.into(), Q.into()).into();
|
||||||
|
let R2: edwards::ExtendedPoint = (&ExtendedPoint::from(P) + &ExtendedPoint::from(Q)).into();
|
||||||
|
println!("Testing point addition:");
|
||||||
|
println!("P = {:?}", P);
|
||||||
|
println!("Q = {:?}", Q);
|
||||||
|
println!("(serial) R1 = {:?}", R1);
|
||||||
|
println!("(vector) R2 = {:?}", R2);
|
||||||
|
println!("P + Q = {:?}", &P + &Q);
|
||||||
|
assert_eq!(R1.compress(), (&P + &Q).compress());
|
||||||
|
assert_eq!(R2.compress(), (&P + &Q).compress());
|
||||||
|
println!("OK!\n");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serial_add_vs_edwards_extendedpoint() {
|
fn addition_vs_serial_add_vs_edwards_extendedpoint() {
|
||||||
use constants;
|
use constants;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
use edwards::Identity;
|
use edwards::Identity;
|
||||||
|
|
@ -149,41 +222,40 @@ mod test {
|
||||||
println!("Testing id + id");
|
println!("Testing id + id");
|
||||||
let P = edwards::ExtendedPoint::identity();
|
let P = edwards::ExtendedPoint::identity();
|
||||||
let Q = edwards::ExtendedPoint::identity();
|
let Q = edwards::ExtendedPoint::identity();
|
||||||
let R: edwards::ExtendedPoint = serial_add(P.into(), Q.into()).into();
|
addition_test_helper(P, Q);
|
||||||
println!("P = {:?}", P);
|
|
||||||
println!("Q = {:?}", Q);
|
|
||||||
println!("R = {:?}", R);
|
|
||||||
println!("P + Q = {:?}", &P + &Q);
|
|
||||||
assert_eq!(R.compress(), (&P + &Q).compress());
|
|
||||||
|
|
||||||
println!("Testing id + B");
|
println!("Testing id + B");
|
||||||
let P = edwards::ExtendedPoint::identity();
|
let P = edwards::ExtendedPoint::identity();
|
||||||
let Q = constants::ED25519_BASEPOINT_POINT;
|
let Q = constants::ED25519_BASEPOINT_POINT;
|
||||||
let R: edwards::ExtendedPoint = serial_add(P.into(), Q.into()).into();
|
addition_test_helper(P, Q);
|
||||||
println!("P = {:?}", P);
|
|
||||||
println!("Q = {:?}", Q);
|
|
||||||
println!("R = {:?}", R);
|
|
||||||
println!("P + Q = {:?}", &P + &Q);
|
|
||||||
assert_eq!(R.compress(), (&P + &Q).compress());
|
|
||||||
|
|
||||||
println!("Testing B + B");
|
println!("Testing B + B");
|
||||||
let P = constants::ED25519_BASEPOINT_POINT;
|
let P = constants::ED25519_BASEPOINT_POINT;
|
||||||
let Q = constants::ED25519_BASEPOINT_POINT;
|
let Q = constants::ED25519_BASEPOINT_POINT;
|
||||||
let R: edwards::ExtendedPoint = serial_add(P.into(), Q.into()).into();
|
addition_test_helper(P, Q);
|
||||||
println!("P = {:?}", P);
|
|
||||||
println!("Q = {:?}", Q);
|
|
||||||
println!("R = {:?}", R);
|
|
||||||
println!("P + Q = {:?}", &P + &Q);
|
|
||||||
assert_eq!(R.compress(), (&P + &Q).compress());
|
|
||||||
|
|
||||||
println!("Testing B + kB");
|
println!("Testing B + kB");
|
||||||
let P = constants::ED25519_BASEPOINT_POINT;
|
let P = constants::ED25519_BASEPOINT_POINT;
|
||||||
let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from_u64(8475983829);
|
let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from_u64(8475983829);
|
||||||
let R: edwards::ExtendedPoint = serial_add(P.into(), Q.into()).into();
|
addition_test_helper(P, Q);
|
||||||
println!("P = {:?}", P);
|
|
||||||
println!("Q = {:?}", Q);
|
|
||||||
println!("R = {:?}", R);
|
|
||||||
println!("P + Q = {:?}", &P + &Q);
|
|
||||||
assert_eq!(R.compress(), (&P + &Q).compress());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, feature = "bench"))]
|
||||||
|
mod bench {
|
||||||
|
use test::Bencher;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use constants;
|
||||||
|
use scalar::Scalar;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn point_addition(b: &mut Bencher) {
|
||||||
|
let B = &constants::ED25519_BASEPOINT_TABLE;
|
||||||
|
let P = ExtendedPoint::from(B * &Scalar::from_u64(83973422));
|
||||||
|
let Q = ExtendedPoint::from(B * &Scalar::from_u64(98932328));
|
||||||
|
|
||||||
|
b.iter(|| &P + &Q );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ impl FieldElement32x4 {
|
||||||
FieldElement32x4(buf)
|
FieldElement32x4(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given `self = (A,B,C,D)`, compute `(B - A, B + A, D - C, D + C)`.
|
// Given `self = (A,B,C,D)`, set `self = (B - A, B + A, D - C, D + C)`.
|
||||||
pub fn diff_sum(&self) -> FieldElement32x4 {
|
pub fn diff_sum(&mut self) {
|
||||||
/// (v0 v1 v2 v3 v4 v5 v6 v7) -> (v1 v0 v3 v2 v5 v4 v7 v6)
|
/// (v0 v1 v2 v3 v4 v5 v6 v7) -> (v1 v0 v3 v2 v5 v4 v7 v6)
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn alternate_32bit_lanes(v: u32x8) -> u32x8 {
|
fn alternate_32bit_lanes(v: u32x8) -> u32x8 {
|
||||||
|
|
@ -92,8 +92,6 @@ impl FieldElement32x4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out = [u32x8::splat(0); 5];
|
|
||||||
|
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
let x = self.0[i];
|
let x = self.0[i];
|
||||||
let p = P_TIMES_2.0[i] ;
|
let p = P_TIMES_2.0[i] ;
|
||||||
|
|
@ -103,10 +101,8 @@ impl FieldElement32x4 {
|
||||||
let sum = x + x_shuf;
|
let sum = x + x_shuf;
|
||||||
let diff_sum = blend_alternating_32bit_lanes(diff, sum);
|
let diff_sum = blend_alternating_32bit_lanes(diff, sum);
|
||||||
|
|
||||||
out[i] = diff_sum;
|
self.0[i] = diff_sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldElement32x4(out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given `self = (A,B,C,D)`, compute `(B + A, B - A, D + C, D - C)`.
|
// Given `self = (A,B,C,D)`, compute `(B + A, B - A, D + C, D - C)`.
|
||||||
|
|
@ -415,9 +411,10 @@ mod test {
|
||||||
let x2 = FieldElement32([10200, 10201, 10202, 10203, 10204, 10205, 10206, 10207, 10208, 10209]);
|
let x2 = FieldElement32([10200, 10201, 10202, 10203, 10204, 10205, 10206, 10207, 10208, 10209]);
|
||||||
let x3 = FieldElement32([10300, 10301, 10302, 10303, 10304, 10305, 10306, 10307, 10308, 10309]);
|
let x3 = FieldElement32([10300, 10301, 10302, 10303, 10304, 10305, 10306, 10307, 10308, 10309]);
|
||||||
|
|
||||||
let vec = FieldElement32x4::new(&x0, &x1, &x2, &x3);
|
let mut vec = FieldElement32x4::new(&x0, &x1, &x2, &x3);
|
||||||
|
vec.diff_sum();
|
||||||
|
|
||||||
let result = vec.diff_sum().split();
|
let result = vec.split();
|
||||||
|
|
||||||
assert_eq!(result[0], &x1 - &x0);
|
assert_eq!(result[0], &x1 - &x0);
|
||||||
assert_eq!(result[1], &x1 + &x0);
|
assert_eq!(result[1], &x1 + &x0);
|
||||||
|
|
@ -493,7 +490,7 @@ mod bench {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn multiply(b: &mut Bencher) {
|
fn multiply(b: &mut Bencher) {
|
||||||
let vec = FieldElement32x4::splat(&FieldElement::zero());
|
let vec = FieldElement32x4::splat(&FieldElement32::zero());
|
||||||
let vecprime = vec.clone();
|
let vecprime = vec.clone();
|
||||||
|
|
||||||
b.iter(|| &vec * &vecprime );
|
b.iter(|| &vec * &vecprime );
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue