mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-10 21:21:13 +00:00
Make rand_core optional (#447)
As proposed in #442 this makes `rand_core` an optional feature that is not covered by the SemVer public API stability guarantees. Co-authored-by: Michael Rosenberg <michael@mrosenberg.pub>
This commit is contained in:
parent
2190332b67
commit
47a0c3eacc
9 changed files with 69 additions and 14 deletions
|
|
@ -5,6 +5,7 @@ major series.
|
||||||
|
|
||||||
## 4.x series
|
## 4.x series
|
||||||
|
|
||||||
|
* Make `rand_core` an optional feature
|
||||||
* Add target u32/u64 backend overrides
|
* Add target u32/u64 backend overrides
|
||||||
* Migrate documentation to docs.rs hosted
|
* Migrate documentation to docs.rs hosted
|
||||||
* Fix backend documentation generation
|
* Fix backend documentation generation
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ exclude = [
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--html-in-header", "docs/assets/rustdoc-include-katex-header.html", "--cfg", "docsrs"]
|
rustdoc-args = ["--html-in-header", "docs/assets/rustdoc-include-katex-header.html", "--cfg", "docsrs"]
|
||||||
features = ["serde", "simd_backend"]
|
features = ["serde", "simd_backend", "rand_core"]
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
|
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
|
||||||
|
|
@ -36,6 +36,7 @@ bincode = "1"
|
||||||
criterion = { version = "0.4.0", features = ["html_reports"] }
|
criterion = { version = "0.4.0", features = ["html_reports"] }
|
||||||
hex = "0.4.2"
|
hex = "0.4.2"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
rand_core = { version = "0.6", default-features = false }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "dalek_benchmarks"
|
name = "dalek_benchmarks"
|
||||||
|
|
@ -43,7 +44,7 @@ harness = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cfg-if = "1"
|
cfg-if = "1"
|
||||||
rand_core = { version = "0.6", default-features = false }
|
rand_core = { version = "0.6", default-features = false, optional = true }
|
||||||
digest = { version = "0.10", default-features = false }
|
digest = { version = "0.10", default-features = false }
|
||||||
subtle = { version = "^2.2.1", 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"] }
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -1,4 +1,4 @@
|
||||||
FEATURES := simd_backend serde
|
FEATURES := simd_backend serde rand_core
|
||||||
|
|
||||||
doc:
|
doc:
|
||||||
cargo +nightly rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --cfg docsrs
|
cargo +nightly rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --cfg docsrs
|
||||||
|
|
|
||||||
|
|
@ -1507,7 +1507,7 @@ mod test {
|
||||||
// Construct random coefficients x0, ..., x_{n-1},
|
// Construct random coefficients x0, ..., x_{n-1},
|
||||||
// followed by some extra hardcoded ones.
|
// followed by some extra hardcoded ones.
|
||||||
let xs = (0..n)
|
let xs = (0..n)
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| crate::mocks::MockScalar::random(&mut rng))
|
||||||
// The largest scalar allowed by the type system, 2^255-1
|
// The largest scalar allowed by the type system, 2^255-1
|
||||||
.chain(iter::once(Scalar::from_bits([0xff; 32])))
|
.chain(iter::once(Scalar::from_bits([0xff; 32])))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
@ -1577,11 +1577,11 @@ mod test {
|
||||||
let B = &crate::constants::ED25519_BASEPOINT_TABLE;
|
let B = &crate::constants::ED25519_BASEPOINT_TABLE;
|
||||||
|
|
||||||
let static_scalars = (0..128)
|
let static_scalars = (0..128)
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| crate::mocks::MockScalar::random(&mut rng))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let dynamic_scalars = (0..128)
|
let dynamic_scalars = (0..128)
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| crate::mocks::MockScalar::random(&mut rng))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let check_scalar: Scalar = static_scalars
|
let check_scalar: Scalar = static_scalars
|
||||||
|
|
|
||||||
|
|
@ -83,3 +83,6 @@ pub(crate) mod prelude;
|
||||||
|
|
||||||
// Generic code for window lookups
|
// Generic code for window lookups
|
||||||
pub(crate) mod window;
|
pub(crate) mod window;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod mocks;
|
||||||
|
|
|
||||||
42
src/mocks.rs
Normal file
42
src/mocks.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
//! This is used mocking / proxying the below for tests:
|
||||||
|
//! - random_test() to Scalar::random() depending on feature `rand_core`
|
||||||
|
|
||||||
|
use crate::ristretto::RistrettoPoint;
|
||||||
|
use crate::scalar::Scalar;
|
||||||
|
|
||||||
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
|
||||||
|
pub struct MockScalar;
|
||||||
|
impl MockScalar {
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
|
/// Proxy Scalar::random() for random_test
|
||||||
|
pub fn random<R: RngCore + CryptoRng + ?Sized>(rng: &mut R) -> Scalar {
|
||||||
|
Scalar::random(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rand_core"))]
|
||||||
|
/// Mock Scalar::random() for random_test
|
||||||
|
pub fn random<R: RngCore + CryptoRng + ?Sized>(rng: &mut R) -> Scalar {
|
||||||
|
let mut scalar_bytes = [0u8; 64];
|
||||||
|
rng.fill_bytes(&mut scalar_bytes);
|
||||||
|
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MockRistrettoPoint;
|
||||||
|
impl MockRistrettoPoint {
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
|
/// Proxy RistrettoPoint::random() for random_test
|
||||||
|
pub fn random<R: RngCore + CryptoRng + ?Sized>(rng: &mut R) -> RistrettoPoint {
|
||||||
|
RistrettoPoint::random(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rand_core"))]
|
||||||
|
/// Mock RistrettoPoint::random() for random_test
|
||||||
|
pub fn random<R: RngCore + CryptoRng + ?Sized>(rng: &mut R) -> RistrettoPoint {
|
||||||
|
let mut uniform_bytes = [0u8; 64];
|
||||||
|
rng.fill_bytes(&mut uniform_bytes);
|
||||||
|
|
||||||
|
RistrettoPoint::from_uniform_bytes(&uniform_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -374,6 +374,7 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::constants;
|
use crate::constants;
|
||||||
|
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -458,6 +459,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
fn montgomery_ladder_matches_edwards_scalarmult() {
|
fn montgomery_ladder_matches_edwards_scalarmult() {
|
||||||
let mut csprng: OsRng = OsRng;
|
let mut csprng: OsRng = OsRng;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
//! used to implement
|
//! used to implement
|
||||||
//!
|
//!
|
||||||
//! * `RistrettoPoint::random()`, which generates random points from an
|
//! * `RistrettoPoint::random()`, which generates random points from an
|
||||||
//! RNG;
|
//! RNG - enabled by `rand_core` feature;
|
||||||
//!
|
//!
|
||||||
//! * `RistrettoPoint::from_hash()` and
|
//! * `RistrettoPoint::from_hash()` and
|
||||||
//! `RistrettoPoint::hash_from_bytes()`, which perform hashing to the
|
//! `RistrettoPoint::hash_from_bytes()`, which perform hashing to the
|
||||||
|
|
@ -165,6 +165,7 @@ use core::ops::{Add, Neg, Sub};
|
||||||
use core::ops::{AddAssign, SubAssign};
|
use core::ops::{AddAssign, SubAssign};
|
||||||
use core::ops::{Mul, MulAssign};
|
use core::ops::{Mul, MulAssign};
|
||||||
|
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
use rand_core::{CryptoRng, RngCore};
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
|
||||||
use digest::generic_array::typenum::U64;
|
use digest::generic_array::typenum::U64;
|
||||||
|
|
@ -501,7 +502,8 @@ impl RistrettoPoint {
|
||||||
/// \mathrm{enc}( \[2\]P\_1), \ldots, \mathrm{enc}( \[2\]P\_n ) \\)
|
/// \mathrm{enc}( \[2\]P\_1), \ldots, \mathrm{enc}( \[2\]P\_n ) \\)
|
||||||
/// in a batch.
|
/// in a batch.
|
||||||
///
|
///
|
||||||
/// ```
|
#[cfg_attr(feature = "rand_core", doc = "```")]
|
||||||
|
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
|
||||||
/// # use curve25519_dalek::ristretto::RistrettoPoint;
|
/// # use curve25519_dalek::ristretto::RistrettoPoint;
|
||||||
/// use rand_core::OsRng;
|
/// use rand_core::OsRng;
|
||||||
///
|
///
|
||||||
|
|
@ -509,6 +511,7 @@ impl RistrettoPoint {
|
||||||
/// # // 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;
|
/// 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();
|
||||||
///
|
///
|
||||||
|
|
@ -662,6 +665,7 @@ impl RistrettoPoint {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
/// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG.
|
/// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG.
|
||||||
///
|
///
|
||||||
/// # Inputs
|
/// # Inputs
|
||||||
|
|
@ -1343,7 +1347,7 @@ mod test {
|
||||||
fn four_torsion_random() {
|
fn four_torsion_random() {
|
||||||
let mut rng = OsRng;
|
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 * &crate::mocks::MockScalar::random(&mut rng);
|
||||||
let P_coset = P.coset4();
|
let P_coset = P.coset4();
|
||||||
for point in P_coset {
|
for point in P_coset {
|
||||||
assert_eq!(P, RistrettoPoint(point));
|
assert_eq!(P, RistrettoPoint(point));
|
||||||
|
|
@ -1670,7 +1674,7 @@ mod test {
|
||||||
let mut rng = OsRng;
|
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 * &crate::mocks::MockScalar::random(&mut rng);
|
||||||
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);
|
||||||
|
|
@ -1683,7 +1687,7 @@ mod test {
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
|
|
||||||
let mut points: Vec<RistrettoPoint> = (0..1024)
|
let mut points: Vec<RistrettoPoint> = (0..1024)
|
||||||
.map(|_| RistrettoPoint::random(&mut rng))
|
.map(|_| crate::mocks::MockRistrettoPoint::random(&mut rng))
|
||||||
.collect();
|
.collect();
|
||||||
points[500] = RistrettoPoint::identity();
|
points[500] = RistrettoPoint::identity();
|
||||||
|
|
||||||
|
|
@ -1702,11 +1706,11 @@ mod test {
|
||||||
let B = &crate::constants::RISTRETTO_BASEPOINT_TABLE;
|
let B = &crate::constants::RISTRETTO_BASEPOINT_TABLE;
|
||||||
|
|
||||||
let static_scalars = (0..128)
|
let static_scalars = (0..128)
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| crate::mocks::MockScalar::random(&mut rng))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let dynamic_scalars = (0..128)
|
let dynamic_scalars = (0..128)
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| crate::mocks::MockScalar::random(&mut rng))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let check_scalar: Scalar = static_scalars
|
let check_scalar: Scalar = static_scalars
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
use rand_core::{CryptoRng, RngCore};
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
|
||||||
use digest::generic_array::typenum::U64;
|
use digest::generic_array::typenum::U64;
|
||||||
|
|
@ -566,6 +567,7 @@ impl Zeroize for Scalar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scalar {
|
impl Scalar {
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
|
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
|
||||||
///
|
///
|
||||||
/// # Inputs
|
/// # Inputs
|
||||||
|
|
@ -1404,7 +1406,7 @@ mod test {
|
||||||
fn non_adjacent_form_random() {
|
fn non_adjacent_form_random() {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
for _ in 0..1_000 {
|
for _ in 0..1_000 {
|
||||||
let x = Scalar::random(&mut rng);
|
let x = crate::mocks::MockScalar::random(&mut rng);
|
||||||
for w in &[5, 6, 7, 8] {
|
for w in &[5, 6, 7, 8] {
|
||||||
non_adjacent_form_iter(*w, &x);
|
non_adjacent_form_iter(*w, &x);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue