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.
## 2.0.0-alpha.1
* Update `README.md` for `2.x` series.
* Fix a `Zeroize`-related build issue in the AVX2 backend.
## 2.0.0-alpha.0
## 2.0.0
* 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
@ -15,6 +10,11 @@ Entries are listed in reverse chronological order.
compatibility with `serde-json` and ensures that the `serde-bincode` encoding
matches the conventional encoding for X/Ed25519.
* 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
`build.rs` to generate constants, and keep the constants in the source code.

View file

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

View file

@ -63,7 +63,8 @@ See `CHANGELOG.md` for more details.
# Backends and Features
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:
@ -103,11 +104,10 @@ unless specifically marked as being variable-time code.
We believe that our constant-time logic is lowered to constant-time
assembly, at least on `x86_64` targets.
As an additional guard against possible future compiler optimizations, the
`nightly` feature places an optimization barrier before every
As an additional guard against possible future compiler optimizations,
the `subtle` crate places an optimization barrier before every
conditional move or assignment. More details can be found in [the
documentation for the `subtle` crate][subtle_doc]. This is
recommended, but not required.
documentation for the `subtle` crate][subtle_doc].
Some functionality (e.g., multiscalar multiplication or batch
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
`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
compiled with appropriate `target_feature`s.
compiled with appropriate `target_feature`s, so this cannot occur.
# Performance

View file

@ -247,7 +247,7 @@ mod ristretto_benches {
c.bench_function_over_inputs(
"Batch Ristretto double-and-encode",
|b, &&size| {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let points: Vec<RistrettoPoint> = (0..size)
.map(|_| RistrettoPoint::random(&mut rng))
.collect();
@ -299,7 +299,7 @@ mod scalar_benches {
c.bench_function_over_inputs(
"Batch scalar inversion",
|b, &&size| {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let scalars: Vec<Scalar> = (0..size).map(|_| Scalar::random(&mut rng)).collect();
b.iter(|| {
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.
// Unwrap first loop iteration to save computing 16*identity
let mut tmp2 = ProjectivePoint::identity();
let mut tmp2;
let mut tmp3 = EdwardsPoint::identity();
let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]);
// 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 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`.
pub(crate) const EDWARDS_D: FieldElement2625 = FieldElement2625([
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,
]);
/// 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.
pub(crate) const SQRT_AD_MINUS_ONE: FieldElement2625 = FieldElement2625([
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 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`.
pub(crate) const EDWARDS_D: FieldElement51 = FieldElement51([
929955233495203,
@ -34,6 +43,24 @@ pub(crate) const EDWARDS_D2: FieldElement51 = FieldElement51([
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.
pub(crate) const SQRT_AD_MINUS_ONE: FieldElement51 = FieldElement51([
2241493124984347,

View file

@ -44,8 +44,6 @@ extern crate packed_simd;
extern crate byteorder;
pub extern crate digest;
extern crate rand_core;
#[cfg(test)]
extern crate rand_os;
extern crate zeroize;
// 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
//! \\(u\\)-line, which discards sign information and unifies the curve
//! 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
//! \\(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::ConstantTimeEq;
use zeroize::Zeroize;
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
/// Curve25519 or its twist.
#[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 {
/// View this `MontgomeryPoint` as an array of bytes.
pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] {
@ -352,8 +360,7 @@ mod test {
use constants;
use super::*;
#[cfg(feature = "rand")]
use rand_os::OsRng;
use rand_core::OsRng;
#[test]
#[cfg(feature = "serde")]
@ -399,7 +406,7 @@ mod test {
#[test]
fn montgomery_to_edwards_rejects_twist() {
let one = FieldElement::one();
// u = 2 corresponds to a point on the twist.
let two = MontgomeryPoint((&one+&one).to_bytes());
@ -422,10 +429,9 @@ mod test {
assert_eq!(u18, u18_unred);
}
#[cfg(feature = "rand")]
#[test]
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 p_edwards: EdwardsPoint = &constants::ED25519_BASEPOINT_TABLE * &s;

View file

@ -490,13 +490,13 @@ impl RistrettoPoint {
/// ```
/// # extern crate curve25519_dalek;
/// # use curve25519_dalek::ristretto::RistrettoPoint;
/// extern crate rand_os;
/// use rand_os::OsRng;
/// extern crate rand_core;
/// use rand_core::OsRng;
///
/// # // Need fn main() here in comment so the doctest compiles
/// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests
/// # fn main() {
/// let mut rng = OsRng::new().unwrap();
/// let mut rng = OsRng;
/// let points: Vec<RistrettoPoint> =
/// (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
/// to a point -- proper elligator support is deferred for now.
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_minus_d_sq = &one - &d.square();
let d_minus_one_sq = (d - &one).square();
let r = i * &r_0.square();
let N_s = &(&r + &one) * &one_minus_d_sq;
let mut c = -&one;
let D = &(&c - &(d * &r)) * &(&r + 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)]
mod test {
#[cfg(feature = "rand")]
use rand_os::OsRng;
use rand_core::OsRng;
use scalar::Scalar;
use constants;
@ -1236,10 +1237,9 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn four_torsion_random() {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let B = &constants::RISTRETTO_BASEPOINT_TABLE;
let P = B * &Scalar::random(&mut rng);
let P_coset = P.coset4();
@ -1299,10 +1299,9 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn random_roundtrip() {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let B = &constants::RISTRETTO_BASEPOINT_TABLE;
for _ in 0..100 {
let P = B * &Scalar::random(&mut rng);
@ -1312,10 +1311,9 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn double_and_compress_1024_random_points() {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let points: Vec<RistrettoPoint> =
(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]
fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
let mut rng = rand::thread_rng();

View file

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