Bump rand_core from v0.9 to v0.10.0-rc-2 (#842)

Prior to a final stable release of the @RustCrypto dependencies used by
the dalek crates, we are going to target `rand_core` v0.10.

This updates the `rand` and `rand_core` dependencies as well as the
aforementioned @RustCrypto dependencies to be compatible with
`rand_core` v0.10, which incurred a few API changes:

- `rand_core` no longer includes `OsRng`, so this replaces the `os_rng`
  features with `getrandom` features (same thing we did for @RustCrypto)
  which uses the `getrandom` crate directly
- For `dev-dependencies` it just migrates straight to `rand`, replacing
  `rand_chacha` with the `chacha` feature of `rand` (which pulls in
  `chacha20`), and sourcing `OsRng` from `rand`, its new home (for now)

This PR also switches to using the `rustcrypto-ff`/`rustcrypto-group` crates
(hopefully temporary) which are forks of `ff` and `group` which have crate
releases that have been updated to use  `rand_core` v0.10.0 prereleases.
This commit is contained in:
Tony Arcieri 2025-11-22 10:37:51 -07:00 committed by GitHub
parent 9e04a586c0
commit 23d0d2cec0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 98 additions and 87 deletions

View file

@ -78,7 +78,7 @@ jobs:
- name: no_std / no feat ${{ matrix.crate }} - name: no_std / no feat ${{ matrix.crate }}
run: cargo build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --no-default-features run: cargo build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --no-default-features
- name: no_std / cargo hack ${{ matrix.crate }} - name: no_std / cargo hack ${{ matrix.crate }}
run: cargo hack build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std,os_rng run: cargo hack build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std,getrandom
clippy: clippy:
name: Check that clippy is happy name: Check that clippy is happy

View file

@ -37,13 +37,12 @@ features = [
] ]
[dev-dependencies] [dev-dependencies]
sha2 = { version = "0.11.0-rc.2", default-features = false } sha2 = { version = "0.11.0-rc.3", default-features = false }
bincode = "1" bincode = "1"
criterion = { version = "0.5", features = ["html_reports"] } criterion = { version = "0.5", features = ["html_reports"] }
hex = "0.4.2" hex = "0.4.2"
proptest = "1" proptest = "1"
rand = "0.9" rand = "0.10.0-rc.5"
rand_core = { version = "0.9", default-features = false, features = ["os_rng"] }
[build-dependencies] [build-dependencies]
rustc_version = "0.4.0" rustc_version = "0.4.0"
@ -55,10 +54,10 @@ required-features = ["alloc", "rand_core"]
[dependencies] [dependencies]
cfg-if = "1" cfg-if = "1"
ff = { version = "=0.14.0-pre.0", default-features = false, optional = true } ff = { version = "=0.14.0-pre.0", package = "rustcrypto-ff", default-features = false, optional = true }
group = { version = "=0.14.0-pre.0", default-features = false, optional = true } group = { version = "=0.14.0-pre.0", package = "rustcrypto-group", default-features = false, optional = true }
rand_core = { version = "0.9", default-features = false, optional = true } rand_core = { version = "0.10.0-rc-2", default-features = false, optional = true }
digest = { version = "0.11.0-rc.1", default-features = false, optional = true, features = [ digest = { version = "0.11.0-rc.4", default-features = false, optional = true, features = [
"block-api", "block-api",
] } ] }
subtle = { version = "2.6.0", default-features = false, features = [ subtle = { version = "2.6.0", default-features = false, features = [

View file

@ -117,7 +117,7 @@ use {
subtle::CtOption, subtle::CtOption,
}; };
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
use rand_core::RngCore; use rand_core::RngCore;
use subtle::Choice; use subtle::Choice;
@ -751,7 +751,7 @@ impl EdwardsPoint {
/// ///
/// Uses rejection sampling, generating a random `CompressedEdwardsY` and then attempting point /// Uses rejection sampling, generating a random `CompressedEdwardsY` and then attempting point
/// decompression, rejecting invalid points. /// decompression, rejecting invalid points.
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
pub fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self { pub fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
let mut repr = CompressedEdwardsY([0u8; 32]); let mut repr = CompressedEdwardsY([0u8; 32]);
loop { loop {
@ -1779,7 +1779,7 @@ impl CofactorGroup for EdwardsPoint {
mod test { mod test {
use super::*; use super::*;
use rand_core::TryRngCore; use rand::TryRngCore;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
@ -2068,7 +2068,7 @@ mod test {
/// Check that mul_base_clamped and mul_clamped agree /// Check that mul_base_clamped and mul_clamped agree
#[test] #[test]
fn mul_base_clamped() { fn mul_base_clamped() {
let mut csprng = rand_core::OsRng; let mut csprng = rand::rngs::OsRng;
// Make a random curve point in the curve. Give it torsion to make things interesting. // Make a random curve point in the curve. Give it torsion to make things interesting.
#[cfg(feature = "precomputed-tables")] #[cfg(feature = "precomputed-tables")]
@ -2182,7 +2182,7 @@ mod test {
} }
} }
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
#[test] #[test]
fn compress_batch() { fn compress_batch() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -2239,7 +2239,7 @@ mod test {
} }
// A single iteration of a consistency check for MSM. // A single iteration of a consistency check for MSM.
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn multiscalar_consistency_iter(n: usize) { fn multiscalar_consistency_iter(n: usize) {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -2266,7 +2266,7 @@ mod test {
// parameters. // parameters.
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn multiscalar_consistency_n_100() { fn multiscalar_consistency_n_100() {
let iters = 50; let iters = 50;
for _ in 0..iters { for _ in 0..iters {
@ -2275,7 +2275,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn multiscalar_consistency_n_250() { fn multiscalar_consistency_n_250() {
let iters = 50; let iters = 50;
for _ in 0..iters { for _ in 0..iters {
@ -2284,7 +2284,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn multiscalar_consistency_n_500() { fn multiscalar_consistency_n_500() {
let iters = 50; let iters = 50;
for _ in 0..iters { for _ in 0..iters {
@ -2293,7 +2293,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn multiscalar_consistency_n_1000() { fn multiscalar_consistency_n_1000() {
let iters = 50; let iters = 50;
for _ in 0..iters { for _ in 0..iters {
@ -2302,7 +2302,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn batch_to_montgomery() { fn batch_to_montgomery() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -2327,7 +2327,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn vartime_precomputed_vs_nonprecomputed_multiscalar() { fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
let mut rng = rand::rng(); let mut rng = rand::rng();

View file

@ -515,7 +515,9 @@ mod test {
use super::*; use super::*;
use crate::constants; use crate::constants;
use rand_core::{CryptoRng, RngCore, TryRngCore}; #[cfg(feature = "rand_core")]
use rand::CryptoRng;
use rand::{RngCore, TryRngCore};
#[test] #[test]
fn identity_in_different_coordinates() { fn identity_in_different_coordinates() {
@ -599,6 +601,7 @@ mod test {
} }
/// Returns a random point on the prime-order subgroup /// Returns a random point on the prime-order subgroup
#[cfg(feature = "rand_core")]
fn rand_prime_order_point<R: CryptoRng + ?Sized>(rng: &mut R) -> EdwardsPoint { fn rand_prime_order_point<R: CryptoRng + ?Sized>(rng: &mut R) -> EdwardsPoint {
let s: Scalar = Scalar::random(rng); let s: Scalar = Scalar::random(rng);
EdwardsPoint::mul_base(&s) EdwardsPoint::mul_base(&s)
@ -616,9 +619,10 @@ mod test {
}) })
} }
#[cfg(feature = "rand_core")]
#[test] #[test]
fn montgomery_ladder_matches_edwards_scalarmult() { fn montgomery_ladder_matches_edwards_scalarmult() {
let mut csprng = rand_core::OsRng.unwrap_err(); let mut csprng = rand::rngs::OsRng.unwrap_err();
for _ in 0..100 { for _ in 0..100 {
let p_edwards = rand_prime_order_point(&mut csprng); let p_edwards = rand_prime_order_point(&mut csprng);
@ -634,9 +638,10 @@ mod test {
// Tests that, on the prime-order subgroup, MontgomeryPoint::mul_bits_be is the same as // Tests that, on the prime-order subgroup, MontgomeryPoint::mul_bits_be is the same as
// multiplying by the Scalar representation of the same bits // multiplying by the Scalar representation of the same bits
#[cfg(feature = "rand_core")]
#[test] #[test]
fn montgomery_mul_bits_be() { fn montgomery_mul_bits_be() {
let mut csprng = rand_core::OsRng.unwrap_err(); let mut csprng = rand::rngs::OsRng.unwrap_err();
for _ in 0..100 { for _ in 0..100 {
// Make a random prime-order point P // Make a random prime-order point P
@ -661,7 +666,7 @@ mod test {
// integers b₁, b₂ and random (curve or twist) point P. // integers b₁, b₂ and random (curve or twist) point P.
#[test] #[test]
fn montgomery_mul_bits_be_twist() { fn montgomery_mul_bits_be_twist() {
let mut csprng = rand_core::OsRng.unwrap_err(); let mut csprng = rand::rngs::OsRng.unwrap_err();
for _ in 0..100 { for _ in 0..100 {
// Make a random point P on the curve or its twist // Make a random point P on the curve or its twist
@ -694,7 +699,7 @@ mod test {
/// Check that mul_base_clamped and mul_clamped agree /// Check that mul_base_clamped and mul_clamped agree
#[test] #[test]
fn mul_base_clamped() { fn mul_base_clamped() {
let mut csprng = rand_core::OsRng; let mut csprng = rand::rngs::OsRng;
// Test agreement on a large integer. Even after clamping, this is not reduced mod l. // Test agreement on a large integer. Even after clamping, this is not reduced mod l.
let a_bytes = [0xff; 32]; let a_bytes = [0xff; 32];

View file

@ -184,7 +184,7 @@ use {
subtle::CtOption, subtle::CtOption,
}; };
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
use { use {
core::convert::Infallible, core::convert::Infallible,
rand_core::{CryptoRng, TryCryptoRng}, rand_core::{CryptoRng, TryCryptoRng},
@ -543,7 +543,7 @@ impl RistrettoPoint {
#[cfg_attr(feature = "rand_core", doc = "```")] #[cfg_attr(feature = "rand_core", doc = "```")]
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")] #[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
/// # use curve25519_dalek::ristretto::RistrettoPoint; /// # use curve25519_dalek::ristretto::RistrettoPoint;
/// use rand_core::{OsRng, TryRngCore}; /// use rand::{rngs::OsRng, TryRngCore};
/// ///
/// # // 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
@ -656,7 +656,6 @@ impl RistrettoPoint {
] ]
} }
#[cfg(any(test, 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
@ -673,13 +672,13 @@ impl RistrettoPoint {
/// discrete log of the output point with respect to any other /// discrete log of the output point with respect to any other
/// point should be unknown. The map is applied twice and the /// point should be unknown. The map is applied twice and the
/// results are added, to ensure a uniform distribution. /// results are added, to ensure a uniform distribution.
#[cfg(feature = "rand_core")]
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self { pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
Self::try_from_rng(rng) Self::try_from_rng(rng)
.map_err(|_: Infallible| {}) .map_err(|_: Infallible| {})
.expect("[bug] unfallible rng failed") .expect("[bug] unfallible rng failed")
} }
#[cfg(any(test, 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
@ -696,6 +695,7 @@ impl RistrettoPoint {
/// discrete log of the output point with respect to any other /// discrete log of the output point with respect to any other
/// point should be unknown. The map is applied twice and the /// point should be unknown. The map is applied twice and the
/// results are added, to ensure a uniform distribution. /// results are added, to ensure a uniform distribution.
#[cfg(feature = "rand_core")]
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> { pub fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
let mut uniform_bytes = [0u8; 64]; let mut uniform_bytes = [0u8; 64];
rng.try_fill_bytes(&mut uniform_bytes)?; rng.try_fill_bytes(&mut uniform_bytes)?;
@ -1277,8 +1277,8 @@ mod test {
use crate::edwards::CompressedEdwardsY; use crate::edwards::CompressedEdwardsY;
#[cfg(feature = "group")] #[cfg(feature = "group")]
use proptest::prelude::*; use proptest::prelude::*;
#[cfg(feature = "rand_core")]
use rand_core::{OsRng, TryRngCore}; use rand::{TryRngCore, rngs::OsRng};
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -1469,6 +1469,7 @@ mod test {
} }
} }
#[cfg(feature = "rand_core")]
#[test] #[test]
fn four_torsion_random() { fn four_torsion_random() {
let mut rng = OsRng.unwrap_err(); let mut rng = OsRng.unwrap_err();
@ -1479,6 +1480,7 @@ mod test {
} }
} }
#[cfg(feature = "rand_core")]
#[test] #[test]
fn random_roundtrip() { fn random_roundtrip() {
let mut rng = OsRng.unwrap_err(); let mut rng = OsRng.unwrap_err();
@ -1542,7 +1544,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn vartime_precomputed_vs_nonprecomputed_multiscalar() { fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -1593,7 +1595,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn partial_precomputed_mixed_multiscalar_empty() { fn partial_precomputed_mixed_multiscalar_empty() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -1636,7 +1638,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn partial_precomputed_mixed_multiscalar() { fn partial_precomputed_mixed_multiscalar() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -1681,7 +1683,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn partial_precomputed_multiscalar() { fn partial_precomputed_multiscalar() {
let mut rng = rand::rng(); let mut rng = rand::rng();
@ -1710,7 +1712,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "alloc")] #[cfg(all(feature = "alloc", feature = "rand_core"))]
fn partial_precomputed_multiscalar_empty() { fn partial_precomputed_multiscalar_empty() {
let mut rng = rand::rng(); let mut rng = rand::rng();

View file

@ -130,7 +130,7 @@ use group::ff::{FieldBits, PrimeFieldBits};
#[cfg(feature = "group")] #[cfg(feature = "group")]
use rand_core::TryRngCore; use rand_core::TryRngCore;
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
use rand_core::CryptoRng; use rand_core::CryptoRng;
#[cfg(feature = "digest")] #[cfg(feature = "digest")]
@ -567,7 +567,6 @@ impl Scalar {
], ],
}; };
#[cfg(any(test, 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
@ -584,11 +583,12 @@ impl Scalar {
/// # fn main() { /// # fn main() {
/// use curve25519_dalek::scalar::Scalar; /// use curve25519_dalek::scalar::Scalar;
/// ///
/// use rand_core::{OsRng, TryRngCore}; /// use rand::{rngs::OsRng, TryRngCore};
/// ///
/// let mut csprng = OsRng.unwrap_err(); /// let mut csprng = OsRng.unwrap_err();
/// let a: Scalar = Scalar::random(&mut csprng); /// let a: Scalar = Scalar::random(&mut csprng);
/// # } /// # }
#[cfg(feature = "rand_core")]
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self { pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
let mut scalar_bytes = [0u8; 64]; let mut scalar_bytes = [0u8; 64];
rng.fill_bytes(&mut scalar_bytes); rng.fill_bytes(&mut scalar_bytes);
@ -1430,7 +1430,7 @@ pub const fn clamp_integer(mut bytes: [u8; 32]) -> [u8; 32] {
#[cfg(test)] #[cfg(test)]
pub(crate) mod test { pub(crate) mod test {
use super::*; use super::*;
use rand_core::RngCore; use rand::RngCore;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
@ -1570,6 +1570,7 @@ pub(crate) mod test {
} }
} }
#[cfg(feature = "rand_core")]
fn non_adjacent_form_iter(w: usize, x: &Scalar) { fn non_adjacent_form_iter(w: usize, x: &Scalar) {
let naf = x.non_adjacent_form(w); let naf = x.non_adjacent_form(w);
@ -1588,6 +1589,7 @@ pub(crate) mod test {
assert_eq!(*x, y); assert_eq!(*x, y);
} }
#[cfg(feature = "rand_core")]
#[test] #[test]
fn non_adjacent_form_random() { fn non_adjacent_form_random() {
let mut rng = rand::rng(); let mut rng = rand::rng();

View file

@ -31,14 +31,14 @@ features = ["batch", "digest", "hazmat", "pem", "serde"]
curve25519-dalek = { version = "=5.0.0-pre.1", default-features = false, features = [ curve25519-dalek = { version = "=5.0.0-pre.1", default-features = false, features = [
"digest", "digest",
] } ] }
ed25519 = { version = "3.0.0-rc.0", default-features = false } ed25519 = { version = "3.0.0-rc.2", default-features = false }
signature = { version = "3.0.0-rc.4", optional = true, default-features = false } signature = { version = "3.0.0-rc.5", optional = true, default-features = false }
sha2 = { version = "0.11.0-rc.2", default-features = false } sha2 = { version = "0.11.0-rc.3", default-features = false }
subtle = { version = "2.3.0", default-features = false } subtle = { version = "2.3.0", default-features = false }
# optional features # optional features
keccak = { version = "0.2.0-rc.0", default-features = false, optional = true } keccak = { version = "0.2.0-rc.0", default-features = false, optional = true }
rand_core = { version = "0.9", default-features = false, optional = true } rand_core = { version = "0.10.0-rc-2", default-features = false, optional = true }
serde = { version = "1.0", default-features = false, optional = true } serde = { version = "1.0", default-features = false, optional = true }
zeroize = { version = "1.5", default-features = false, optional = true } zeroize = { version = "1.5", default-features = false, optional = true }
@ -50,16 +50,14 @@ curve25519-dalek = { version = "=5.0.0-pre.1", default-features = false, feature
x25519-dalek = { version = "=3.0.0-pre.1", default-features = false, features = [ x25519-dalek = { version = "=3.0.0-pre.1", default-features = false, features = [
"static_secrets", "static_secrets",
] } ] }
blake2 = "0.11.0-rc.2" blake2 = "0.11.0-rc.3"
sha3 = "0.11.0-rc.3" sha3 = "0.11.0-rc.3"
hex = "0.4" hex = "0.4"
bincode = "1.0" bincode = "1.0"
serde_json = "1.0" serde_json = "1.0"
criterion = { version = "0.5", features = ["html_reports"] } criterion = { version = "0.5", features = ["html_reports"] }
hex-literal = "0.4" hex-literal = "0.4"
rand = "0.9" rand = { version = "0.10.0-rc.5", features = ["chacha"] }
rand_core = { version = "0.9", default-features = false }
rand_chacha = "0.9"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
strobe-rs = "0.5" strobe-rs = "0.5"
toml = { version = "0.9" } toml = { version = "0.9" }

View file

@ -50,11 +50,11 @@ struct ZeroRng;
impl rand_core::RngCore for ZeroRng { impl rand_core::RngCore for ZeroRng {
fn next_u32(&mut self) -> u32 { fn next_u32(&mut self) -> u32 {
rand_core::impls::next_u32_via_fill(self) rand_core::le::next_u32_via_fill(self)
} }
fn next_u64(&mut self) -> u64 { fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_fill(self) rand_core::le::next_u64_via_fill(self)
} }
/// A no-op function which leaves the destination bytes for randomness unchanged. /// A no-op function which leaves the destination bytes for randomness unchanged.

View file

@ -187,11 +187,11 @@ pub struct TranscriptRng {
impl rand_core::RngCore for TranscriptRng { impl rand_core::RngCore for TranscriptRng {
fn next_u32(&mut self) -> u32 { fn next_u32(&mut self) -> u32 {
rand_core::impls::next_u32_via_fill(self) rand_core::le::next_u32_via_fill(self)
} }
fn next_u64(&mut self) -> u64 { fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_fill(self) rand_core::le::next_u64_via_fill(self)
} }
fn fill_bytes(&mut self, dest: &mut [u8]) { fn fill_bytes(&mut self, dest: &mut [u8]) {
@ -305,8 +305,7 @@ mod tests {
#[test] #[test]
fn transcript_rng_is_bound_to_transcript_and_witnesses() { fn transcript_rng_is_bound_to_transcript_and_witnesses() {
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use rand_chacha::ChaChaRng; use rand::{SeedableRng, rngs::ChaCha8Rng};
use rand_core::SeedableRng;
// Check that the TranscriptRng is bound to the transcript and // Check that the TranscriptRng is bound to the transcript and
// the witnesses. This is done by producing a sequence of // the witnesses. This is done by producing a sequence of
@ -332,22 +331,22 @@ mod tests {
let mut r1 = t1 let mut r1 = t1
.build_rng() .build_rng()
.rekey_with_witness_bytes(b"witness", witness1) .rekey_with_witness_bytes(b"witness", witness1)
.finalize(&mut ChaChaRng::from_seed([0; 32])); .finalize(&mut ChaCha8Rng::from_seed([0; 32]));
let mut r2 = t2 let mut r2 = t2
.build_rng() .build_rng()
.rekey_with_witness_bytes(b"witness", witness1) .rekey_with_witness_bytes(b"witness", witness1)
.finalize(&mut ChaChaRng::from_seed([0; 32])); .finalize(&mut ChaCha8Rng::from_seed([0; 32]));
let mut r3 = t3 let mut r3 = t3
.build_rng() .build_rng()
.rekey_with_witness_bytes(b"witness", witness2) .rekey_with_witness_bytes(b"witness", witness2)
.finalize(&mut ChaChaRng::from_seed([0; 32])); .finalize(&mut ChaCha8Rng::from_seed([0; 32]));
let mut r4 = t4 let mut r4 = t4
.build_rng() .build_rng()
.rekey_with_witness_bytes(b"witness", witness2) .rekey_with_witness_bytes(b"witness", witness2)
.finalize(&mut ChaChaRng::from_seed([0; 32])); .finalize(&mut ChaCha8Rng::from_seed([0; 32]));
let s1 = Scalar::random(&mut r1); let s1 = Scalar::random(&mut r1);
let s2 = Scalar::random(&mut r2); let s2 = Scalar::random(&mut r2);

View file

@ -14,7 +14,7 @@ use core::fmt::Debug;
#[cfg(feature = "pkcs8")] #[cfg(feature = "pkcs8")]
use ed25519::pkcs8; use ed25519::pkcs8;
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
use rand_core::CryptoRng; use rand_core::CryptoRng;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -201,7 +201,7 @@ impl SigningKey {
/// # Input /// # Input
/// ///
/// A CSPRNG with a `fill_bytes()` method, e.g. `rand_os::OsRng`. /// A CSPRNG with a `fill_bytes()` method, e.g. `rand_os::OsRng`.
#[cfg(any(test, feature = "rand_core"))] #[cfg(feature = "rand_core")]
pub fn generate<R: CryptoRng + ?Sized>(csprng: &mut R) -> SigningKey { pub fn generate<R: CryptoRng + ?Sized>(csprng: &mut R) -> SigningKey {
let mut secret = SecretKey::default(); let mut secret = SecretKey::default();
csprng.fill_bytes(&mut secret); csprng.fill_bytes(&mut secret);

View file

@ -27,7 +27,7 @@ mod vectors {
scalar::Scalar, scalar::Scalar,
traits::IsIdentity, traits::IsIdentity,
}; };
use rand_core::TryRngCore; use rand::TryRngCore;
#[cfg(not(feature = "digest"))] #[cfg(not(feature = "digest"))]
use sha2::{Sha512, digest::Digest}; use sha2::{Sha512, digest::Digest};

View file

@ -39,20 +39,21 @@ rustdoc-args = [
"--cfg", "--cfg",
"docsrs", "docsrs",
] ]
features = ["os_rng", "reusable_secrets", "serde", "static_secrets"] features = ["reusable_secrets", "serde", "static_secrets"]
[dependencies] [dependencies]
curve25519-dalek = { version = "=5.0.0-pre.1", default-features = false } curve25519-dalek = { version = "=5.0.0-pre.1", default-features = false }
rand_core = { version = "0.9", default-features = false } rand_core = { version = "0.10.0-rc-2", default-features = false }
serde = { version = "1", default-features = false, optional = true, features = [
"derive", # optional dependencies
] } getrandom = { version = "0.3", optional = true }
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
zeroize = { version = "1", default-features = false, optional = true } zeroize = { version = "1", default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
bincode = "1" bincode = "1"
criterion = "0.5" criterion = "0.5"
rand_core = { version = "0.9", default-features = false, features = ["os_rng"] } rand = "0.10.0-rc.5"
[[bench]] [[bench]]
name = "x25519" name = "x25519"
@ -60,7 +61,7 @@ harness = false
[features] [features]
default = ["alloc", "precomputed-tables", "zeroize"] default = ["alloc", "precomputed-tables", "zeroize"]
os_rng = ["rand_core/os_rng"] getrandom = ["dep:getrandom"]
zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"] zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"]
serde = ["dep:serde", "curve25519-dalek/serde"] serde = ["dep:serde", "curve25519-dalek/serde"]
alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"] alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"]

View file

@ -51,7 +51,7 @@ loudly meows `bob_public` back to Alice. Alice now computes her
shared secret with Bob by doing: shared secret with Bob by doing:
```rust ```rust
# use rand_core::{OsRng, TryRngCore}; # use rand::{rngs::OsRng, TryRngCore};
# use x25519_dalek::{EphemeralSecret, PublicKey}; # use x25519_dalek::{EphemeralSecret, PublicKey};
# let mut rng = OsRng.unwrap_err(); # let mut rng = OsRng.unwrap_err();
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng); # let alice_secret = EphemeralSecret::random_from_rng(&mut rng);
@ -64,7 +64,7 @@ let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
Similarly, Bob computes a shared secret by doing: Similarly, Bob computes a shared secret by doing:
```rust ```rust
# use rand_core::{OsRng, TryRngCore}; # use rand::{rngs::OsRng, TryRngCore};
# use x25519_dalek::{EphemeralSecret, PublicKey}; # use x25519_dalek::{EphemeralSecret, PublicKey};
# let mut rng = OsRng.unwrap_err(); # let mut rng = OsRng.unwrap_err();
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng); # let alice_secret = EphemeralSecret::random_from_rng(&mut rng);
@ -77,7 +77,7 @@ let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);
These secrets are the same: These secrets are the same:
```rust ```rust
# use rand_core::{OsRng, TryRngCore}; # use rand::{rngs::OsRng, TryRngCore};
# use x25519_dalek::{EphemeralSecret, PublicKey}; # use x25519_dalek::{EphemeralSecret, PublicKey};
# let mut rng = OsRng.unwrap_err(); # let mut rng = OsRng.unwrap_err();
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng); # let alice_secret = EphemeralSecret::random_from_rng(&mut rng);

View file

@ -13,7 +13,7 @@
use criterion::{Criterion, criterion_group, criterion_main}; use criterion::{Criterion, criterion_group, criterion_main};
use rand_core::{OsRng, TryRngCore}; use rand::{TryRngCore, rngs::OsRng};
use x25519_dalek::EphemeralSecret; use x25519_dalek::EphemeralSecret;
use x25519_dalek::PublicKey; use x25519_dalek::PublicKey;

View file

@ -17,8 +17,6 @@
use curve25519_dalek::{edwards::EdwardsPoint, montgomery::MontgomeryPoint, traits::IsIdentity}; use curve25519_dalek::{edwards::EdwardsPoint, montgomery::MontgomeryPoint, traits::IsIdentity};
use rand_core::CryptoRng; use rand_core::CryptoRng;
#[cfg(feature = "os_rng")]
use rand_core::TryRngCore;
#[cfg(feature = "zeroize")] #[cfg(feature = "zeroize")]
use zeroize::{Zeroize, ZeroizeOnDrop}; use zeroize::{Zeroize, ZeroizeOnDrop};
@ -95,9 +93,12 @@ impl EphemeralSecret {
} }
/// Generate a new [`EphemeralSecret`]. /// Generate a new [`EphemeralSecret`].
#[cfg(feature = "os_rng")] #[cfg(feature = "getrandom")]
pub fn random() -> Self { pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng.unwrap_err()) // The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
getrandom::fill(&mut bytes).expect("getrandom failure");
EphemeralSecret(bytes)
} }
} }
@ -157,9 +158,12 @@ impl ReusableSecret {
} }
/// Generate a new [`ReusableSecret`]. /// Generate a new [`ReusableSecret`].
#[cfg(feature = "os_rng")] #[cfg(feature = "getrandom")]
pub fn random() -> Self { pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng.unwrap_mut()) // The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
getrandom::fill(&mut bytes).expect("getrandom failure");
ReusableSecret(bytes)
} }
} }
@ -218,9 +222,12 @@ impl StaticSecret {
} }
/// Generate a new [`StaticSecret`]. /// Generate a new [`StaticSecret`].
#[cfg(feature = "os_rng")] #[cfg(feature = "getrandom")]
pub fn random() -> Self { pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng.unwrap_mut()) // The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
getrandom::fill(&mut bytes).expect("getrandom failure");
StaticSecret(bytes)
} }
/// Extract this key's bytes for serialization. /// Extract this key's bytes for serialization.
@ -356,9 +363,7 @@ impl ZeroizeOnDrop for SharedSecret {}
/// # Example /// # Example
#[cfg_attr(feature = "static_secrets", doc = "```")] #[cfg_attr(feature = "static_secrets", doc = "```")]
#[cfg_attr(not(feature = "static_secrets"), doc = "```ignore")] #[cfg_attr(not(feature = "static_secrets"), doc = "```ignore")]
/// use rand_core::OsRng; /// use rand::{rngs::OsRng, RngCore, TryRngCore};
/// use rand_core::RngCore;
/// use rand_core::TryRngCore;
/// ///
/// use x25519_dalek::x25519; /// use x25519_dalek::x25519;
/// use x25519_dalek::StaticSecret; /// use x25519_dalek::StaticSecret;

View file

@ -178,10 +178,10 @@ fn rfc7748_ladder_test2() {
); );
} }
mod rand_core { mod os_rng {
use super::*; use super::*;
use ::rand_core::{OsRng, TryRngCore}; use rand::{TryRngCore, rngs::OsRng};
#[test] #[test]
fn ephemeral_from_rng() { fn ephemeral_from_rng() {
@ -201,8 +201,8 @@ mod rand_core {
} }
} }
#[cfg(feature = "os_rng")] #[cfg(feature = "getrandom")]
mod os_rng { mod getrandom {
use super::*; use super::*;