From 8b57f55d6a469a32ce0a4871c88899590483644a Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Fri, 14 Feb 2025 13:16:58 -0800 Subject: [PATCH 1/2] bump `rand_core` from `0.6.4` to `0.9.1` --- Cargo.toml | 24 ++++++-- benches/bench.rs | 113 ++++++++++++++++++------------------- src/generic.rs | 26 ++++----- src/hazmat/miller_rabin.rs | 14 ++--- src/hazmat/precomputed.rs | 4 +- src/hazmat/sieve.rs | 35 ++++++------ src/presets.rs | 64 ++++++++++----------- src/traits.rs | 52 +++++++++-------- 8 files changed, 171 insertions(+), 161 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6cb911c..a3ead5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,19 +10,18 @@ categories = ["cryptography", "no-std"] rust-version = "1.83" [dependencies] -crypto-bigint = { version = "0.6", default-features = false, features = ["rand_core"] } -rand_core = { version = "0.6.4", default-features = false } +crypto-bigint = { version = "0.7.0-pre", default-features = false, features = ["rand_core"] } +rand_core = { version = "0.9.0", default-features = false } # Optional dependencies used in tests and benchmarks openssl = { version = "0.10.39", optional = true, features = ["vendored"] } rug = { version = "1.26", default-features = false, features = ["integer"], optional = true } glass_pumpkin = { version = "1", optional = true } rayon = { version = "1", optional = true } - [dev-dependencies] # need `crypto-bigint` with `alloc` to test `BoxedUint` -crypto-bigint = { version = "0.6.1", default-features = false, features = ["alloc"] } -rand_chacha = "0.3" +crypto-bigint = { version = "0.7.0-pre", default-features = false, features = ["alloc"] } +rand_chacha = "0.9" criterion = { version = "0.5", features = ["html_reports"] } num-modular = { version = "0.5", features = ["num-bigint"] } num-bigint = "0.4" @@ -33,7 +32,7 @@ num_cpus = "1.16" [features] default = ["default-rng"] -default-rng = ["rand_core/getrandom"] +default-rng = ["rand_core/os_rng"] tests-openssl = ["openssl"] tests-gmp = ["rug/std"] tests-glass-pumpkin = ["glass_pumpkin"] @@ -53,3 +52,16 @@ harness = false [[bench]] name = "cctv" harness = false + +[patch.crates-io] +# https://github.com/RustCrypto/crypto-bigint/pull/762 +# https://github.com/RustCrypto/crypto-bigint/pull/765 +crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint.git" } + +# https://github.com/LF-Decentralized-Trust-labs/agora-glass_pumpkin/pull/26 +glass_pumpkin = { git = "https://github.com/baloo/agora-glass_pumpkin.git", branch = "baloo/rand-core/0.9" } +# https://github.com/rust-num/num-bigint/pull/317 +num-bigint = { git = "https://github.com/bionicles/num-bigint.git" } + +# https://github.com/rust-random/rand/pull/1593 +rand_core = { git = "https://github.com/fjarri/rand.git", branch = "sized" } diff --git a/benches/bench.rs b/benches/bench.rs index bfd9c11..36c3a46 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -3,7 +3,7 @@ use core::num::NonZero; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use crypto_bigint::{nlimbs, BoxedUint, Integer, Odd, RandomBits, Uint, U1024, U128, U256}; use rand_chacha::ChaCha8Rng; -use rand_core::{CryptoRngCore, OsRng, SeedableRng}; +use rand_core::{CryptoRng, OsRng, SeedableRng, TryRngCore}; #[cfg(feature = "tests-gmp")] use rug::{integer::Order, Integer as GmpInteger}; @@ -11,9 +11,6 @@ use rug::{integer::Order, Integer as GmpInteger}; #[cfg(feature = "tests-openssl")] use openssl::bn::BigNum; -#[cfg(feature = "multicore")] -use rand_core::RngCore; - use crypto_primes::{ generate_prime_with_rng, generate_safe_prime_with_rng, hazmat::{ @@ -31,21 +28,19 @@ fn make_rng() -> ChaCha8Rng { #[cfg(feature = "multicore")] fn make_random_rng() -> ChaCha8Rng { - let mut seed = ::Seed::default(); - OsRng.fill_bytes(&mut seed); - ChaCha8Rng::from_seed(seed) + ChaCha8Rng::from_os_rng() } -fn random_odd_uint(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Odd { - random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb).unwrap() +fn random_odd_uint(rng: &mut R, bit_length: u32) -> Odd { + random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb).unwrap() } -fn make_sieve(rng: &mut (impl CryptoRngCore + ?Sized)) -> SmallPrimesSieve> { - let start = random_odd_uint::>(rng, Uint::::BITS); +fn make_sieve(rng: &mut R) -> SmallPrimesSieve> { + let start = random_odd_uint::, R>(rng, Uint::::BITS); SmallPrimesSieve::new(start.get(), NonZero::new(Uint::::BITS).unwrap(), false) } -fn make_presieved_num(rng: &mut (impl CryptoRngCore + ?Sized)) -> Odd> { +fn make_presieved_num(rng: &mut R) -> Odd> { let mut sieve = make_sieve(rng); Odd::new(sieve.next().unwrap()).unwrap() } @@ -54,12 +49,12 @@ fn bench_sieve(c: &mut Criterion) { let mut group = c.benchmark_group("Sieve"); group.bench_function("(U128) random start", |b| { - b.iter(|| random_odd_uint::(&mut OsRng, 128)) + b.iter(|| random_odd_uint::(&mut OsRng.unwrap_err(), 128)) }); group.bench_function("(U128) creation", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 128), + || random_odd_uint::(&mut OsRng.unwrap_err(), 128), |start| SmallPrimesSieve::new(start.get(), NonZero::new(128).unwrap(), false), BatchSize::SmallInput, ) @@ -68,19 +63,19 @@ fn bench_sieve(c: &mut Criterion) { // 5 is the average number of pre-sieved samples we need to take before we encounter a prime group.bench_function("(U128) average sieve samples for a prime (5)", |b| { b.iter_batched( - || make_sieve::<{ nlimbs!(128) }>(&mut OsRng), + || make_sieve::<{ nlimbs!(128) }, _>(&mut OsRng.unwrap_err()), |sieve| sieve.take(5).for_each(drop), BatchSize::SmallInput, ) }); group.bench_function("(U1024) random start", |b| { - b.iter(|| random_odd_uint::(&mut OsRng, 1024)) + b.iter(|| random_odd_uint::(&mut OsRng.unwrap_err(), 1024)) }); group.bench_function("(U1024) creation", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 1024), + || random_odd_uint::(&mut OsRng.unwrap_err(), 1024), |start| SmallPrimesSieve::new(start.get(), NonZero::new(1024).unwrap(), false), BatchSize::SmallInput, ) @@ -89,7 +84,7 @@ fn bench_sieve(c: &mut Criterion) { // 42 is the average number of pre-sieved samples we need to take before we encounter a prime group.bench_function("(U1024) average sieve samples for a prime (42)", |b| { b.iter_batched( - || make_sieve::<{ nlimbs!(1024) }>(&mut OsRng), + || make_sieve::<{ nlimbs!(1024) }, _>(&mut OsRng.unwrap_err()), |sieve| sieve.take(42).for_each(drop), BatchSize::SmallInput, ) @@ -99,7 +94,7 @@ fn bench_sieve(c: &mut Criterion) { // before we encounter a safe prime group.bench_function("(U1024) average sieve samples for a safe prime (42^2)", |b| { b.iter_batched( - || make_sieve::<{ nlimbs!(1024) }>(&mut OsRng), + || make_sieve::<{ nlimbs!(1024) }, _>(&mut OsRng.unwrap_err()), |sieve| sieve.take(42 * 42).for_each(drop), BatchSize::SmallInput, ) @@ -113,7 +108,7 @@ fn bench_miller_rabin(c: &mut Criterion) { group.bench_function("(U128) creation", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 128), + || random_odd_uint::(&mut OsRng.unwrap_err(), 128), MillerRabin::::new, BatchSize::SmallInput, ) @@ -121,15 +116,15 @@ fn bench_miller_rabin(c: &mut Criterion) { group.bench_function("(U128) random base test (pre-sieved)", |b| { b.iter_batched( - || MillerRabin::new(make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)), - |mr| mr.test_random_base(&mut OsRng), + || MillerRabin::new(make_presieved_num::<{ nlimbs!(128) }, _>(&mut OsRng.unwrap_err())), + |mr| mr.test_random_base(&mut OsRng.unwrap_err()), BatchSize::SmallInput, ) }); group.bench_function("(U1024) creation", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 1024), + || random_odd_uint::(&mut OsRng.unwrap_err(), 1024), MillerRabin::::new, BatchSize::SmallInput, ) @@ -137,8 +132,8 @@ fn bench_miller_rabin(c: &mut Criterion) { group.bench_function("(U1024) random base test (pre-sieved)", |b| { b.iter_batched( - || MillerRabin::new(make_presieved_num::<{ nlimbs!(1024) }>(&mut OsRng)), - |mr| mr.test_random_base(&mut OsRng), + || MillerRabin::new(make_presieved_num::<{ nlimbs!(1024) }, _>(&mut OsRng.unwrap_err())), + |mr| mr.test_random_base(&mut OsRng.unwrap_err()), BatchSize::SmallInput, ) }); @@ -150,7 +145,7 @@ fn bench_lucas(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U128) Selfridge base, strong check (pre-sieved)", |b| { b.iter_batched( - || make_presieved_num::<{ nlimbs!(128) }>(&mut rng), + || make_presieved_num::<{ nlimbs!(128) }, _>(&mut rng), |n| lucas_test(n, SelfridgeBase, LucasCheck::Strong), BatchSize::SmallInput, ) @@ -159,7 +154,7 @@ fn bench_lucas(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) Selfridge base, strong check (pre-sieved)", |b| { b.iter_batched( - || make_presieved_num::<{ nlimbs!(1024) }>(&mut rng), + || make_presieved_num::<{ nlimbs!(1024) }, _>(&mut rng), |n| lucas_test(n, SelfridgeBase, LucasCheck::Strong), BatchSize::SmallInput, ) @@ -168,7 +163,7 @@ fn bench_lucas(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) A* base, Lucas-V check (pre-sieved)", |b| { b.iter_batched( - || make_presieved_num::<{ nlimbs!(1024) }>(&mut rng), + || make_presieved_num::<{ nlimbs!(1024) }, _>(&mut rng), |n| lucas_test(n, AStarBase, LucasCheck::LucasV), BatchSize::SmallInput, ) @@ -177,7 +172,7 @@ fn bench_lucas(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) brute force base, almost extra strong (pre-sieved)", |b| { b.iter_batched( - || make_presieved_num::<{ nlimbs!(1024) }>(&mut rng), + || make_presieved_num::<{ nlimbs!(1024) }, _>(&mut rng), |n| lucas_test(n, BruteForceBase, LucasCheck::AlmostExtraStrong), BatchSize::SmallInput, ) @@ -186,7 +181,7 @@ fn bench_lucas(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) brute force base, extra strong (pre-sieved)", |b| { b.iter_batched( - || make_presieved_num::<{ nlimbs!(1024) }>(&mut rng), + || make_presieved_num::<{ nlimbs!(1024) }, _>(&mut rng), |n| lucas_test(n, BruteForceBase, LucasCheck::ExtraStrong), BatchSize::SmallInput, ) @@ -219,50 +214,50 @@ fn bench_presets(c: &mut Criterion) { group.bench_function("(U128) Prime test", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 128), - |num| is_prime_with_rng(&mut OsRng, num.as_ref()), + || random_odd_uint::(&mut OsRng.unwrap_err(), 128), + |num| is_prime_with_rng(&mut OsRng.unwrap_err(), num.as_ref()), BatchSize::SmallInput, ) }); group.bench_function("(U128) Safe prime test", |b| { b.iter_batched( - || random_odd_uint::(&mut OsRng, 128), - |num| is_safe_prime_with_rng(&mut OsRng, num.as_ref()), + || random_odd_uint::(&mut OsRng.unwrap_err(), 128), + |num| is_safe_prime_with_rng(&mut OsRng.unwrap_err(), num.as_ref()), BatchSize::SmallInput, ) }); let mut rng = make_rng(); group.bench_function("(U128) Random prime", |b| { - b.iter(|| generate_prime_with_rng::(&mut rng, 128)) + b.iter(|| generate_prime_with_rng::(&mut rng, 128)) }); let mut rng = make_rng(); group.bench_function("(U1024) Random prime", |b| { - b.iter(|| generate_prime_with_rng::(&mut rng, 1024)) + b.iter(|| generate_prime_with_rng::(&mut rng, 1024)) }); let mut rng = make_rng(); group.bench_function("(U128) Random safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) }); group.sample_size(20); let mut rng = make_rng(); group.bench_function("(U1024) Random safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) }); let mut rng = make_rng(); group.bench_function("(Boxed128) Random safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) }); group.sample_size(20); let mut rng = make_rng(); group.bench_function("(Boxed1024) Random safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) }); group.finish(); @@ -272,19 +267,19 @@ fn bench_presets(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U128) Random safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) }); // The performance should scale with the prime size, not with the Uint size. // So we should strive for this test's result to be as close as possible // to that of the previous one and as far away as possible from the next one. group.bench_function("(U256) Random 128 bit safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 128)) }); // The upper bound for the previous test. group.bench_function("(U256) Random 256 bit safe prime", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 256)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 256)) }); group.finish(); @@ -297,7 +292,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(U128) Random prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_prime_with_rng::(&mut rng, 128, num_cpus::get()), + |mut rng| par_generate_prime_with_rng::(&mut rng, 128, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -305,7 +300,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(U1024) Random prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_prime_with_rng::(&mut rng, 1024, num_cpus::get()), + |mut rng| par_generate_prime_with_rng::(&mut rng, 1024, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -313,7 +308,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(U128) Random safe prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 128, num_cpus::get()), + |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 128, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -322,7 +317,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(U1024) Random safe prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 1024, num_cpus::get()), + |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 1024, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -330,7 +325,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(Boxed128) Random safe prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 128, num_cpus::get()), + |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 128, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -339,7 +334,7 @@ fn bench_multicore_presets(c: &mut Criterion) { group.bench_function("(Boxed1024) Random safe prime", |b| { b.iter_batched( make_random_rng, - |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 1024, num_cpus::get()), + |mut rng| par_generate_safe_prime_with_rng::(&mut rng, 1024, num_cpus::get()), BatchSize::SmallInput, ) }); @@ -352,14 +347,14 @@ fn bench_multicore_presets(_c: &mut Criterion) {} fn bench_gmp(c: &mut Criterion) { let mut group = c.benchmark_group("GMP"); - fn random(rng: &mut (impl CryptoRngCore + ?Sized)) -> GmpInteger { - let num = random_odd_uint::>(rng, Uint::::BITS).get(); + fn random(rng: &mut R) -> GmpInteger { + let num = random_odd_uint::, R>(rng, Uint::::BITS).get(); GmpInteger::from_digits(num.as_words(), Order::Lsf) } group.bench_function("(U128) Random prime", |b| { b.iter_batched( - || random::<{ nlimbs!(128) }>(&mut OsRng), + || random::<{ nlimbs!(128) }, _>(&mut OsRng.unwrap_err()), |n| n.next_prime(), BatchSize::SmallInput, ) @@ -367,7 +362,7 @@ fn bench_gmp(c: &mut Criterion) { group.bench_function("(U1024) Random prime", |b| { b.iter_batched( - || random::<{ nlimbs!(1024) }>(&mut OsRng), + || random::<{ nlimbs!(1024) }, _>(&mut OsRng.unwrap_err()), |n| n.next_prime(), BatchSize::SmallInput, ) @@ -447,9 +442,9 @@ fn bench_glass_pumpkin(c: &mut Criterion) { } // Mimics the sequence of checks `glass-pumpkin` does to find a prime. - fn prime_like_gp(bit_length: u32, rng: &mut (impl CryptoRngCore + ?Sized)) -> BoxedUint { + fn prime_like_gp(bit_length: u32, rng: &mut R) -> BoxedUint { loop { - let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) + let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) .unwrap() .get(); let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), false); @@ -473,9 +468,9 @@ fn bench_glass_pumpkin(c: &mut Criterion) { } // Mimics the sequence of checks `glass-pumpkin` does to find a safe prime. - fn safe_prime_like_gp(bit_length: u32, rng: &mut (impl CryptoRngCore + ?Sized)) -> BoxedUint { + fn safe_prime_like_gp(bit_length: u32, rng: &mut R) -> BoxedUint { loop { - let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) + let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) .unwrap() .get(); let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), true); @@ -521,7 +516,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) Random prime (crypto-primes default)", |b| { - b.iter(|| generate_prime_with_rng::(&mut rng, 1024)) + b.iter(|| generate_prime_with_rng::(&mut rng, 1024)) }); let mut rng = make_rng(); @@ -538,7 +533,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) { let mut rng = make_rng(); group.bench_function("(U1024) Random safe prime (crypto-primes default)", |b| { - b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) + b.iter(|| generate_safe_prime_with_rng::(&mut rng, 1024)) }); let mut rng = make_rng(); diff --git a/src/generic.rs b/src/generic.rs index e8495e4..f3d8943 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1,4 +1,4 @@ -use rand_core::CryptoRngCore; +use rand_core::CryptoRng; #[cfg(feature = "multicore")] use rayon::iter::{ParallelBridge, ParallelIterator}; @@ -15,7 +15,7 @@ pub fn sieve_and_find( ) -> Option where S: SieveFactory, - R: CryptoRngCore + ?Sized, + R: CryptoRng + ?Sized, { // We could use `SieveIterator` here, but it requires cloning the `rng`. // Unlike the parallel version, it is avoidable here. @@ -42,7 +42,7 @@ where #[cfg(feature = "multicore")] pub fn par_sieve_and_find(rng: &mut R, sieve_factory: S, predicate: F, threadcount: usize) -> Option where - R: CryptoRngCore + Clone + Send + Sync, + R: CryptoRng + Clone + Send + Sync, S: Send + Sync + SieveFactory, S::Sieve: Send, S::Item: Send, @@ -67,13 +67,13 @@ where /// A structure that chains the creation of sieves, returning the results from one until it is exhausted, /// and then creating a new one. #[derive(Debug)] -pub struct SieveIterator<'a, R: CryptoRngCore + ?Sized, S: SieveFactory> { +pub struct SieveIterator<'a, R: CryptoRng + ?Sized, S: SieveFactory> { sieve_factory: S, sieve: S::Sieve, rng: &'a mut R, } -impl<'a, R: CryptoRngCore + ?Sized, S: SieveFactory> SieveIterator<'a, R, S> { +impl<'a, R: CryptoRng + ?Sized, S: SieveFactory> SieveIterator<'a, R, S> { /// Creates a new chained iterator producing results from sieves returned from `sieve_factory`. pub fn new(rng: &'a mut R, sieve_factory: S) -> Option { let mut sieve_factory = sieve_factory; @@ -86,7 +86,7 @@ impl<'a, R: CryptoRngCore + ?Sized, S: SieveFactory> SieveIterator<'a, R, S> { } } -impl Iterator for SieveIterator<'_, R, S> { +impl Iterator for SieveIterator<'_, R, S> { type Item = S::Item; fn next(&mut self) -> Option { @@ -102,7 +102,7 @@ impl Iterator for SieveIterator<'_, R, S> { #[cfg(test)] mod tests { - use rand_core::{CryptoRngCore, OsRng}; + use rand_core::{CryptoRng, OsRng, TryRngCore}; use super::sieve_and_find; use crate::SieveFactory; @@ -121,9 +121,9 @@ mod tests { type Item = usize; type Sieve = core::ops::Range; - fn make_sieve( + fn make_sieve( &mut self, - _rng: &mut (impl CryptoRngCore + ?Sized), + _rng: &mut R, previous_sieve: Option<&Self::Sieve>, ) -> Option { self.count += 1; @@ -136,24 +136,24 @@ mod tests { } let factory = TestSieveFactory { count: 0 }; - let result = sieve_and_find(&mut OsRng, factory, |_rng, num| *num == 11); + let result = sieve_and_find(&mut OsRng.unwrap_err(), factory, |_rng, num| *num == 11); assert!(result.is_some()); #[cfg(feature = "multicore")] { let factory = TestSieveFactory { count: 0 }; - let result = par_sieve_and_find(&mut OsRng, factory, |_rng, num| *num == 11, 1); + let result = par_sieve_and_find(&mut OsRng.unwrap_err(), factory, |_rng, num| *num == 11, 1); assert!(result.is_some()); } let factory = TestSieveFactory { count: 0 }; - let result = sieve_and_find(&mut OsRng, factory, |_rng, num| *num == 20); + let result = sieve_and_find(&mut OsRng.unwrap_err(), factory, |_rng, num| *num == 20); assert!(result.is_none()); #[cfg(feature = "multicore")] { let factory = TestSieveFactory { count: 0 }; - let result = par_sieve_and_find(&mut OsRng, factory, |_rng, num| *num == 20, 1); + let result = par_sieve_and_find(&mut OsRng.unwrap_err(), factory, |_rng, num| *num == 20, 1); assert!(result.is_none()); } } diff --git a/src/hazmat/miller_rabin.rs b/src/hazmat/miller_rabin.rs index 5f68682..78dba30 100644 --- a/src/hazmat/miller_rabin.rs +++ b/src/hazmat/miller_rabin.rs @@ -1,7 +1,7 @@ //! Miller-Rabin primality test. use crypto_bigint::{Integer, Limb, Monty, NonZero as CTNonZero, Odd, PowBoundedExp, RandomMod, Square}; -use rand_core::CryptoRngCore; +use rand_core::CryptoRng; use super::Primality; @@ -105,7 +105,7 @@ impl MillerRabin { /// drawn using the provided RNG. /// /// Note: panics if `candidate == 3` (so the range above is empty). - pub fn test_random_base(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> Primality { + pub fn test_random_base(&self, rng: &mut R) -> Primality { // We sample a random base from the range `[3, candidate-2]`: // - we have a separate method for base 2; // - the test holds trivially for bases 1 or `candidate-1`. @@ -141,7 +141,7 @@ mod tests { use crypto_bigint::{Integer, Odd, RandomMod, Uint, U1024, U128, U1536, U64}; use rand_chacha::ChaCha8Rng; - use rand_core::{CryptoRngCore, OsRng, SeedableRng}; + use rand_core::{CryptoRng, OsRng, SeedableRng, TryRngCore}; #[cfg(feature = "tests-exhaustive")] use num_prime::nt_funcs::is_prime64; @@ -160,15 +160,15 @@ mod tests { #[should_panic(expected = "No suitable random base possible when `candidate == 3`; use the base 2 test.")] fn random_base_range_check() { let mr = MillerRabin::new(Odd::new(U64::from(3u32)).unwrap()); - mr.test_random_base(&mut OsRng); + mr.test_random_base(&mut OsRng.unwrap_err()); } fn is_spsp(num: u32) -> bool { pseudoprimes::STRONG_BASE_2.iter().any(|x| *x == num) } - fn random_checks( - rng: &mut (impl CryptoRngCore + ?Sized), + fn random_checks( + rng: &mut R, mr: &MillerRabin, count: usize, ) -> usize { @@ -200,7 +200,7 @@ mod tests { #[test] fn trivial() { let mut rng = ChaCha8Rng::from_seed(*b"01234567890123456789012345678901"); - let start = random_odd_integer::(&mut rng, NonZero::new(1024).unwrap(), SetBits::Msb).unwrap(); + let start = random_odd_integer::(&mut rng, NonZero::new(1024).unwrap(), SetBits::Msb).unwrap(); for num in SmallPrimesSieve::new(start.get(), NonZero::new(1024).unwrap(), false).take(10) { let mr = MillerRabin::new(Odd::new(num).unwrap()); diff --git a/src/hazmat/precomputed.rs b/src/hazmat/precomputed.rs index 89e385a..cfe4a59 100644 --- a/src/hazmat/precomputed.rs +++ b/src/hazmat/precomputed.rs @@ -143,7 +143,7 @@ pub(crate) static RECIPROCALS: [Reciprocal; SMALL_PRIMES.len()] = create_recipro #[cfg(test)] mod tests { use crypto_bigint::{NonZero, Random, U256}; - use rand_core::OsRng; + use rand_core::{OsRng, TryRngCore}; use super::{create_reciprocals, SMALL_PRIMES}; @@ -155,7 +155,7 @@ mod tests { for (reciprocal, prime) in reciprocals.iter().zip(SMALL_PRIMES.iter()) { for _ in 0..10 { - let x = U256::random(&mut OsRng); + let x = U256::random(&mut OsRng.unwrap_err()); let r_ref = (x % NonZero::new(U256::from(*prime)).unwrap()).as_limbs()[0]; let r_test = x.rem_limb_with_reciprocal(reciprocal); assert_eq!(r_ref, r_test); diff --git a/src/hazmat/sieve.rs b/src/hazmat/sieve.rs index be6d013..f483a47 100644 --- a/src/hazmat/sieve.rs +++ b/src/hazmat/sieve.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use core::num::{NonZero, NonZeroU32}; use crypto_bigint::{Integer, Odd, RandomBits, RandomBitsError}; -use rand_core::CryptoRngCore; +use rand_core::{CryptoRng, TryCryptoRng}; use crate::hazmat::precomputed::{SmallPrime, LAST_SMALL_PRIME, RECIPROCALS, SMALL_PRIMES}; use crate::traits::SieveFactory; @@ -33,11 +33,11 @@ pub enum SetBits { /// /// Returns an error variant if `bit_length` is greater than the maximum allowed for `T` /// (applies to fixed-length types). -pub fn random_odd_integer( - rng: &mut (impl CryptoRngCore + ?Sized), +pub fn random_odd_integer( + rng: &mut R, bit_length: NonZeroU32, set_bits: SetBits, -) -> Result, RandomBitsError> { +) -> Result, RandomBitsError> { let bit_length = bit_length.get(); let mut random = T::try_random_bits(rng, bit_length)?; @@ -323,13 +323,13 @@ impl SmallPrimesSieveFactory { impl SieveFactory for SmallPrimesSieveFactory { type Item = T; type Sieve = SmallPrimesSieve; - fn make_sieve( + fn make_sieve( &mut self, - rng: &mut (impl CryptoRngCore + ?Sized), + rng: &mut R, _previous_sieve: Option<&Self::Sieve>, ) -> Option { let start = - random_odd_integer::(rng, self.max_bit_length, self.set_bits).expect("random_odd_integer() failed"); + random_odd_integer::(rng, self.max_bit_length, self.set_bits).expect("random_odd_integer() failed"); Some(SmallPrimesSieve::new( start.get(), self.max_bit_length, @@ -358,7 +358,7 @@ mod tests { let max_prime = SMALL_PRIMES[SMALL_PRIMES.len() - 1]; let mut rng = ChaCha8Rng::from_seed(*b"01234567890123456789012345678901"); - let start = random_odd_integer::(&mut rng, NonZero::new(32).unwrap(), SetBits::Msb) + let start = random_odd_integer::(&mut rng, NonZero::new(32).unwrap(), SetBits::Msb) .unwrap() .get(); for num in SmallPrimesSieve::new(start, NonZero::new(32).unwrap(), false).take(100) { @@ -376,9 +376,10 @@ mod tests { let max_prime = SMALL_PRIMES[SMALL_PRIMES.len() - 1]; let mut rng = ChaCha8Rng::from_seed(*b"01234567890123456789012345678901"); - let start = random_odd_integer::(&mut rng, NonZero::new(32).unwrap(), SetBits::Msb) - .unwrap() - .get(); + let start = + random_odd_integer::(&mut rng, NonZero::new(32).unwrap(), SetBits::Msb) + .unwrap() + .get(); for num in SmallPrimesSieve::new(start, NonZero::new(32).unwrap(), false).take(100) { // For 32-bit targets @@ -456,7 +457,7 @@ mod tests { #[test] fn random_below_max_length() { for _ in 0..10 { - let r = random_odd_integer::(&mut OsRng, NonZero::new(50).unwrap(), SetBits::Msb) + let r = random_odd_integer::(&mut OsRng, NonZero::new(50).unwrap(), SetBits::Msb) .unwrap() .get(); assert_eq!(r.bits(), 50); @@ -465,7 +466,7 @@ mod tests { #[test] fn random_odd_uint_too_many_bits() { - assert!(random_odd_integer::(&mut OsRng, NonZero::new(65).unwrap(), SetBits::Msb).is_err()); + assert!(random_odd_integer::(&mut OsRng, NonZero::new(65).unwrap(), SetBits::Msb).is_err()); } #[test] @@ -505,19 +506,19 @@ mod tests { #[test] fn set_bits() { for _ in 0..10 { - let x = random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::Msb).unwrap(); + let x = random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::Msb).unwrap(); assert!(bool::from(x.bit(63))); } for _ in 0..10 { - let x = random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::TwoMsb).unwrap(); + let x = random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::TwoMsb).unwrap(); assert!(bool::from(x.bit(63))); assert!(bool::from(x.bit(62))); } // 1 in 2^30 chance of spurious failure... good enough? assert!((0..30) - .map(|_| { random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::None).unwrap() }) + .map(|_| { random_odd_integer::(&mut OsRng, NonZero::new(64).unwrap(), SetBits::None).unwrap() }) .any(|x| !bool::from(x.bit(63)))); } @@ -525,7 +526,7 @@ mod tests { fn set_two_msb_small_bit_length() { // Check that when technically there isn't a second most significant bit, // `random_odd_integer()` still returns a number. - let x = random_odd_integer::(&mut OsRng, NonZero::new(1).unwrap(), SetBits::TwoMsb) + let x = random_odd_integer::(&mut OsRng, NonZero::new(1).unwrap(), SetBits::TwoMsb) .unwrap() .get(); assert_eq!(x, U64::ONE); diff --git a/src/presets.rs b/src/presets.rs index 2fa8c8b..c08c98f 100644 --- a/src/presets.rs +++ b/src/presets.rs @@ -1,8 +1,8 @@ use crypto_bigint::{Integer, Limb, Odd, RandomBits, RandomMod}; -use rand_core::CryptoRngCore; +use rand_core::CryptoRng; #[cfg(feature = "default-rng")] -use rand_core::OsRng; +use rand_core::{OsRng, TryRngCore}; use crate::{ generic::sieve_and_find, @@ -17,7 +17,7 @@ use crate::generic::par_sieve_and_find; /// See [`is_prime_with_rng`] for details about the performed checks. #[cfg(feature = "default-rng")] pub fn generate_prime(bit_length: u32) -> T { - generate_prime_with_rng(&mut OsRng, bit_length) + generate_prime_with_rng(&mut OsRng.unwrap_err(), bit_length) } /// Returns a random prime of size `bit_length` using [`OsRng`] as the RNG. @@ -31,7 +31,7 @@ pub fn generate_prime(bit_length: u32) -> T /// Panics if the platform is unable to spawn threads. #[cfg(all(feature = "default-rng", feature = "multicore"))] pub fn par_generate_prime(bit_length: u32, threadcount: usize) -> T { - par_generate_prime_with_rng(&mut OsRng, bit_length, threadcount) + par_generate_prime_with_rng(&mut OsRng.unwrap_err(), bit_length, threadcount) } /// Returns a random safe prime (that is, such that `(n - 1) / 2` is also prime) of size @@ -40,7 +40,7 @@ pub fn par_generate_prime(bit_length: u32, /// See [`is_prime_with_rng`] for details about the performed checks. #[cfg(feature = "default-rng")] pub fn generate_safe_prime(bit_length: u32) -> T { - generate_safe_prime_with_rng(&mut OsRng, bit_length) + generate_safe_prime_with_rng(&mut OsRng.unwrap_err(), bit_length) } /// Returns a random safe prime (that is, such that `(n - 1) / 2` is also prime) of size @@ -55,7 +55,7 @@ pub fn generate_safe_prime(bit_length: u32) /// Panics if the platform is unable to spawn threads. #[cfg(all(feature = "default-rng", feature = "multicore"))] pub fn par_generate_safe_prime(bit_length: u32, threadcount: usize) -> T { - par_generate_safe_prime_with_rng(&mut OsRng, bit_length, threadcount) + par_generate_safe_prime_with_rng(&mut OsRng.unwrap_err(), bit_length, threadcount) } /// Probabilistically checks if the given number is prime using [`OsRng`] as the RNG. @@ -63,7 +63,7 @@ pub fn par_generate_safe_prime(bit_length: /// See [`is_prime_with_rng`] for details about the performed checks. #[cfg(feature = "default-rng")] pub fn is_prime(num: &T) -> bool { - is_prime_with_rng(&mut OsRng, num) + is_prime_with_rng(&mut OsRng.unwrap_err(), num) } /// Probabilistically checks if the given number is a safe prime (that is, such that `(n - 1) / 2` is @@ -72,7 +72,7 @@ pub fn is_prime(num: &T) -> bool { /// See [`is_prime_with_rng`] for details about the performed checks. #[cfg(feature = "default-rng")] pub fn is_safe_prime(num: &T) -> bool { - is_safe_prime_with_rng(&mut OsRng, num) + is_safe_prime_with_rng(&mut OsRng.unwrap_err(), num) } /// Returns a random prime of size `bit_length` using the provided RNG. @@ -80,8 +80,8 @@ pub fn is_safe_prime(num: &T) -> bool { /// Panics if `bit_length` is less than 2, or greater than the bit size of the target `Uint`. /// /// See [`is_prime_with_rng`] for details about the performed checks. -pub fn generate_prime_with_rng( - rng: &mut (impl CryptoRngCore + ?Sized), +pub fn generate_prime_with_rng( + rng: &mut R, bit_length: u32, ) -> T { sieve_and_find( @@ -98,8 +98,8 @@ pub fn generate_prime_with_rng( /// Panics if `bit_length` is less than 3, or greater than the bit size of the target `Uint`. /// /// See [`is_prime_with_rng`] for details about the performed checks. -pub fn generate_safe_prime_with_rng( - rng: &mut (impl CryptoRngCore + ?Sized), +pub fn generate_safe_prime_with_rng( + rng: &mut R, bit_length: u32, ) -> T { sieve_and_find( @@ -118,13 +118,10 @@ pub fn generate_safe_prime_with_rng( /// /// Panics if the platform is unable to spawn threads. #[cfg(feature = "multicore")] -pub fn par_generate_prime_with_rng( - rng: &mut (impl CryptoRngCore + Send + Sync + Clone), - bit_length: u32, - threadcount: usize, -) -> T +pub fn par_generate_prime_with_rng(rng: &mut R, bit_length: u32, threadcount: usize) -> T where T: Integer + RandomBits + RandomMod, + R: CryptoRng + Send + Sync + Clone, { par_sieve_and_find( rng, @@ -145,13 +142,10 @@ where /// /// See [`is_prime_with_rng`] for details about the performed checks. #[cfg(feature = "multicore")] -pub fn par_generate_safe_prime_with_rng( - rng: &mut (impl CryptoRngCore + Send + Sync + Clone), - bit_length: u32, - threadcount: usize, -) -> T +pub fn par_generate_safe_prime_with_rng(rng: &mut R, bit_length: u32, threadcount: usize) -> T where T: Integer + RandomBits + RandomMod, + R: CryptoRng + Send + Sync + Clone, { par_sieve_and_find( rng, @@ -187,7 +181,7 @@ where /// "Strengthening the Baillie-PSW primality test", /// Math. Comp. 90 1931-1955 (2021), /// DOI: [10.1090/mcom/3616](https://doi.org/10.1090/mcom/3616) -pub fn is_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), num: &T) -> bool { +pub fn is_prime_with_rng(rng: &mut R, num: &T) -> bool { if num == &T::from_limb_like(Limb::from(2u32), num) { return true; } @@ -201,7 +195,7 @@ pub fn is_prime_with_rng(rng: &mut (impl CryptoRngCore + /// Probabilistically checks if the given number is a safe prime using the provided RNG. /// /// See [`is_prime_with_rng`] for details about the performed checks. -pub fn is_safe_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), num: &T) -> bool { +pub fn is_safe_prime_with_rng(rng: &mut R, num: &T) -> bool { // Since, by the definition of safe prime, `(num - 1) / 2` must also be prime, // and therefore odd, `num` has to be equal to 3 modulo 4. // 5 is the only exception, so we check for it. @@ -228,7 +222,7 @@ pub fn is_safe_prime_with_rng(rng: &mut (impl CryptoRngC /// If the outcome of M-R is "probably prime", then run a Lucas test /// If the Lucas test is inconclusive, run a Miller-Rabin with random base and unless this second /// M-R test finds it's composite, then conclude that it's prime. -fn _is_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), candidate: Odd) -> bool { +fn _is_prime_with_rng(rng: &mut R, candidate: Odd) -> bool { let mr = MillerRabin::new(candidate.clone()); if !mr.test_base_two().is_probably_prime() { @@ -253,7 +247,7 @@ fn _is_prime_with_rng(rng: &mut (impl CryptoRngCore + ?S mod tests { use crypto_bigint::{nlimbs, BoxedUint, CheckedAdd, Uint, Word, U128, U64}; use num_prime::nt_funcs::is_prime64; - use rand_core::OsRng; + use rand_core::{OsRng, TryRngCore}; use super::{ generate_prime, generate_prime_with_rng, generate_safe_prime, generate_safe_prime_with_rng, is_prime, @@ -391,13 +385,13 @@ mod tests { #[test] #[should_panic(expected = "random_odd_integer() failed: BitLengthTooLarge { bit_length: 65, bits_precision: 64 }")] fn generate_prime_too_many_bits() { - let _p: U64 = generate_prime_with_rng(&mut OsRng, 65); + let _p: U64 = generate_prime_with_rng(&mut OsRng.unwrap_err(), 65); } #[test] #[should_panic(expected = "random_odd_integer() failed: BitLengthTooLarge { bit_length: 65, bits_precision: 64 }")] fn generate_safe_prime_too_many_bits() { - let _p: U64 = generate_safe_prime_with_rng(&mut OsRng, 65); + let _p: U64 = generate_safe_prime_with_rng(&mut OsRng.unwrap_err(), 65); } fn is_prime_ref(num: Word) -> bool { @@ -479,7 +473,7 @@ mod tests_openssl { use crypto_bigint::U128; use openssl::bn::{BigNum, BigNumContext}; - use rand_core::OsRng; + use rand_core::{OsRng, TryRngCore}; use super::{generate_prime, is_prime}; use crate::hazmat::{random_odd_integer, SetBits}; @@ -517,7 +511,8 @@ mod tests_openssl { // Generate random numbers, check if our test agrees with OpenSSL for _ in 0..100 { - let p = random_odd_integer::(&mut OsRng, NonZero::new(128).unwrap(), SetBits::Msb).unwrap(); + let p = random_odd_integer::(&mut OsRng.unwrap_err(), NonZero::new(128).unwrap(), SetBits::Msb) + .unwrap(); let actual = is_prime(p.as_ref()); let p_bn = to_openssl(&p); let expected = openssl_is_prime(&p_bn, &mut ctx); @@ -535,7 +530,7 @@ mod tests_gmp { use core::num::NonZero; use crypto_bigint::U128; - use rand_core::OsRng; + use rand_core::{OsRng, TryRngCore}; use rug::{ integer::{IsPrime, Order}, Integer, @@ -567,7 +562,9 @@ mod tests_gmp { // Generate primes with GMP, check them for _ in 0..100 { - let start = random_odd_integer::(&mut OsRng, NonZero::new(128).unwrap(), SetBits::Msb).unwrap(); + let start = + random_odd_integer::(&mut OsRng.unwrap_err(), NonZero::new(128).unwrap(), SetBits::Msb) + .unwrap(); let start_bn = to_gmp(&start); let p_bn = start_bn.next_prime(); let p = from_gmp(&p_bn); @@ -576,7 +573,8 @@ mod tests_gmp { // Generate random numbers, check if our test agrees with GMP for _ in 0..100 { - let p = random_odd_integer::(&mut OsRng, NonZero::new(128).unwrap(), SetBits::Msb).unwrap(); + let p = random_odd_integer::(&mut OsRng.unwrap_err(), NonZero::new(128).unwrap(), SetBits::Msb) + .unwrap(); let actual = is_prime(p.as_ref()); let p_bn = to_gmp(&p); let expected = gmp_is_prime(&p_bn); diff --git a/src/traits.rs b/src/traits.rs index 8217e46..361dbfd 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,5 +1,5 @@ use crypto_bigint::{Integer, RandomBits, RandomMod}; -use rand_core::CryptoRngCore; +use rand_core::CryptoRng; use crate::{generate_prime_with_rng, generate_safe_prime_with_rng, is_prime_with_rng, is_safe_prime_with_rng}; @@ -14,9 +14,9 @@ pub trait SieveFactory { /// Makes a sieve given an RNG and the previous exhausted sieve (if any). /// /// Returning `None` signals that the prime generation should stop. - fn make_sieve( + fn make_sieve( &mut self, - rng: &mut (impl CryptoRngCore + ?Sized), + rng: &mut R, previous_sieve: Option<&Self::Sieve>, ) -> Option; } @@ -29,7 +29,7 @@ pub trait RandomPrimeWithRng { /// Panics if `bit_length` is less than 2, or greater than the bit size of the target `Uint`. /// /// See [`is_prime_with_rng`] for details about the performed checks. - fn generate_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self; + fn generate_prime_with_rng(rng: &mut R, bit_length: u32) -> Self; /// Returns a random safe prime (that is, such that `(n - 1) / 2` is also prime) /// of size `bit_length` using the provided RNG. @@ -37,33 +37,33 @@ pub trait RandomPrimeWithRng { /// Panics if `bit_length` is less than 3, or greater than the bit size of the target `Uint`. /// /// See [`is_prime_with_rng`] for details about the performed checks. - fn generate_safe_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self; + fn generate_safe_prime_with_rng(rng: &mut R, bit_length: u32) -> Self; /// Probabilistically checks if the given number is prime using the provided RNG. /// /// See [`is_prime_with_rng`] for details about the performed checks. - fn is_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool; + fn is_prime_with_rng(&self, rng: &mut R) -> bool; /// Probabilistically checks if the given number is a safe prime using the provided RNG. /// /// See [`is_prime_with_rng`] for details about the performed checks. - fn is_safe_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool; + fn is_safe_prime_with_rng(&self, rng: &mut R) -> bool; } impl RandomPrimeWithRng for T where T: Integer + RandomBits + RandomMod, { - fn generate_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self { + fn generate_prime_with_rng(rng: &mut R, bit_length: u32) -> Self { generate_prime_with_rng(rng, bit_length) } - fn generate_safe_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self { + fn generate_safe_prime_with_rng(rng: &mut R, bit_length: u32) -> Self { generate_safe_prime_with_rng(rng, bit_length) } - fn is_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool { + fn is_prime_with_rng(&self, rng: &mut R) -> bool { is_prime_with_rng(rng, self) } - fn is_safe_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool { + fn is_safe_prime_with_rng(&self, rng: &mut R) -> bool { is_safe_prime_with_rng(rng, self) } } @@ -71,31 +71,35 @@ where #[cfg(test)] mod tests { use crypto_bigint::{BoxedUint, U64}; - use rand_core::OsRng; + use rand_core::{OsRng, TryRngCore}; use super::RandomPrimeWithRng; #[test] fn uint_impl() { - assert!(!U64::from(15u32).is_prime_with_rng(&mut OsRng)); - assert!(U64::from(19u32).is_prime_with_rng(&mut OsRng)); + assert!(!U64::from(15u32).is_prime_with_rng(&mut OsRng.unwrap_err())); + assert!(U64::from(19u32).is_prime_with_rng(&mut OsRng.unwrap_err())); - assert!(!U64::from(13u32).is_safe_prime_with_rng(&mut OsRng)); - assert!(U64::from(11u32).is_safe_prime_with_rng(&mut OsRng)); + assert!(!U64::from(13u32).is_safe_prime_with_rng(&mut OsRng.unwrap_err())); + assert!(U64::from(11u32).is_safe_prime_with_rng(&mut OsRng.unwrap_err())); - assert!(U64::generate_prime_with_rng(&mut OsRng, 10).is_prime_with_rng(&mut OsRng)); - assert!(U64::generate_safe_prime_with_rng(&mut OsRng, 10).is_safe_prime_with_rng(&mut OsRng)); + assert!(U64::generate_prime_with_rng(&mut OsRng.unwrap_err(), 10).is_prime_with_rng(&mut OsRng.unwrap_err())); + assert!(U64::generate_safe_prime_with_rng(&mut OsRng.unwrap_err(), 10) + .is_safe_prime_with_rng(&mut OsRng.unwrap_err())); } #[test] fn boxed_uint_impl() { - assert!(!BoxedUint::from(15u32).is_prime_with_rng(&mut OsRng)); - assert!(BoxedUint::from(19u32).is_prime_with_rng(&mut OsRng)); + assert!(!BoxedUint::from(15u32).is_prime_with_rng(&mut OsRng.unwrap_err())); + assert!(BoxedUint::from(19u32).is_prime_with_rng(&mut OsRng.unwrap_err())); - assert!(!BoxedUint::from(13u32).is_safe_prime_with_rng(&mut OsRng)); - assert!(BoxedUint::from(11u32).is_safe_prime_with_rng(&mut OsRng)); + assert!(!BoxedUint::from(13u32).is_safe_prime_with_rng(&mut OsRng.unwrap_err())); + assert!(BoxedUint::from(11u32).is_safe_prime_with_rng(&mut OsRng.unwrap_err())); - assert!(BoxedUint::generate_prime_with_rng(&mut OsRng, 10).is_prime_with_rng(&mut OsRng)); - assert!(BoxedUint::generate_safe_prime_with_rng(&mut OsRng, 10).is_safe_prime_with_rng(&mut OsRng)); + assert!( + BoxedUint::generate_prime_with_rng(&mut OsRng.unwrap_err(), 10).is_prime_with_rng(&mut OsRng.unwrap_err()) + ); + assert!(BoxedUint::generate_safe_prime_with_rng(&mut OsRng.unwrap_err(), 10) + .is_safe_prime_with_rng(&mut OsRng.unwrap_err())); } } From a6272c5ea9e1758eb56cda4567f51a562415a56c Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Mon, 17 Feb 2025 16:50:14 -0800 Subject: [PATCH 2/2] relax sizing requirement on the `TryCryptoRng` blanket impl --- Cargo.toml | 3 --- benches/bench.rs | 17 +++++++++------- src/hazmat/sieve.rs | 4 ++-- src/lib.rs | 3 +++ src/rng.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 src/rng.rs diff --git a/Cargo.toml b/Cargo.toml index a3ead5c..7a30b32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,3 @@ crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint.git" } glass_pumpkin = { git = "https://github.com/baloo/agora-glass_pumpkin.git", branch = "baloo/rand-core/0.9" } # https://github.com/rust-num/num-bigint/pull/317 num-bigint = { git = "https://github.com/bionicles/num-bigint.git" } - -# https://github.com/rust-random/rand/pull/1593 -rand_core = { git = "https://github.com/fjarri/rand.git", branch = "sized" } diff --git a/benches/bench.rs b/benches/bench.rs index 36c3a46..9034e8e 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -18,6 +18,7 @@ use crypto_primes::{ SmallPrimesSieve, }, is_prime_with_rng, is_safe_prime_with_rng, + rng::MaybeRng, }; #[cfg(feature = "multicore")] use crypto_primes::{par_generate_prime_with_rng, par_generate_safe_prime_with_rng}; @@ -32,7 +33,7 @@ fn make_random_rng() -> ChaCha8Rng { } fn random_odd_uint(rng: &mut R, bit_length: u32) -> Odd { - random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb).unwrap() + random_odd_integer::(&mut MaybeRng(rng), NonZero::new(bit_length).unwrap(), SetBits::Msb).unwrap() } fn make_sieve(rng: &mut R) -> SmallPrimesSieve> { @@ -444,9 +445,10 @@ fn bench_glass_pumpkin(c: &mut Criterion) { // Mimics the sequence of checks `glass-pumpkin` does to find a prime. fn prime_like_gp(bit_length: u32, rng: &mut R) -> BoxedUint { loop { - let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) - .unwrap() - .get(); + let start = + random_odd_integer::(&mut MaybeRng(rng), NonZero::new(bit_length).unwrap(), SetBits::Msb) + .unwrap() + .get(); let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), false); for num in sieve { let odd_num = Odd::new(num.clone()).unwrap(); @@ -470,9 +472,10 @@ fn bench_glass_pumpkin(c: &mut Criterion) { // Mimics the sequence of checks `glass-pumpkin` does to find a safe prime. fn safe_prime_like_gp(bit_length: u32, rng: &mut R) -> BoxedUint { loop { - let start = random_odd_integer::(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb) - .unwrap() - .get(); + let start = + random_odd_integer::(&mut MaybeRng(rng), NonZero::new(bit_length).unwrap(), SetBits::Msb) + .unwrap() + .get(); let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), true); for num in sieve { let odd_num = Odd::new(num.clone()).unwrap(); diff --git a/src/hazmat/sieve.rs b/src/hazmat/sieve.rs index f483a47..18d7c0e 100644 --- a/src/hazmat/sieve.rs +++ b/src/hazmat/sieve.rs @@ -328,8 +328,8 @@ impl SieveFactory for SmallPrimesSieveFactory { rng: &mut R, _previous_sieve: Option<&Self::Sieve>, ) -> Option { - let start = - random_odd_integer::(rng, self.max_bit_length, self.set_bits).expect("random_odd_integer() failed"); + let start = random_odd_integer::(&mut crate::rng::MaybeRng(rng), self.max_bit_length, self.set_bits) + .expect("random_odd_integer() failed"); Some(SmallPrimesSieve::new( start.get(), self.max_bit_length, diff --git a/src/lib.rs b/src/lib.rs index 19ff3ec..a01b1fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,9 @@ pub mod hazmat; mod presets; mod traits; +#[doc(hidden)] +pub mod rng; + pub use generic::{sieve_and_find, SieveIterator}; pub use presets::{generate_prime_with_rng, generate_safe_prime_with_rng, is_prime_with_rng, is_safe_prime_with_rng}; pub use traits::{RandomPrimeWithRng, SieveFactory}; diff --git a/src/rng.rs b/src/rng.rs new file mode 100644 index 0000000..3e39945 --- /dev/null +++ b/src/rng.rs @@ -0,0 +1,49 @@ +use rand_core::{CryptoRng, RngCore, TryCryptoRng, TryRngCore}; + +/// Adapter from [`CryptoRng`] to [`TryCryptoRng`] +/// +/// This is pending the release of a fix availale in this PR: +/// +#[doc(hidden)] +#[derive(Debug)] +pub struct MaybeRng<'r, R>(pub &'r mut R) +where + R: ?Sized; + +impl TryRngCore for MaybeRng<'_, R> +where + R: RngCore + ?Sized, +{ + type Error = core::convert::Infallible; + + #[inline] + fn try_next_u32(&mut self) -> Result { + Ok(self.0.next_u32()) + } + #[inline] + fn try_next_u64(&mut self) -> Result { + Ok(self.0.next_u64()) + } + #[inline] + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> { + self.0.fill_bytes(dst); + Ok(()) + } +} + +impl TryCryptoRng for MaybeRng<'_, R> {} + +#[cfg(test)] +mod tests { + use super::*; + use rand_core::OsRng; + #[test] + fn test_rng() { + let mut rng = OsRng.unwrap_err(); + + let mut rng = MaybeRng(&mut rng); + rng.try_next_u32().unwrap(); + rng.try_next_u64().unwrap(); + rng.try_fill_bytes(&mut []).unwrap(); + } +}