mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-07 20:50:39 +00:00
Merge remote-tracking branch 'hdevalence/feature/operator_scalar_mult_r2' into develop
This commit is contained in:
commit
61d07693ec
6 changed files with 154 additions and 136 deletions
|
|
@ -36,12 +36,10 @@ version = "^0.6"
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
nightly = ["basepoint_table_creation", "radix_51"]
|
nightly = ["radix_51"]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["rand"]
|
std = ["rand"]
|
||||||
yolocrypto = []
|
yolocrypto = []
|
||||||
# Needs nightly for placement new
|
|
||||||
basepoint_table_creation = []
|
|
||||||
bench = []
|
bench = []
|
||||||
# Radix-51 arithmetic using u128
|
# Radix-51 arithmetic using u128
|
||||||
radix_51 = []
|
radix_51 = []
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ use curve::ExtendedPoint;
|
||||||
use curve::AffineNielsPoint;
|
use curve::AffineNielsPoint;
|
||||||
use curve::CompressedEdwardsY;
|
use curve::CompressedEdwardsY;
|
||||||
use curve::EdwardsBasepointTable;
|
use curve::EdwardsBasepointTable;
|
||||||
|
#[cfg(feature = "yolocrypto")]
|
||||||
|
use decaf::{DecafPoint, DecafBasepointTable};
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
|
||||||
#[cfg(feature="radix_51")]
|
#[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,
|
||||||
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.
|
/// Basepoint has y = 4/5.
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(not(feature="radix_51"))]
|
||||||
pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{
|
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)`.
|
/// 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`,
|
/// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`,
|
||||||
|
|
|
||||||
149
src/curve.rs
149
src/curve.rs
|
|
@ -79,7 +79,9 @@
|
||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::iter::Iterator;
|
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 constants;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
|
|
@ -90,11 +92,6 @@ use subtle::CTAssignable;
|
||||||
use subtle::CTEq;
|
use subtle::CTEq;
|
||||||
use subtle::CTNegatable;
|
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
|
// Compressed points
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -789,18 +786,20 @@ impl<'a> Neg for &'a AffineNielsPoint {
|
||||||
// Scalar multiplication
|
// Scalar multiplication
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Trait for scalar multiplication of an arbitrary point.
|
impl<'b> MulAssign<&'b Scalar> for ExtendedPoint {
|
||||||
pub trait ScalarMult<S> {
|
fn mul_assign(&mut self, scalar: &'b Scalar) {
|
||||||
/// Compute `scalar * self`.
|
let result = (self as &ExtendedPoint) * scalar;
|
||||||
fn scalar_mult(&self, scalar: &S) -> Self;
|
*self = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScalarMult<Scalar> for ExtendedPoint {
|
impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint {
|
||||||
|
type Output = ExtendedPoint;
|
||||||
/// Scalar multiplication: compute `scalar * self`.
|
/// Scalar multiplication: compute `scalar * self`.
|
||||||
///
|
///
|
||||||
/// Uses a window of size 4. Note: for scalar multiplication of
|
/// Uses a window of size 4. Note: for scalar multiplication of
|
||||||
/// the basepoint, `basepoint_mult` is approximately 4x faster.
|
/// 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 A = self.to_projective_niels();
|
||||||
let mut As: [ProjectiveNielsPoint; 8] = [A; 8];
|
let mut As: [ProjectiveNielsPoint; 8] = [A; 8];
|
||||||
for i in 0..7 {
|
for i in 0..7 {
|
||||||
|
|
@ -822,27 +821,8 @@ impl ScalarMult<Scalar> for ExtendedPoint {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]);
|
pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]);
|
||||||
|
|
||||||
impl EdwardsBasepointTable {
|
impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable {
|
||||||
/// Create a table of precomputed multiples of `basepoint`.
|
type Output = ExtendedPoint;
|
||||||
#[cfg(feature="basepoint_table_creation")]
|
|
||||||
pub fn create(basepoint: &ExtendedPoint) -> Box<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]);
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by
|
/// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by
|
||||||
/// computing the multiple `aB` of the basepoint `B`.
|
/// computing the multiple `aB` of the basepoint `B`.
|
||||||
|
|
@ -869,7 +849,7 @@ impl EdwardsBasepointTable {
|
||||||
/// We then use the `select_precomputed_point` function, which
|
/// We then use the `select_precomputed_point` function, which
|
||||||
/// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`,
|
/// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`,
|
||||||
/// and returns `x * 16^2i * B` in constant time.
|
/// 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 e = scalar.to_radix_16();
|
||||||
let mut h = ExtendedPoint::identity();
|
let mut h = ExtendedPoint::identity();
|
||||||
let mut t: CompletedPoint;
|
let mut t: CompletedPoint;
|
||||||
|
|
@ -890,21 +870,32 @@ impl EdwardsBasepointTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for scalar multiplication of a distinguished basepoint.
|
impl EdwardsBasepointTable {
|
||||||
pub trait BasepointMult<S> {
|
/// Create a table of precomputed multiples of `basepoint`.
|
||||||
/// Return the basepoint `B`.
|
pub fn create(basepoint: &ExtendedPoint) -> EdwardsBasepointTable {
|
||||||
fn basepoint() -> Self;
|
// Create the table storage
|
||||||
/// Compute `scalar * B`.
|
// XXX can we skip the initialization without too much unsafety?
|
||||||
fn basepoint_mult(scalar: &S) -> Self;
|
// stick 30K on the stack and call it a day.
|
||||||
}
|
let mut table = EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]);
|
||||||
|
let mut P = basepoint.clone();
|
||||||
impl BasepointMult<Scalar> for ExtendedPoint {
|
for i in 0..32 {
|
||||||
fn basepoint() -> ExtendedPoint {
|
// P = (16^2)^i * B
|
||||||
constants::ED25519_BASEPOINT
|
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);
|
||||||
|
}
|
||||||
|
table
|
||||||
}
|
}
|
||||||
|
|
||||||
fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint {
|
/// Get the basepoint for this table as an `ExtendedPoint`.
|
||||||
constants::ED25519_BASEPOINT_TABLE.basepoint_mult(scalar)
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1075,12 +1066,15 @@ pub mod vartime {
|
||||||
///
|
///
|
||||||
/// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an
|
/// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an
|
||||||
/// error to call this function with two vectors of different lengths.
|
/// error to call this function with two vectors of different lengths.
|
||||||
pub fn k_fold_scalar_mult(scalars: &Vec<Scalar>,
|
pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> ExtendedPoint
|
||||||
points: &Vec<ExtendedPoint>) -> ExtendedPoint {
|
where I: IntoIterator<Item=&'a Scalar>, J: IntoIterator<Item=&'b ExtendedPoint>
|
||||||
assert_eq!(scalars.len(), points.len());
|
{
|
||||||
|
//assert_eq!(scalars.len(), points.len());
|
||||||
|
|
||||||
let nafs: Vec<_> = scalars.iter().map(|c| c.non_adjacent_form()).collect();
|
let nafs: Vec<_> = scalars.into_iter()
|
||||||
let odd_multiples: Vec<_> = points.iter().map(|P| OddMultiples::create(&P)).collect();
|
.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();
|
let mut r = ProjectivePoint::identity();
|
||||||
|
|
||||||
|
|
@ -1282,11 +1276,18 @@ mod test {
|
||||||
/// Test that computing 1*basepoint gives the correct basepoint.
|
/// Test that computing 1*basepoint gives the correct basepoint.
|
||||||
#[test]
|
#[test]
|
||||||
fn basepoint_mult_one_vs_basepoint() {
|
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();
|
let compressed = bp.compress_edwards();
|
||||||
assert_eq!(compressed, constants::BASE_CMPRSSD);
|
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<ExtendedPoint> for ExtendedPoint`
|
/// Test `impl Add<ExtendedPoint> for ExtendedPoint`
|
||||||
/// using basepoint + basepoint versus the 2*basepoint constant.
|
/// using basepoint + basepoint versus the 2*basepoint constant.
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -1334,7 +1335,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn to_affine_niels_clears_denominators() {
|
fn to_affine_niels_clears_denominators() {
|
||||||
// construct a point as aB so it has denominators (ie. Z != 1)
|
// 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 aB_affine_niels = aB.to_affine_niels();
|
||||||
let also_aB = (&ExtendedPoint::identity() + &aB_affine_niels).to_extended();
|
let also_aB = (&ExtendedPoint::identity() + &aB_affine_niels).to_extended();
|
||||||
assert_eq!( aB.compress_edwards(),
|
assert_eq!( aB.compress_edwards(),
|
||||||
|
|
@ -1344,14 +1345,15 @@ mod test {
|
||||||
/// Test basepoint_mult versus a known scalar multiple from ed25519.py
|
/// Test basepoint_mult versus a known scalar multiple from ed25519.py
|
||||||
#[test]
|
#[test]
|
||||||
fn basepoint_mult_vs_ed25519py() {
|
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);
|
assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test that multiplication by the basepoint order kills the basepoint
|
/// Test that multiplication by the basepoint order kills the basepoint
|
||||||
#[test]
|
#[test]
|
||||||
fn basepoint_mult_by_basepoint_order() {
|
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());
|
assert!(should_be_id.is_identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1360,16 +1362,15 @@ mod test {
|
||||||
#[cfg(feature="basepoint_table_creation")]
|
#[cfg(feature="basepoint_table_creation")]
|
||||||
fn test_precomputed_basepoint_mult() {
|
fn test_precomputed_basepoint_mult() {
|
||||||
let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT);
|
let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT);
|
||||||
let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR);
|
let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR;
|
||||||
let aB_2 = table.basepoint_mult(&A_SCALAR);
|
let aB_2 = &table * &A_SCALAR;
|
||||||
assert_eq!(aB_1.compress_edwards(),
|
assert_eq!(aB_1.compress_edwards(), aB_2.compress_edwards());
|
||||||
aB_2.compress_edwards());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test scalar_mult versus a known scalar multiple from ed25519.py
|
/// Test scalar_mult versus a known scalar multiple from ed25519.py
|
||||||
#[test]
|
#[test]
|
||||||
fn scalar_mult_vs_ed25519py() {
|
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);
|
assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1384,7 +1385,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn basepoint_mult_two_vs_basepoint2() {
|
fn basepoint_mult_two_vs_basepoint2() {
|
||||||
let mut two_bytes = [0u8; 32]; two_bytes[0] = 2;
|
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);
|
assert_eq!(bp2.compress_edwards(), BASE2_CMPRSSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1450,11 +1451,11 @@ mod test {
|
||||||
/// the type system and prove correctness).
|
/// the type system and prove correctness).
|
||||||
#[test]
|
#[test]
|
||||||
fn monte_carlo_overflow_underflow_debug_assert_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,
|
// N.B. each scalar_mult does 1407 field mults, 1024 field squarings,
|
||||||
// so this does ~ 1M of each operation.
|
// so this does ~ 1M of each operation.
|
||||||
for _ in 0..1_000 {
|
for _ in 0..1_000 {
|
||||||
P = P.scalar_mult(&A_SCALAR);
|
P *= &A_SCALAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1473,9 +1474,10 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn k_fold_scalar_mult_vs_ed25519py() {
|
fn k_fold_scalar_mult_vs_ed25519py() {
|
||||||
let A = A_TIMES_BASEPOINT.decompress().unwrap();
|
let A = A_TIMES_BASEPOINT.decompress().unwrap();
|
||||||
let points = vec![A,constants::ED25519_BASEPOINT];
|
let result = vartime::k_fold_scalar_mult(
|
||||||
let scalars = vec![A_SCALAR, B_SCALAR];
|
&[A_SCALAR, B_SCALAR],
|
||||||
let result = vartime::k_fold_scalar_mult(&scalars, &points);
|
&[A, constants::ED25519_BASEPOINT]
|
||||||
|
);
|
||||||
assert_eq!(result.compress_edwards(), DOUBLE_SCALAR_MULT_RESULT);
|
assert_eq!(result.compress_edwards(), DOUBLE_SCALAR_MULT_RESULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1495,13 +1497,14 @@ mod bench {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn basepoint_mult(b: &mut Bencher) {
|
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]
|
#[bench]
|
||||||
fn scalar_mult(b: &mut Bencher) {
|
fn scalar_mult(b: &mut Bencher) {
|
||||||
let bp = constants::ED25519_BASEPOINT;
|
let B = &constants::ED25519_BASEPOINT;
|
||||||
b.iter(|| bp.scalar_mult(&A_SCALAR));
|
b.iter(|| B * &A_SCALAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
|
@ -1565,7 +1568,7 @@ mod bench {
|
||||||
#[cfg(feature="basepoint_table_creation")]
|
#[cfg(feature="basepoint_table_creation")]
|
||||||
#[bench]
|
#[bench]
|
||||||
fn create_basepoint_table(b: &mut Bencher) {
|
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));
|
b.iter(|| EdwardsBasepointTable::create(&aB));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1586,8 +1589,8 @@ mod bench {
|
||||||
// Create 10 random scalars
|
// Create 10 random scalars
|
||||||
let scalars: Vec<_> = (0..10).map(|_| Scalar::random(&mut csprng)).collect();
|
let scalars: Vec<_> = (0..10).map(|_| Scalar::random(&mut csprng)).collect();
|
||||||
// Create 10 points (by doing scalar mults)
|
// Create 10 points (by doing scalar mults)
|
||||||
let points: Vec<_> = scalars.iter()
|
let B = &constants::ED25519_BASEPOINT_TABLE;
|
||||||
.map(|s| ExtendedPoint::basepoint_mult(s)).collect();
|
let points: Vec<_> = scalars.iter().map(|s| B * &s).collect();
|
||||||
|
|
||||||
// XXX Currently Rust's benchmarking implementation doesn't
|
// XXX Currently Rust's benchmarking implementation doesn't
|
||||||
// allow you to specify a sequence of random inputs, but only
|
// allow you to specify a sequence of random inputs, but only
|
||||||
|
|
|
||||||
99
src/decaf.rs
99
src/decaf.rs
|
|
@ -30,17 +30,11 @@ use subtle::CTAssignable;
|
||||||
use subtle::CTNegatable;
|
use subtle::CTNegatable;
|
||||||
|
|
||||||
use core::ops::{Add, Sub, Neg};
|
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;
|
||||||
use curve::ExtendedPoint;
|
use curve::ExtendedPoint;
|
||||||
use curve::EdwardsBasepointTable;
|
use curve::EdwardsBasepointTable;
|
||||||
use curve::BasepointMult;
|
|
||||||
use curve::ScalarMult;
|
|
||||||
use curve::Identity;
|
use curve::Identity;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
|
||||||
|
|
@ -250,40 +244,42 @@ impl<'a> Neg for &'a DecafPoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScalarMult<Scalar> for DecafPoint {
|
impl<'b> MulAssign<&'b Scalar> for DecafPoint {
|
||||||
fn scalar_mult(&self, scalar: &Scalar) -> DecafPoint {
|
fn mul_assign(&mut self, scalar: &'b Scalar) {
|
||||||
DecafPoint(self.0.scalar_mult(scalar))
|
let result = (self as &DecafPoint) * scalar;
|
||||||
|
*self = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasepointMult<Scalar> for DecafPoint {
|
impl<'a, 'b> Mul<&'b Scalar> for &'a DecafPoint {
|
||||||
// XXX is this actually in the image of the isogeny,
|
type Output = DecafPoint;
|
||||||
// or do we need a different basepoint?
|
/// Scalar multiplication: compute `scalar * self`.
|
||||||
fn basepoint() -> DecafPoint {
|
fn mul(self, scalar: &'b Scalar) -> DecafPoint {
|
||||||
DecafPoint(ExtendedPoint::basepoint())
|
DecafPoint(&self.0 * scalar)
|
||||||
}
|
|
||||||
|
|
||||||
fn basepoint_mult(scalar: &Scalar) -> DecafPoint {
|
|
||||||
DecafPoint(ExtendedPoint::basepoint_mult(scalar))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Precomputation
|
/// Precomputation
|
||||||
#[derive(Clone)]
|
#[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 {
|
impl DecafBasepointTable {
|
||||||
/// Create a precomputed table of multiples of the given `basepoint`.
|
/// Create a precomputed table of multiples of the given `basepoint`.
|
||||||
#[cfg(feature = "basepoint_table_creation")]
|
pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable {
|
||||||
pub fn create(basepoint: &DecafPoint) -> Box<DecafBasepointTable> {
|
DecafBasepointTable(EdwardsBasepointTable::create(&basepoint.0))
|
||||||
let edwards_table = EdwardsBasepointTable::create(&basepoint.0);
|
|
||||||
box DecafBasepointTable(*edwards_table)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use the precomputed table to quickly compute `scalar * basepoint`
|
/// Get the basepoint for this table as a `DecafPoint`.
|
||||||
pub fn basepoint_mult(&self, scalar: &Scalar) -> DecafPoint {
|
pub fn basepoint(&self) -> DecafPoint {
|
||||||
DecafPoint(self.0.basepoint_mult(scalar))
|
DecafPoint(self.0.basepoint())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,10 +318,11 @@ pub mod vartime {
|
||||||
///
|
///
|
||||||
/// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an
|
/// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an
|
||||||
/// error to call this function with two vectors of different lengths.
|
/// error to call this function with two vectors of different lengths.
|
||||||
pub fn k_fold_scalar_mult(scalars: &Vec<Scalar>,
|
pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> DecafPoint
|
||||||
points: &Vec<DecafPoint>) -> DecafPoint {
|
where I: IntoIterator<Item=&'a Scalar>, J: IntoIterator<Item=&'b DecafPoint>
|
||||||
let extended_points: Vec<ExtendedPoint> = points.iter().map(|P| P.0).collect();
|
{
|
||||||
DecafPoint(curve::vartime::k_fold_scalar_mult(scalars, &extended_points))
|
let extended_points = points.into_iter().map(|P| &P.0);
|
||||||
|
DecafPoint(curve::vartime::k_fold_scalar_mult(scalars, extended_points))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +338,6 @@ mod test {
|
||||||
use constants;
|
use constants;
|
||||||
use curve::CompressedEdwardsY;
|
use curve::CompressedEdwardsY;
|
||||||
use curve::ExtendedPoint;
|
use curve::ExtendedPoint;
|
||||||
use curve::BasepointMult;
|
|
||||||
use curve::Identity;
|
use curve::Identity;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -367,17 +363,17 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decaf_basepoint_roundtrip() {
|
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;
|
let bp_recaf = bp_compressed_decaf.decompress().unwrap().0;
|
||||||
// Check that bp_recaf differs from bp by a point of order 4
|
// Check that bp_recaf differs from bp by a point of order 4
|
||||||
let diff = &ExtendedPoint::basepoint() - &bp_recaf;
|
let diff = &constants::ED25519_BASEPOINT - &bp_recaf;
|
||||||
let diff4 = diff.mult_by_pow_2(4);
|
let diff4 = diff.mult_by_pow_2(4); // XXX this is wrong
|
||||||
assert_eq!(diff4.compress_edwards(), CompressedEdwardsY::identity());
|
assert_eq!(diff4.compress_edwards(), CompressedEdwardsY::identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decaf_four_torsion_basepoint() {
|
fn decaf_four_torsion_basepoint() {
|
||||||
let bp = DecafPoint::basepoint();
|
let bp = constants::DECAF_ED25519_BASEPOINT;
|
||||||
let bp_coset = bp.coset4();
|
let bp_coset = bp.coset4();
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
assert_eq!(bp, DecafPoint(bp_coset[i]));
|
assert_eq!(bp, DecafPoint(bp_coset[i]));
|
||||||
|
|
@ -387,8 +383,8 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn decaf_four_torsion_random() {
|
fn decaf_four_torsion_random() {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
let s = Scalar::random(&mut rng);
|
let B = &constants::DECAF_ED25519_BASEPOINT_TABLE;
|
||||||
let P = DecafPoint::basepoint_mult(&s);
|
let P = B * &Scalar::random(&mut rng);
|
||||||
let P_coset = P.coset4();
|
let P_coset = P.coset4();
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
assert_eq!(P, DecafPoint(P_coset[i]));
|
assert_eq!(P, DecafPoint(P_coset[i]));
|
||||||
|
|
@ -398,27 +394,14 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn decaf_random_roundtrip() {
|
fn decaf_random_roundtrip() {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
|
let B = &constants::DECAF_ED25519_BASEPOINT_TABLE;
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
let s = Scalar::random(&mut rng);
|
let P = B * &Scalar::random(&mut rng);
|
||||||
let P = DecafPoint::basepoint_mult(&s);
|
|
||||||
let compressed_P = P.compress();
|
let compressed_P = P.compress();
|
||||||
let Q = compressed_P.decompress().unwrap();
|
let Q = compressed_P.decompress().unwrap();
|
||||||
assert_eq!(P, Q);
|
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"))]
|
#[cfg(all(test, feature = "bench"))]
|
||||||
|
|
@ -431,8 +414,8 @@ mod bench {
|
||||||
#[bench]
|
#[bench]
|
||||||
fn decompression(b: &mut Bencher) {
|
fn decompression(b: &mut Bencher) {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
let s = Scalar::random(&mut rng);
|
let B = &constants::DECAF_ED25519_BASEPOINT_TABLE;
|
||||||
let P = DecafPoint::basepoint_mult(&s);
|
let P = B * &Scalar::random(&mut rng);
|
||||||
let P_compressed = P.compress();
|
let P_compressed = P.compress();
|
||||||
b.iter(|| P_compressed.decompress().unwrap());
|
b.iter(|| P_compressed.decompress().unwrap());
|
||||||
}
|
}
|
||||||
|
|
@ -440,8 +423,8 @@ mod bench {
|
||||||
#[bench]
|
#[bench]
|
||||||
fn compression(b: &mut Bencher) {
|
fn compression(b: &mut Bencher) {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
let s = Scalar::random(&mut rng);
|
let B = &constants::DECAF_ED25519_BASEPOINT_TABLE;
|
||||||
let P = DecafPoint::basepoint_mult(&s);
|
let P = B * &Scalar::random(&mut rng);
|
||||||
b.iter(|| P.compress());
|
b.iter(|| P.compress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@
|
||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![cfg_attr(not(feature = "std"), feature(collections))]
|
#![cfg_attr(not(feature = "std"), feature(collections))]
|
||||||
#![cfg_attr(feature = "nightly", feature(box_syntax))]
|
|
||||||
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
||||||
#![allow(unused_features)]
|
|
||||||
#![cfg_attr(feature = "bench", feature(test))]
|
#![cfg_attr(feature = "bench", feature(test))]
|
||||||
|
|
||||||
|
#![allow(unused_features)]
|
||||||
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
||||||
|
|
||||||
//! # curve25519-dalek
|
//! # curve25519-dalek
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,15 @@ impl Scalar {
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
|
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.
|
/// Compute the multiplicative inverse of this scalar.
|
||||||
pub fn invert(&self) -> Scalar {
|
pub fn invert(&self) -> Scalar {
|
||||||
self.unpack().invert().pack()
|
self.unpack().invert().pack()
|
||||||
|
|
@ -727,6 +736,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]
|
#[test]
|
||||||
fn scalar_multiply_by_one() {
|
fn scalar_multiply_by_one() {
|
||||||
let one = Scalar::one();
|
let one = Scalar::one();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue