mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-03 20:13:48 +00:00
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:
parent
9e04a586c0
commit
23d0d2cec0
16 changed files with 98 additions and 87 deletions
2
.github/workflows/workspace.yml
vendored
2
.github/workflows/workspace.yml
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 = [
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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::*;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue