mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-04 20:24:10 +00:00
Merge branch 'release/0.4.0'
This commit is contained in:
commit
d0bc40783b
9 changed files with 274 additions and 64 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "curve25519-dalek"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"Henry de Valence <hdevalence@hdevalence.ca>"]
|
||||
readme = "README.md"
|
||||
|
|
@ -8,6 +8,7 @@ license = "CC0-1.0"
|
|||
repository = "https://code.ciph.re/isis/curve25519-dalek"
|
||||
homepage = "https://code.ciph.re/isis/curve25519-dalek"
|
||||
documentation = "https://docs.rs/curve25519-dalek"
|
||||
categories = ["cryptography", "no-std"]
|
||||
keywords = ["cryptography", "curve25519", "elliptic", "curve", "ECC"]
|
||||
description = "A low-level cryptographic library for point, group, field, and scalar operations on a curve isomorphic to the twisted Edwards curve defined by -x²+y² = 1 - 121665/121666 x²y² over GF(2²⁵⁵ - 19)."
|
||||
exclude = [
|
||||
|
|
@ -34,7 +35,7 @@ lto = false # controls `-C lto` for binaries and staticlibs
|
|||
debug-assertions = true # controls whether debug assertions are enabled
|
||||
codegen-units = 1 # controls whether the compiler passes `-C codegen-units`
|
||||
# `codegen-units` is ignored when `lto = true`
|
||||
panic = 'unwind' # panic strategy (`-C panic=...`), can also be 'abort'
|
||||
panic = 'unwind' # panic strategy (`-C panic=...`), can also be 'abort'
|
||||
|
||||
# The release profile, used for `cargo build --release`.
|
||||
[profile.release]
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ Extensive documentation is available [here](https://docs.rs/curve25519-dalek).
|
|||
To install, add the following to the dependencies section of your project's
|
||||
`Cargo.toml`:
|
||||
|
||||
curve25519-dalek = "^0.2"
|
||||
curve25519-dalek = "^0.4"
|
||||
|
||||
Then, in your library or executable source, add:
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
use field::FieldElement;
|
||||
use curve::PreComputedPoint;
|
||||
use curve::CompressedEdwardsY;
|
||||
use scalar::Scalar;
|
||||
|
||||
pub const d: FieldElement = FieldElement([
|
||||
-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]);
|
||||
|
||||
/// `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] = [
|
||||
PreComputedPoint{
|
||||
y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]),
|
||||
|
|
|
|||
107
src/curve.rs
107
src/curve.rs
|
|
@ -80,13 +80,15 @@
|
|||
use core::fmt::Debug;
|
||||
use core::iter::Iterator;
|
||||
use core::ops::{Add, Sub, Neg, Index};
|
||||
use core::cmp::{PartialEq, Eq};
|
||||
|
||||
use constants;
|
||||
use field::FieldElement;
|
||||
use scalar::Scalar;
|
||||
use util::bytes_equal_ct;
|
||||
use util::CTAssignable;
|
||||
use subtle::arrays_equal_ct;
|
||||
use subtle::bytes_equal_ct;
|
||||
use subtle::CTAssignable;
|
||||
use subtle::CTEq;
|
||||
use subtle::CTNegatable;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Compressed points
|
||||
|
|
@ -98,7 +100,7 @@ use util::CTAssignable;
|
|||
///
|
||||
/// The first 255 bits of a CompressedEdwardsY represent the
|
||||
/// y-coordinate. The high bit of the 32nd byte gives the sign of `x`.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct CompressedEdwardsY(pub [u8; 32]);
|
||||
|
||||
impl Debug for CompressedEdwardsY {
|
||||
|
|
@ -107,18 +109,6 @@ impl Debug for CompressedEdwardsY {
|
|||
}
|
||||
}
|
||||
|
||||
impl Eq for CompressedEdwardsY {}
|
||||
impl PartialEq for CompressedEdwardsY {
|
||||
/// Determine if this `CompressedEdwardsY` is equal to another.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// This function is NOT constant time.
|
||||
fn eq(&self, other: &CompressedEdwardsY) -> bool {
|
||||
return self.0 == other.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for CompressedEdwardsY {
|
||||
type Output = u8;
|
||||
|
||||
|
|
@ -238,7 +228,7 @@ pub struct CachedPoint {
|
|||
// Constructors
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/// Trait for curve point types that have an identity constructor.
|
||||
/// Trait for curve point types which have an identity constructor.
|
||||
pub trait Identity {
|
||||
/// Returns the identity element of the curve.
|
||||
/// Can be used as a constructor.
|
||||
|
|
@ -303,6 +293,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
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
@ -666,6 +687,25 @@ impl ExtendedPoint {
|
|||
r = s.double();
|
||||
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
|
||||
|
|
@ -746,9 +786,8 @@ fn select_precomputed_point<T>(x: i8, points: &[T; 8]) -> T
|
|||
}
|
||||
// Now t == |x| * P.
|
||||
|
||||
let minus_t = -(&t);
|
||||
let neg_mask = (xmask & 1) as u8;
|
||||
t.conditional_assign(&minus_t, neg_mask);
|
||||
t.conditional_negate(neg_mask);
|
||||
// Now t == x * P.
|
||||
|
||||
t
|
||||
|
|
@ -825,7 +864,7 @@ mod test {
|
|||
use test::Bencher;
|
||||
use field::FieldElement;
|
||||
use scalar::Scalar;
|
||||
use util::CTAssignable;
|
||||
use subtle::CTAssignable;
|
||||
use constants;
|
||||
use constants::BASE_CMPRSSD;
|
||||
use super::*;
|
||||
|
|
@ -946,6 +985,20 @@ mod test {
|
|||
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
|
||||
#[test]
|
||||
fn test_convert_to_precomputed() {
|
||||
|
|
@ -1057,6 +1110,20 @@ mod test {
|
|||
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]
|
||||
fn bench_basepoint_mult(b: &mut Bencher) {
|
||||
b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR));
|
||||
|
|
|
|||
67
src/field.rs
67
src/field.rs
|
|
@ -24,8 +24,12 @@ use core::ops::{Index, IndexMut};
|
|||
use core::cmp::{Eq, PartialEq};
|
||||
use core::ops::Neg;
|
||||
|
||||
use util::byte_is_nonzero;
|
||||
use util::CTAssignable;
|
||||
use subtle::arrays_equal_ct;
|
||||
use subtle::byte_is_nonzero;
|
||||
use subtle::CTAssignable;
|
||||
use subtle::CTEq;
|
||||
|
||||
use utils::{load3, load4};
|
||||
|
||||
/// FieldElements are represented as an array of ten "Limbs", which are radix
|
||||
/// 25.5, that is, each Limb of a FieldElement alternates between being
|
||||
|
|
@ -40,6 +44,7 @@ pub type Limb = i32;
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct FieldElement(pub [Limb; 10]);
|
||||
|
||||
impl Eq for FieldElement {}
|
||||
impl PartialEq for FieldElement {
|
||||
/// Test equality between two FieldElements by converting them to bytes.
|
||||
///
|
||||
|
|
@ -48,10 +53,10 @@ impl PartialEq for FieldElement {
|
|||
/// This comparison is *not* constant time. It could easily be
|
||||
/// made to be, but the main use of an `Eq` implementation is for
|
||||
/// branching, so it seems pointless.
|
||||
///
|
||||
/// XXX it would be good to encode constant-time considerations
|
||||
/// (no data flow from secret information) into Rust's type
|
||||
/// system.
|
||||
//
|
||||
// XXX it would be good to encode constant-time considerations
|
||||
// (no data flow from secret information) into Rust's type
|
||||
// system.
|
||||
fn eq(&self, other: &FieldElement) -> bool {
|
||||
let self_bytes = self.to_bytes();
|
||||
let other_bytes = other.to_bytes();
|
||||
|
|
@ -63,7 +68,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 {
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
|
|
@ -150,7 +164,7 @@ impl CTAssignable for FieldElement {
|
|||
///
|
||||
/// ```
|
||||
/// # use curve25519_dalek::field::FieldElement;
|
||||
/// # use curve25519_dalek::util::CTAssignable;
|
||||
/// # use curve25519_dalek::subtle::CTAssignable;
|
||||
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
||||
/// let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||
|
|
@ -162,7 +176,7 @@ impl CTAssignable for FieldElement {
|
|||
///
|
||||
/// ```
|
||||
/// # use curve25519_dalek::field::FieldElement;
|
||||
/// # use curve25519_dalek::util::CTAssignable;
|
||||
/// # use curve25519_dalek::subtle::CTAssignable;
|
||||
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
||||
/// # let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||
|
|
@ -181,25 +195,6 @@ impl CTAssignable for FieldElement {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert an array of (at least) three bytes into an i64.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn load3(input: &[u8]) -> i64 {
|
||||
(input[0] as i64)
|
||||
| ((input[1] as i64) << 8)
|
||||
| ((input[2] as i64) << 16)
|
||||
}
|
||||
|
||||
/// Convert an array of (at least) four bytes into an i64.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn load4(input: &[u8]) -> i64 {
|
||||
(input[0] as i64)
|
||||
| ((input[1] as i64) << 8)
|
||||
| ((input[2] as i64) << 16)
|
||||
| ((input[3] as i64) << 24)
|
||||
}
|
||||
|
||||
impl FieldElement {
|
||||
/// Invert the sign of this field element
|
||||
pub fn negate(&mut self) {
|
||||
|
|
@ -711,7 +706,7 @@ impl FieldElement {
|
|||
/// XXX This returns an extra intermediate to save computation in
|
||||
/// finding inverses, at the cost of an extra copy when it's not
|
||||
/// used (e.g., when raising to (p-1)/2 or (p-5)/8). Good idea?
|
||||
fn pow22501(&self) -> (FieldElement,FieldElement) {
|
||||
fn pow22501(&self) -> (FieldElement, FieldElement) {
|
||||
// Instead of managing which temporary variables are used
|
||||
// for what, we define as many as we need and trust the
|
||||
// compiler to reuse stack space as appropriate.
|
||||
|
|
@ -803,6 +798,7 @@ impl FieldElement {
|
|||
mod test {
|
||||
use field::*;
|
||||
use test::Bencher;
|
||||
use subtle::CTNegatable;
|
||||
|
||||
#[bench]
|
||||
fn bench_fieldelement_a_mul_a(b: &mut Bencher) {
|
||||
|
|
@ -932,4 +928,17 @@ mod test {
|
|||
// high bit is set to zero in to_bytes
|
||||
assert!(test_bytes[31] == (B_BYTES[31] & 127u8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conditional_negate() {
|
||||
let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]);
|
||||
let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]);
|
||||
let mut x = one;
|
||||
x.conditional_negate(1u8);
|
||||
assert_eq!(x, minus_one);
|
||||
x.conditional_negate(0u8);
|
||||
assert_eq!(x, minus_one);
|
||||
x.conditional_negate(1u8);
|
||||
assert_eq!(x, one);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ pub mod field;
|
|||
pub mod curve;
|
||||
pub mod scalar;
|
||||
|
||||
// Utilities module.
|
||||
// Constant-time functions and other miscelaneous utilities.
|
||||
|
||||
pub mod util;
|
||||
pub mod subtle;
|
||||
pub mod utils;
|
||||
|
||||
// Low-level curve and point constants, as well as pre-computed curve group elements.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,23 +29,61 @@
|
|||
//! between two scalars, the `UnpackedScalar` struct is stored as
|
||||
//! limbs.
|
||||
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::ops::{Neg};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use rand::Rng;
|
||||
|
||||
// XXX should these be in a utility module ?
|
||||
use field::{load3, load4};
|
||||
use util::CTAssignable;
|
||||
use constants;
|
||||
use utils::{load3, load4};
|
||||
use subtle::CTAssignable;
|
||||
use subtle::CTEq;
|
||||
use subtle::arrays_equal_ct;
|
||||
|
||||
/// The `Scalar` struct represents an element in ℤ/lℤ, where
|
||||
///
|
||||
/// l = 2^252 + 27742317777372353535851937790883648493
|
||||
///
|
||||
/// is the order of the basepoint. The `Scalar` is stored as bytes.
|
||||
#[derive(Copy,Clone)]
|
||||
#[derive(Copy, Clone)]
|
||||
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 {
|
||||
type Output = u8;
|
||||
|
||||
|
|
@ -62,12 +100,21 @@ 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 {
|
||||
/// Conditionally assign another Scalar to this one.
|
||||
///
|
||||
/// ```
|
||||
/// # use curve25519_dalek::scalar::Scalar;
|
||||
/// # use curve25519_dalek::util::CTAssignable;
|
||||
/// # use curve25519_dalek::subtle::CTAssignable;
|
||||
/// let a = 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]);
|
||||
/// let b = Scalar([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
|
|
@ -627,4 +674,13 @@ mod test {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
|
||||
//! Utility functions and tools for constant-time comparisons.
|
||||
//! Constant-time traits and utility functions.
|
||||
|
||||
use core::ops::Neg;
|
||||
|
||||
/// Trait for items which can be conditionally assigned in constant time.
|
||||
pub trait CTAssignable {
|
||||
|
|
@ -19,11 +21,41 @@ pub trait CTAssignable {
|
|||
fn conditional_assign(&mut self, other: &Self, choice: u8);
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// implementation is provided.
|
||||
pub trait CTNegatable
|
||||
{
|
||||
/// Conditionally negate an element if `choice == 1u8`.
|
||||
fn conditional_negate(&mut self, choice: u8);
|
||||
}
|
||||
|
||||
impl<T> CTNegatable for T
|
||||
where T: CTAssignable, for<'a> &'a T: Neg<Output=T>
|
||||
{
|
||||
fn conditional_negate(&mut self, choice: u8) {
|
||||
// Need to cast to eliminate mutability
|
||||
let self_neg: T = -(self as &T);
|
||||
self.conditional_assign(&self_neg, choice);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check equality of two bytes in constant time.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns 1 if `a == b` and 0 otherwise.
|
||||
/// Returns `1u8` if `a == b` and `0u8` otherwise.
|
||||
#[inline(always)]
|
||||
pub fn bytes_equal_ct(a: u8, b: u8) -> u8 {
|
||||
let mut x: u8;
|
||||
|
|
@ -62,10 +94,8 @@ pub fn byte_is_nonzero(b: u8) -> u8 {
|
|||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns 1 if `a == b` and 0 otherwise.
|
||||
/// Returns `1u8` if `a == b` and `0u8` otherwise.
|
||||
#[inline(always)]
|
||||
// We don't use this in curve25519-dalek, but it's useful for e.g. an ed25519 implementation.
|
||||
#[allow(dead_code)]
|
||||
pub fn arrays_equal_ct(a: &[u8; 32], b: &[u8; 32]) -> u8 {
|
||||
let mut x: u8 = 0;
|
||||
|
||||
31
src/utils.rs
Normal file
31
src/utils.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// To the extent possible under law, the authors have waived all copyright and
|
||||
// related or neighboring rights to curve25519-dalek, using the Creative
|
||||
// Commons "CC0" public domain dedication. See
|
||||
// <http://creativecommons.org/publicdomain/zero/.0/> for full details.
|
||||
//
|
||||
// Authors:
|
||||
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
|
||||
//! Miscellaneous common utility function.
|
||||
|
||||
/// Convert an array of (at least) three bytes into an i64.
|
||||
#[inline]
|
||||
//#[allow(dead_code)]
|
||||
pub fn load3(input: &[u8]) -> i64 {
|
||||
(input[0] as i64)
|
||||
| ((input[1] as i64) << 8)
|
||||
| ((input[2] as i64) << 16)
|
||||
}
|
||||
|
||||
/// Convert an array of (at least) four bytes into an i64.
|
||||
#[inline]
|
||||
//#[allow(dead_code)]
|
||||
pub fn load4(input: &[u8]) -> i64 {
|
||||
(input[0] as i64)
|
||||
| ((input[1] as i64) << 8)
|
||||
| ((input[2] as i64) << 16)
|
||||
| ((input[3] as i64) << 24)
|
||||
}
|
||||
Loading…
Reference in a new issue