Merge branch 'develop' into feature/compressed-try-from

This commit is contained in:
isis agora lovecruft 2019-11-26 21:21:14 +00:00 committed by GitHub
commit d52ab8bb6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 96 additions and 58 deletions

View file

@ -2,12 +2,7 @@
Entries are listed in reverse chronological order. Entries are listed in reverse chronological order.
## 2.0.0-alpha.1 ## 2.0.0
* Update `README.md` for `2.x` series.
* Fix a `Zeroize`-related build issue in the AVX2 backend.
## 2.0.0-alpha.0
* Fix a data modeling error in the `serde` feature pointed out by Trevor Perrin * Fix a data modeling error in the `serde` feature pointed out by Trevor Perrin
which caused points and scalars to be serialized with length fields rather which caused points and scalars to be serialized with length fields rather
@ -15,6 +10,11 @@ Entries are listed in reverse chronological order.
compatibility with `serde-json` and ensures that the `serde-bincode` encoding compatibility with `serde-json` and ensures that the `serde-bincode` encoding
matches the conventional encoding for X/Ed25519. matches the conventional encoding for X/Ed25519.
* Update `rand_core` to `0.5`, allowing use with new `rand` versions. * Update `rand_core` to `0.5`, allowing use with new `rand` versions.
* Switch from `clear_on_drop` to `zeroize` (by Tony Arcieri).
* Require `subtle = ^2.2.1` and remove the note advising nightly Rust, which is
no longer required as of that version of `subtle`. See the `subtle`
changelog for more details.
* Update `README.md` for `2.x` series.
* Remove the `build.rs` hack which loaded the entire crate into its own * Remove the `build.rs` hack which loaded the entire crate into its own
`build.rs` to generate constants, and keep the constants in the source code. `build.rs` to generate constants, and keep the constants in the source code.

View file

@ -1,6 +1,6 @@
[package] [package]
name = "curve25519-dalek" name = "curve25519-dalek"
version = "2.0.0-alpha.1" version = "2.0.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>", authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
"Henry de Valence <hdevalence@hdevalence.ca>"] "Henry de Valence <hdevalence@hdevalence.ca>"]
readme = "README.md" readme = "README.md"
@ -26,7 +26,6 @@ features = ["nightly", "simd_backend"]
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"} travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
[dev-dependencies] [dev-dependencies]
rand_os = "0.2"
sha2 = { version = "0.8", default-features = false } sha2 = { version = "0.8", default-features = false }
bincode = "1" bincode = "1"
criterion = "0.2" criterion = "0.2"
@ -40,7 +39,7 @@ harness = false
rand_core = { version = "0.5", default-features = false } rand_core = { version = "0.5", default-features = false }
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
digest = { version = "0.8", default-features = false } digest = { version = "0.8", default-features = false }
subtle = { version = "2", default-features = false } subtle = { version = "^2.2.1", default-features = false }
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
packed_simd = { version = "0.3", features = ["into_bits"], optional = true } packed_simd = { version = "0.3", features = ["into_bits"], optional = true }
zeroize = { version = "1", default-features = false } zeroize = { version = "1", default-features = false }

View file

@ -63,7 +63,8 @@ See `CHANGELOG.md` for more details.
# Backends and Features # Backends and Features
The `nightly` feature enables features available only when using a Rust nightly The `nightly` feature enables features available only when using a Rust nightly
compiler. **It is recommended for security**. compiler. In particular, it is required for rendering documentation and for
the SIMD backends.
Curve arithmetic is implemented using one of the following backends: Curve arithmetic is implemented using one of the following backends:
@ -103,11 +104,10 @@ unless specifically marked as being variable-time code.
We believe that our constant-time logic is lowered to constant-time We believe that our constant-time logic is lowered to constant-time
assembly, at least on `x86_64` targets. assembly, at least on `x86_64` targets.
As an additional guard against possible future compiler optimizations, the As an additional guard against possible future compiler optimizations,
`nightly` feature places an optimization barrier before every the `subtle` crate places an optimization barrier before every
conditional move or assignment. More details can be found in [the conditional move or assignment. More details can be found in [the
documentation for the `subtle` crate][subtle_doc]. This is documentation for the `subtle` crate][subtle_doc].
recommended, but not required.
Some functionality (e.g., multiscalar multiplication or batch Some functionality (e.g., multiscalar multiplication or batch
inversion) requires heap allocation for temporary buffers. All inversion) requires heap allocation for temporary buffers. All
@ -124,9 +124,9 @@ functions in other crates.
The implementation is memory-safe, and contains no significant The implementation is memory-safe, and contains no significant
`unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD `unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD
intrinsics. These are marked `unsafe` because invoking them on an intrinsics. These are marked `unsafe` only because invoking them on an
inappropriate CPU would cause `SIGILL`, but the entire backend is only inappropriate CPU would cause `SIGILL`, but the entire backend is only
compiled with appropriate `target_feature`s. compiled with appropriate `target_feature`s, so this cannot occur.
# Performance # Performance

View file

@ -247,7 +247,7 @@ mod ristretto_benches {
c.bench_function_over_inputs( c.bench_function_over_inputs(
"Batch Ristretto double-and-encode", "Batch Ristretto double-and-encode",
|b, &&size| { |b, &&size| {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng;
let points: Vec<RistrettoPoint> = (0..size) let points: Vec<RistrettoPoint> = (0..size)
.map(|_| RistrettoPoint::random(&mut rng)) .map(|_| RistrettoPoint::random(&mut rng))
.collect(); .collect();
@ -299,7 +299,7 @@ mod scalar_benches {
c.bench_function_over_inputs( c.bench_function_over_inputs(
"Batch scalar inversion", "Batch scalar inversion",
|b, &&size| { |b, &&size| {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng;
let scalars: Vec<Scalar> = (0..size).map(|_| Scalar::random(&mut rng)).collect(); let scalars: Vec<Scalar> = (0..size).map(|_| Scalar::random(&mut rng)).collect();
b.iter(|| { b.iter(|| {
let mut s = scalars.clone(); let mut s = scalars.clone();

View file

@ -25,7 +25,7 @@ pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
// We sum right-to-left. // We sum right-to-left.
// Unwrap first loop iteration to save computing 16*identity // Unwrap first loop iteration to save computing 16*identity
let mut tmp2 = ProjectivePoint::identity(); let mut tmp2;
let mut tmp3 = EdwardsPoint::identity(); let mut tmp3 = EdwardsPoint::identity();
let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]); let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]);
// Now tmp1 = s_63*P in P1xP1 coords // Now tmp1 = s_63*P in P1xP1 coords

View file

@ -18,6 +18,11 @@ use backend::serial::u32::scalar::Scalar29;
use edwards::{EdwardsBasepointTable, EdwardsPoint}; use edwards::{EdwardsBasepointTable, EdwardsPoint};
use window::{LookupTable, NafLookupTable8}; use window::{LookupTable, NafLookupTable8};
/// The value of minus one, equal to `-&FieldElement::one()`
pub(crate) const MINUS_ONE: FieldElement2625 = FieldElement2625([
67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431
]);
/// Edwards `d` value, equal to `-121665/121666 mod p`. /// Edwards `d` value, equal to `-121665/121666 mod p`.
pub(crate) const EDWARDS_D: FieldElement2625 = FieldElement2625([ pub(crate) const EDWARDS_D: FieldElement2625 = FieldElement2625([
56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, 48412415, 21499315, 56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, 48412415, 21499315,
@ -28,6 +33,16 @@ pub(crate) const EDWARDS_D2: FieldElement2625 = FieldElement2625([
45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, 27058993, 29715967, 9444199, 45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, 27058993, 29715967, 9444199,
]); ]);
/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2`
pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement2625 = FieldElement2625([
6275446, 16937061, 44170319, 29780721, 11667076, 7397348, 39186143, 1766194, 42675006, 672202
]);
/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2`
pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement2625 = FieldElement2625([
15551776, 22456977, 53683765, 23429360, 55212328, 10178283, 40474537, 4729243, 61826754, 23438029
]);
/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. /// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters.
pub(crate) const SQRT_AD_MINUS_ONE: FieldElement2625 = FieldElement2625([ pub(crate) const SQRT_AD_MINUS_ONE: FieldElement2625 = FieldElement2625([
24849947, 33400850, 43495378, 6347714, 46036536, 32887293, 41837720, 18186727, 66238516, 24849947, 33400850, 43495378, 6347714, 46036536, 32887293, 41837720, 18186727, 66238516,

View file

@ -16,6 +16,15 @@ use backend::serial::u64::scalar::Scalar52;
use edwards::{EdwardsBasepointTable, EdwardsPoint}; use edwards::{EdwardsBasepointTable, EdwardsPoint};
use window::{LookupTable, NafLookupTable8}; use window::{LookupTable, NafLookupTable8};
/// The value of minus one, equal to `-&FieldElement::one()`
pub(crate) const MINUS_ONE: FieldElement51 = FieldElement51([
2251799813685228,
2251799813685247,
2251799813685247,
2251799813685247,
2251799813685247
]);
/// Edwards `d` value, equal to `-121665/121666 mod p`. /// Edwards `d` value, equal to `-121665/121666 mod p`.
pub(crate) const EDWARDS_D: FieldElement51 = FieldElement51([ pub(crate) const EDWARDS_D: FieldElement51 = FieldElement51([
929955233495203, 929955233495203,
@ -34,6 +43,24 @@ pub(crate) const EDWARDS_D2: FieldElement51 = FieldElement51([
633789495995903, 633789495995903,
]); ]);
/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2`
pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement51 = FieldElement51([
1136626929484150,
1998550399581263,
496427632559748,
118527312129759,
45110755273534
]);
/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2`
pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement51 = FieldElement51([
1507062230895904,
1572317787530805,
683053064812840,
317374165784489,
1572899562415810
]);
/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. /// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters.
pub(crate) const SQRT_AD_MINUS_ONE: FieldElement51 = FieldElement51([ pub(crate) const SQRT_AD_MINUS_ONE: FieldElement51 = FieldElement51([
2241493124984347, 2241493124984347,

View file

@ -44,8 +44,6 @@ extern crate packed_simd;
extern crate byteorder; extern crate byteorder;
pub extern crate digest; pub extern crate digest;
extern crate rand_core; extern crate rand_core;
#[cfg(test)]
extern crate rand_os;
extern crate zeroize; extern crate zeroize;
// Used for traits related to constant-time code. // Used for traits related to constant-time code.

View file

@ -17,7 +17,7 @@
//! Montgomery arithmetic works not on the curve itself, but on the //! Montgomery arithmetic works not on the curve itself, but on the
//! \\(u\\)-line, which discards sign information and unifies the curve //! \\(u\\)-line, which discards sign information and unifies the curve
//! and its quadratic twist. See [_Montgomery curves and their //! and its quadratic twist. See [_Montgomery curves and their
//! arithmetic_][costello-smith] by Costello and Smith for more details. //! arithmetic_][costello-smith] by Costello and Smith for more details.
//! //!
//! The `MontgomeryPoint` struct contains the affine \\(u\\)-coordinate //! The `MontgomeryPoint` struct contains the affine \\(u\\)-coordinate
//! \\(u\_0(P)\\) of a point \\(P\\) on either the curve or the twist. //! \\(u\_0(P)\\) of a point \\(P\\) on either the curve or the twist.
@ -62,6 +62,8 @@ use subtle::Choice;
use subtle::ConditionallySelectable; use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use zeroize::Zeroize;
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of /// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
/// Curve25519 or its twist. /// Curve25519 or its twist.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -110,6 +112,12 @@ impl ValidityCheck for MontgomeryPoint {
} }
} }
impl Zeroize for MontgomeryPoint {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
impl MontgomeryPoint { impl MontgomeryPoint {
/// View this `MontgomeryPoint` as an array of bytes. /// View this `MontgomeryPoint` as an array of bytes.
pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] {
@ -352,8 +360,7 @@ mod test {
use constants; use constants;
use super::*; use super::*;
#[cfg(feature = "rand")] use rand_core::OsRng;
use rand_os::OsRng;
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -399,7 +406,7 @@ mod test {
#[test] #[test]
fn montgomery_to_edwards_rejects_twist() { fn montgomery_to_edwards_rejects_twist() {
let one = FieldElement::one(); let one = FieldElement::one();
// u = 2 corresponds to a point on the twist. // u = 2 corresponds to a point on the twist.
let two = MontgomeryPoint((&one+&one).to_bytes()); let two = MontgomeryPoint((&one+&one).to_bytes());
@ -422,10 +429,9 @@ mod test {
assert_eq!(u18, u18_unred); assert_eq!(u18, u18_unred);
} }
#[cfg(feature = "rand")]
#[test] #[test]
fn montgomery_ladder_matches_edwards_scalarmult() { fn montgomery_ladder_matches_edwards_scalarmult() {
let mut csprng: OsRng = OsRng::new().unwrap(); let mut csprng: OsRng = OsRng;
let s: Scalar = Scalar::random(&mut csprng); let s: Scalar = Scalar::random(&mut csprng);
let p_edwards: EdwardsPoint = &constants::ED25519_BASEPOINT_TABLE * &s; let p_edwards: EdwardsPoint = &constants::ED25519_BASEPOINT_TABLE * &s;

View file

@ -490,13 +490,13 @@ impl RistrettoPoint {
/// ``` /// ```
/// # extern crate curve25519_dalek; /// # extern crate curve25519_dalek;
/// # use curve25519_dalek::ristretto::RistrettoPoint; /// # use curve25519_dalek::ristretto::RistrettoPoint;
/// extern crate rand_os; /// extern crate rand_core;
/// use rand_os::OsRng; /// use rand_core::OsRng;
/// ///
/// # // Need fn main() here in comment so the doctest compiles /// # // Need fn main() here in comment so the doctest compiles
/// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests
/// # fn main() { /// # fn main() {
/// let mut rng = OsRng::new().unwrap(); /// let mut rng = OsRng;
/// let points: Vec<RistrettoPoint> = /// let points: Vec<RistrettoPoint> =
/// (0..32).map(|_| RistrettoPoint::random(&mut rng)).collect(); /// (0..32).map(|_| RistrettoPoint::random(&mut rng)).collect();
/// ///
@ -603,14 +603,16 @@ impl RistrettoPoint {
/// This method is not public because it's just used for hashing /// This method is not public because it's just used for hashing
/// to a point -- proper elligator support is deferred for now. /// to a point -- proper elligator support is deferred for now.
pub(crate) fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint { pub(crate) fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint {
let (i, d) = (&constants::SQRT_M1, &constants::EDWARDS_D); let i = &constants::SQRT_M1;
let d = &constants::EDWARDS_D;
let one_minus_d_sq = &constants::ONE_MINUS_EDWARDS_D_SQUARED;
let d_minus_one_sq = &constants::EDWARDS_D_MINUS_ONE_SQUARED;
let mut c = constants::MINUS_ONE;
let one = FieldElement::one(); let one = FieldElement::one();
let one_minus_d_sq = &one - &d.square();
let d_minus_one_sq = (d - &one).square();
let r = i * &r_0.square(); let r = i * &r_0.square();
let N_s = &(&r + &one) * &one_minus_d_sq; let N_s = &(&r + &one) * &one_minus_d_sq;
let mut c = -&one;
let D = &(&c - &(d * &r)) * &(&r + d); let D = &(&c - &(d * &r)) * &(&r + d);
let (Ns_D_is_sq, mut s) = FieldElement::sqrt_ratio_i(&N_s, &D); let (Ns_D_is_sq, mut s) = FieldElement::sqrt_ratio_i(&N_s, &D);
@ -1087,8 +1089,7 @@ impl Debug for RistrettoPoint {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[cfg(feature = "rand")] use rand_core::OsRng;
use rand_os::OsRng;
use scalar::Scalar; use scalar::Scalar;
use constants; use constants;
@ -1236,10 +1237,9 @@ mod test {
} }
} }
#[cfg(feature = "rand")]
#[test] #[test]
fn four_torsion_random() { fn four_torsion_random() {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng;
let B = &constants::RISTRETTO_BASEPOINT_TABLE; let B = &constants::RISTRETTO_BASEPOINT_TABLE;
let P = B * &Scalar::random(&mut rng); let P = B * &Scalar::random(&mut rng);
let P_coset = P.coset4(); let P_coset = P.coset4();
@ -1299,10 +1299,9 @@ mod test {
} }
} }
#[cfg(feature = "rand")]
#[test] #[test]
fn random_roundtrip() { fn random_roundtrip() {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng;
let B = &constants::RISTRETTO_BASEPOINT_TABLE; let B = &constants::RISTRETTO_BASEPOINT_TABLE;
for _ in 0..100 { for _ in 0..100 {
let P = B * &Scalar::random(&mut rng); let P = B * &Scalar::random(&mut rng);
@ -1312,10 +1311,9 @@ mod test {
} }
} }
#[cfg(feature = "rand")]
#[test] #[test]
fn double_and_compress_1024_random_points() { fn double_and_compress_1024_random_points() {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng;
let points: Vec<RistrettoPoint> = let points: Vec<RistrettoPoint> =
(0..1024).map(|_| RistrettoPoint::random(&mut rng)).collect(); (0..1024).map(|_| RistrettoPoint::random(&mut rng)).collect();
@ -1327,19 +1325,6 @@ mod test {
} }
} }
#[cfg(feature = "rand")]
#[test]
fn random_is_valid() {
let mut rng = OsRng::new().unwrap();
for _ in 0..100 {
let P = RistrettoPoint::random(&mut rng);
// Check that P is on the curve
assert!(P.0.is_valid());
// Check that P is in the image of the ristretto map
P.compress();
}
}
#[test] #[test]
fn vartime_precomputed_vs_nonprecomputed_multiscalar() { fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();

View file

@ -160,6 +160,8 @@ use subtle::Choice;
use subtle::ConditionallySelectable; use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use zeroize::Zeroize;
use backend; use backend;
use constants; use constants;
@ -522,6 +524,12 @@ impl From<u128> for Scalar {
} }
} }
impl Zeroize for Scalar {
fn zeroize(&mut self) {
self.bytes.zeroize();
}
}
impl Scalar { impl Scalar {
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG. /// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
/// ///
@ -536,15 +544,15 @@ impl Scalar {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// extern crate rand_os; /// extern crate rand_core;
/// # extern crate curve25519_dalek; /// # extern crate curve25519_dalek;
/// # /// #
/// # fn main() { /// # fn main() {
/// use curve25519_dalek::scalar::Scalar; /// use curve25519_dalek::scalar::Scalar;
/// ///
/// use rand_os::OsRng; /// use rand_core::OsRng;
/// ///
/// let mut csprng: OsRng = OsRng::new().unwrap(); /// let mut csprng = OsRng;
/// let a: Scalar = Scalar::random(&mut csprng); /// let a: Scalar = Scalar::random(&mut csprng);
/// # } /// # }
pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self { pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {