Skip to content

Commit

Permalink
Make rand_core optional (#447)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
pinkforest and rozbb authored Dec 8, 2022
1 parent 2190332 commit 47a0c3e
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ major series.

## 4.x series

* Make `rand_core` an optional feature
* Add target u32/u64 backend overrides
* Migrate documentation to docs.rs hosted
* Fix backend documentation generation
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exclude = [

[package.metadata.docs.rs]
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]
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
Expand All @@ -36,14 +36,15 @@ bincode = "1"
criterion = { version = "0.4.0", features = ["html_reports"] }
hex = "0.4.2"
rand = "0.8"
rand_core = { version = "0.6", default-features = false }

[[bench]]
name = "dalek_benchmarks"
harness = false

[dependencies]
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 }
subtle = { version = "^2.2.1", default-features = false }
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FEATURES := simd_backend serde
FEATURES := simd_backend serde rand_core

doc:
cargo +nightly rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --cfg docsrs
Expand Down
6 changes: 3 additions & 3 deletions src/edwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1507,7 +1507,7 @@ mod test {
// Construct random coefficients x0, ..., x_{n-1},
// followed by some extra hardcoded ones.
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
.chain(iter::once(Scalar::from_bits([0xff; 32])))
.collect::<Vec<_>>();
Expand Down Expand Up @@ -1577,11 +1577,11 @@ mod test {
let B = &crate::constants::ED25519_BASEPOINT_TABLE;

let static_scalars = (0..128)
.map(|_| Scalar::random(&mut rng))
.map(|_| crate::mocks::MockScalar::random(&mut rng))
.collect::<Vec<_>>();

let dynamic_scalars = (0..128)
.map(|_| Scalar::random(&mut rng))
.map(|_| crate::mocks::MockScalar::random(&mut rng))
.collect::<Vec<_>>();

let check_scalar: Scalar = static_scalars
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,6 @@ pub(crate) mod prelude;

// Generic code for window lookups
pub(crate) mod window;

#[cfg(test)]
pub(crate) mod mocks;
42 changes: 42 additions & 0 deletions src/mocks.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
2 changes: 2 additions & 0 deletions src/montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ mod test {
use super::*;
use crate::constants;

#[cfg(feature = "rand_core")]
use rand_core::OsRng;

#[test]
Expand Down Expand Up @@ -458,6 +459,7 @@ mod test {
}

#[test]
#[cfg(feature = "rand_core")]
fn montgomery_ladder_matches_edwards_scalarmult() {
let mut csprng: OsRng = OsRng;

Expand Down
18 changes: 11 additions & 7 deletions src/ristretto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
//! used to implement
//!
//! * `RistrettoPoint::random()`, which generates random points from an
//! RNG;
//! RNG - enabled by `rand_core` feature;
//!
//! * `RistrettoPoint::from_hash()` and
//! `RistrettoPoint::hash_from_bytes()`, which perform hashing to the
Expand Down Expand Up @@ -165,6 +165,7 @@ use core::ops::{Add, Neg, Sub};
use core::ops::{AddAssign, SubAssign};
use core::ops::{Mul, MulAssign};

#[cfg(feature = "rand_core")]
use rand_core::{CryptoRng, RngCore};

use digest::generic_array::typenum::U64;
Expand Down Expand Up @@ -501,14 +502,16 @@ impl RistrettoPoint {
/// \mathrm{enc}( \[2\]P\_1), \ldots, \mathrm{enc}( \[2\]P\_n ) \\)
/// in a batch.
///
/// ```
#[cfg_attr(feature = "rand_core", doc = "```")]
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
/// # use curve25519_dalek::ristretto::RistrettoPoint;
/// 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;
///
/// let points: Vec<RistrettoPoint> =
/// (0..32).map(|_| RistrettoPoint::random(&mut rng)).collect();
///
Expand Down Expand Up @@ -662,6 +665,7 @@ impl RistrettoPoint {
)
}

#[cfg(feature = "rand_core")]
/// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG.
///
/// # Inputs
Expand Down Expand Up @@ -1343,7 +1347,7 @@ mod test {
fn four_torsion_random() {
let mut rng = OsRng;
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();
for point in P_coset {
assert_eq!(P, RistrettoPoint(point));
Expand Down Expand Up @@ -1670,7 +1674,7 @@ mod test {
let mut rng = OsRng;
let B = &constants::RISTRETTO_BASEPOINT_TABLE;
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 Q = compressed_P.decompress().unwrap();
assert_eq!(P, Q);
Expand All @@ -1683,7 +1687,7 @@ mod test {
let mut rng = OsRng;

let mut points: Vec<RistrettoPoint> = (0..1024)
.map(|_| RistrettoPoint::random(&mut rng))
.map(|_| crate::mocks::MockRistrettoPoint::random(&mut rng))
.collect();
points[500] = RistrettoPoint::identity();

Expand All @@ -1702,11 +1706,11 @@ mod test {
let B = &crate::constants::RISTRETTO_BASEPOINT_TABLE;

let static_scalars = (0..128)
.map(|_| Scalar::random(&mut rng))
.map(|_| crate::mocks::MockScalar::random(&mut rng))
.collect::<Vec<_>>();

let dynamic_scalars = (0..128)
.map(|_| Scalar::random(&mut rng))
.map(|_| crate::mocks::MockScalar::random(&mut rng))
.collect::<Vec<_>>();

let check_scalar: Scalar = static_scalars
Expand Down
4 changes: 3 additions & 1 deletion src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ use crate::prelude::*;

use cfg_if::cfg_if;

#[cfg(feature = "rand_core")]
use rand_core::{CryptoRng, RngCore};

use digest::generic_array::typenum::U64;
Expand Down Expand Up @@ -566,6 +567,7 @@ impl Zeroize for Scalar {
}

impl Scalar {
#[cfg(feature = "rand_core")]
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
///
/// # Inputs
Expand Down Expand Up @@ -1404,7 +1406,7 @@ mod test {
fn non_adjacent_form_random() {
let mut rng = rand::thread_rng();
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] {
non_adjacent_form_iter(*w, &x);
}
Expand Down

0 comments on commit 47a0c3e

Please sign in to comment.