mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-09 21:10:44 +00:00
Merge branch 'feature/9-vxeddsa-functionality_r2' into develop
This commit is contained in:
commit
aad1d1751a
5 changed files with 181 additions and 7 deletions
|
|
@ -21,6 +21,7 @@
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use curve::PreComputedPoint;
|
use curve::PreComputedPoint;
|
||||||
use curve::CompressedEdwardsY;
|
use curve::CompressedEdwardsY;
|
||||||
|
use scalar::Scalar;
|
||||||
|
|
||||||
pub const d: FieldElement = FieldElement([
|
pub const d: FieldElement = FieldElement([
|
||||||
-10913610, 13857413, -15372611, 6949391, 114729,
|
-10913610, 13857413, -15372611, 6949391, 114729,
|
||||||
|
|
@ -66,6 +67,20 @@ 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]);
|
||||||
|
|
||||||
|
/// `l` is the order of base point, i.e. 2^252 +
|
||||||
|
/// 27742317777372353535851937790883648493, in little-endian form
|
||||||
|
pub const l: Scalar = Scalar([ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
||||||
|
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]);
|
||||||
|
|
||||||
|
/// `lminus1` is the order of base point minus one, i.e. 2^252 +
|
||||||
|
/// 27742317777372353535851937790883648493 - 1, in little-endian form
|
||||||
|
pub const lminus1: Scalar = Scalar([ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
||||||
|
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]);
|
||||||
|
|
||||||
pub const bi: [PreComputedPoint; 8] = [
|
pub const bi: [PreComputedPoint; 8] = [
|
||||||
PreComputedPoint{
|
PreComputedPoint{
|
||||||
y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]),
|
y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]),
|
||||||
|
|
|
||||||
82
src/curve.rs
82
src/curve.rs
|
|
@ -85,8 +85,10 @@ use core::cmp::{PartialEq, Eq};
|
||||||
use constants;
|
use constants;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
use util::arrays_equal_ct;
|
||||||
use util::bytes_equal_ct;
|
use util::bytes_equal_ct;
|
||||||
use util::CTAssignable;
|
use util::CTAssignable;
|
||||||
|
use util::CTEq;
|
||||||
use util::CTNegatable;
|
use util::CTNegatable;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -227,7 +229,7 @@ pub struct CachedPoint {
|
||||||
// Constructors
|
// Constructors
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Trait for curve point types that have an identity constructor.
|
/// Trait for curve point types which have an identity constructor.
|
||||||
pub trait Identity {
|
pub trait Identity {
|
||||||
/// Returns the identity element of the curve.
|
/// Returns the identity element of the curve.
|
||||||
/// Can be used as a constructor.
|
/// Can be used as a constructor.
|
||||||
|
|
@ -292,6 +294,37 @@ impl CTAssignable for PreComputedPoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Constant-time Equality
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
impl CTEq for ExtendedPoint {
|
||||||
|
fn ct_eq(&self, other: &ExtendedPoint) -> u8 {
|
||||||
|
arrays_equal_ct(&self.compress().0, &other.compress().0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for testing if a curve point is equivalent to the identity point.
|
||||||
|
pub trait IsIdentity {
|
||||||
|
/// Return true if this element is the identity element of the curve.
|
||||||
|
fn is_identity(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement generic identity equality testing for a point representations
|
||||||
|
/// which have constant-time equality testing and a defined identity
|
||||||
|
/// constructor.
|
||||||
|
impl<T> IsIdentity for T where T: CTEq + Identity {
|
||||||
|
fn is_identity(&self) -> bool {
|
||||||
|
let identity: T = T::identity();
|
||||||
|
|
||||||
|
if self.ct_eq(&identity) == 1u8 {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Point conversions
|
// Point conversions
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -655,6 +688,25 @@ impl ExtendedPoint {
|
||||||
r = s.double();
|
r = s.double();
|
||||||
return r.to_extended();
|
return r.to_extended();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if this point is of small order.
|
||||||
|
///
|
||||||
|
/// The order of the group of points on the curve Ɛ is |Ɛ| = 8q. Thus, to
|
||||||
|
/// check if a point P is of small order, we multiply by 8 and then test
|
||||||
|
/// if the result is equal to the identity.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
///
|
||||||
|
/// True if it is of small order; false otherwise.
|
||||||
|
pub fn is_small_order(&self) -> bool {
|
||||||
|
let p8: ExtendedPoint = self.mult_by_pow_2(3);
|
||||||
|
|
||||||
|
if p8.is_identity() {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a point `A` and scalars `a` and `b`, compute the point
|
/// Given a point `A` and scalars `a` and `b`, compute the point
|
||||||
|
|
@ -934,6 +986,20 @@ mod test {
|
||||||
assert_eq!( bp_added.compress(), BASE2_CMPRSSD);
|
assert_eq!( bp_added.compress(), BASE2_CMPRSSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extended_point_equality() {
|
||||||
|
let two = [2, 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 ];
|
||||||
|
let id1 = ExtendedPoint::identity();
|
||||||
|
let id2 = ExtendedPoint{
|
||||||
|
X: FieldElement::zero(),
|
||||||
|
Y: FieldElement::from_bytes(&two),
|
||||||
|
Z: FieldElement::from_bytes(&two),
|
||||||
|
T: FieldElement::zero()};
|
||||||
|
|
||||||
|
assert!(id1.ct_eq(&id2) == 1u8);
|
||||||
|
}
|
||||||
|
|
||||||
/// Sanity check for conversion to precomputed points
|
/// Sanity check for conversion to precomputed points
|
||||||
#[test]
|
#[test]
|
||||||
fn test_convert_to_precomputed() {
|
fn test_convert_to_precomputed() {
|
||||||
|
|
@ -1045,6 +1111,20 @@ mod test {
|
||||||
assert_eq!(p1.xy2d, p2.xy2d);
|
assert_eq!(p1.xy2d, p2.xy2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_small_order() {
|
||||||
|
let p1: ExtendedPoint = ExtendedPoint::identity();
|
||||||
|
let p2: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap();
|
||||||
|
|
||||||
|
assert!(p1.is_small_order() == true);
|
||||||
|
assert!(p2.is_small_order() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_identity() {
|
||||||
|
assert!(ExtendedPoint::identity().is_identity());
|
||||||
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_basepoint_mult(b: &mut Bencher) {
|
fn bench_basepoint_mult(b: &mut Bencher) {
|
||||||
b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR));
|
b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR));
|
||||||
|
|
|
||||||
22
src/field.rs
22
src/field.rs
|
|
@ -24,8 +24,10 @@ use core::ops::{Index, IndexMut};
|
||||||
use core::cmp::{Eq, PartialEq};
|
use core::cmp::{Eq, PartialEq};
|
||||||
use core::ops::Neg;
|
use core::ops::Neg;
|
||||||
|
|
||||||
|
use util::arrays_equal_ct;
|
||||||
use util::byte_is_nonzero;
|
use util::byte_is_nonzero;
|
||||||
use util::CTAssignable;
|
use util::CTAssignable;
|
||||||
|
use util::CTEq;
|
||||||
|
|
||||||
/// FieldElements are represented as an array of ten "Limbs", which are radix
|
/// FieldElements are represented as an array of ten "Limbs", which are radix
|
||||||
/// 25.5, that is, each Limb of a FieldElement alternates between being
|
/// 25.5, that is, each Limb of a FieldElement alternates between being
|
||||||
|
|
@ -40,6 +42,7 @@ pub type Limb = i32;
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct FieldElement(pub [Limb; 10]);
|
pub struct FieldElement(pub [Limb; 10]);
|
||||||
|
|
||||||
|
impl Eq for FieldElement {}
|
||||||
impl PartialEq for FieldElement {
|
impl PartialEq for FieldElement {
|
||||||
/// Test equality between two FieldElements by converting them to bytes.
|
/// Test equality between two FieldElements by converting them to bytes.
|
||||||
///
|
///
|
||||||
|
|
@ -48,10 +51,10 @@ impl PartialEq for FieldElement {
|
||||||
/// This comparison is *not* constant time. It could easily be
|
/// This comparison is *not* constant time. It could easily be
|
||||||
/// made to be, but the main use of an `Eq` implementation is for
|
/// made to be, but the main use of an `Eq` implementation is for
|
||||||
/// branching, so it seems pointless.
|
/// branching, so it seems pointless.
|
||||||
///
|
//
|
||||||
/// XXX it would be good to encode constant-time considerations
|
// XXX it would be good to encode constant-time considerations
|
||||||
/// (no data flow from secret information) into Rust's type
|
// (no data flow from secret information) into Rust's type
|
||||||
/// system.
|
// system.
|
||||||
fn eq(&self, other: &FieldElement) -> bool {
|
fn eq(&self, other: &FieldElement) -> bool {
|
||||||
let self_bytes = self.to_bytes();
|
let self_bytes = self.to_bytes();
|
||||||
let other_bytes = other.to_bytes();
|
let other_bytes = other.to_bytes();
|
||||||
|
|
@ -63,7 +66,16 @@ impl PartialEq for FieldElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for FieldElement {}
|
impl CTEq for FieldElement {
|
||||||
|
/// Test equality between two `FieldElement`s by converting them to bytes.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// `1u8` if the two `FieldElement`s are equal, and `0u8` otherwise.
|
||||||
|
fn ct_eq(&self, other: &FieldElement) -> u8 {
|
||||||
|
arrays_equal_ct(&self.to_bytes(), &other.to_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for FieldElement {
|
impl Debug for FieldElement {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,19 @@
|
||||||
//! between two scalars, the `UnpackedScalar` struct is stored as
|
//! between two scalars, the `UnpackedScalar` struct is stored as
|
||||||
//! limbs.
|
//! limbs.
|
||||||
|
|
||||||
|
use core::cmp::{Eq, PartialEq};
|
||||||
use core::ops::{Index, IndexMut};
|
use core::ops::{Index, IndexMut};
|
||||||
|
use core::ops::{Neg};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
// XXX should these be in a utility module ?
|
// XXX should these be in a utility module ?
|
||||||
|
use constants;
|
||||||
use field::{load3, load4};
|
use field::{load3, load4};
|
||||||
use util::CTAssignable;
|
use util::CTAssignable;
|
||||||
|
use util::CTEq;
|
||||||
|
use util::arrays_equal_ct;
|
||||||
|
|
||||||
/// The `Scalar` struct represents an element in ℤ/lℤ, where
|
/// The `Scalar` struct represents an element in ℤ/lℤ, where
|
||||||
///
|
///
|
||||||
|
|
@ -46,6 +51,40 @@ use util::CTAssignable;
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Scalar(pub [u8; 32]);
|
pub struct Scalar(pub [u8; 32]);
|
||||||
|
|
||||||
|
impl Eq for Scalar{}
|
||||||
|
impl PartialEq for Scalar {
|
||||||
|
/// Test equality between two `Scalar`s.
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// This function is *not* guaranteed to be constant time and should only be
|
||||||
|
/// used for debugging purposes.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// True if they are equal, and false otherwise.
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
let equal: u8 = arrays_equal_ct(&self.0, &other.0);
|
||||||
|
|
||||||
|
if equal == 1u8 {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CTEq for Scalar {
|
||||||
|
/// Test equality between two `Scalar`s in constant time.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// `1u8` if they are equal, and `0u8` otherwise.
|
||||||
|
fn ct_eq(&self, other: &Self) -> u8 {
|
||||||
|
arrays_equal_ct(&self.0, &other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Index<usize> for Scalar {
|
impl Index<usize> for Scalar {
|
||||||
type Output = u8;
|
type Output = u8;
|
||||||
|
|
||||||
|
|
@ -62,6 +101,15 @@ impl IndexMut<usize> for Scalar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for Scalar {
|
||||||
|
type Output = Scalar;
|
||||||
|
|
||||||
|
/// Negate this scalar by computing (l - 1) * self - 0 (mod l).
|
||||||
|
fn neg(self) -> Scalar {
|
||||||
|
Scalar::multiply_add(&constants::lminus1, &self, &Scalar::zero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CTAssignable for Scalar {
|
impl CTAssignable for Scalar {
|
||||||
/// Conditionally assign another Scalar to this one.
|
/// Conditionally assign another Scalar to this one.
|
||||||
///
|
///
|
||||||
|
|
@ -627,4 +675,13 @@ mod test {
|
||||||
assert!(test_red[i] == reduced[i]);
|
assert!(test_red[i] == reduced[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Negating a scalar twice should result in the original scalar.
|
||||||
|
#[test]
|
||||||
|
fn test_scalar_neg() {
|
||||||
|
let negative_x: Scalar = -X;
|
||||||
|
let orig: Scalar = -negative_x;
|
||||||
|
|
||||||
|
assert!(orig == X);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/util.rs
12
src/util.rs
|
|
@ -21,7 +21,17 @@ pub trait CTAssignable {
|
||||||
fn conditional_assign(&mut self, other: &Self, choice: u8);
|
fn conditional_assign(&mut self, other: &Self, choice: u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for items which can be conditionally negated in constant time.
|
/// Trait for items whose equality to another item may be tested in constant time.
|
||||||
|
pub trait CTEq {
|
||||||
|
/// Determine if two items are equal in constant time.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// `1u8` if the two items are equal, and `0u8` otherwise.
|
||||||
|
fn ct_eq(&self, other: &Self) -> u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trait for items which can be conditionally negated in constant time.
|
||||||
///
|
///
|
||||||
/// Note: it is not necessary to implement this trait, as a generic
|
/// Note: it is not necessary to implement this trait, as a generic
|
||||||
/// implementation is provided.
|
/// implementation is provided.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue