Skip to content

Commit 44e4901

Browse files
authored
Merge pull request #76 from fjarri/dyn-rng
Relax `CryptoRngCore` bound to allow non-sized args
2 parents 7524e59 + e53a457 commit 44e4901

File tree

8 files changed

+48
-31
lines changed

8 files changed

+48
-31
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
44
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

66

7+
## [0.6.1] - in development
8+
9+
### Added
10+
11+
- Relaxed `CryptoRngCore` bounds to allow `?Sized`. ([#76])
12+
13+
14+
[#76]: https://github.com/entropyxyz/crypto-primes/pull/76
15+
16+
717
## [0.6.0] - 2025-01-29
818

919
### Changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "crypto-primes"
3-
version = "0.6.0"
3+
version = "0.6.1-dev"
44
edition = "2021"
55
license = "Apache-2.0 OR MIT"
66
description = "Random prime number generation and primality checking library"
@@ -21,7 +21,7 @@ rayon = { version = "1", optional = true }
2121

2222
[dev-dependencies]
2323
# need `crypto-bigint` with `alloc` to test `BoxedUint`
24-
crypto-bigint = { version = "0.6", default-features = false, features = ["alloc"] }
24+
crypto-bigint = { version = "0.6.1", default-features = false, features = ["alloc"] }
2525
rand_chacha = "0.3"
2626
criterion = { version = "0.5", features = ["html_reports"] }
2727
num-modular = { version = "0.5", features = ["num-bigint"] }

benches/bench.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ fn make_random_rng() -> ChaCha8Rng {
3636
ChaCha8Rng::from_seed(seed)
3737
}
3838

39-
fn random_odd_uint<T: RandomBits + Integer>(rng: &mut impl CryptoRngCore, bit_length: u32) -> Odd<T> {
39+
fn random_odd_uint<T: RandomBits + Integer>(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Odd<T> {
4040
random_odd_integer::<T>(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb).unwrap()
4141
}
4242

43-
fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> SmallPrimesSieve<Uint<L>> {
43+
fn make_sieve<const L: usize>(rng: &mut (impl CryptoRngCore + ?Sized)) -> SmallPrimesSieve<Uint<L>> {
4444
let start = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS);
4545
SmallPrimesSieve::new(start.get(), NonZero::new(Uint::<L>::BITS).unwrap(), false)
4646
}
4747

48-
fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Odd<Uint<L>> {
48+
fn make_presieved_num<const L: usize>(rng: &mut (impl CryptoRngCore + ?Sized)) -> Odd<Uint<L>> {
4949
let mut sieve = make_sieve(rng);
5050
Odd::new(sieve.next().unwrap()).unwrap()
5151
}
@@ -352,7 +352,7 @@ fn bench_multicore_presets(_c: &mut Criterion) {}
352352
fn bench_gmp(c: &mut Criterion) {
353353
let mut group = c.benchmark_group("GMP");
354354

355-
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> GmpInteger {
355+
fn random<const L: usize>(rng: &mut (impl CryptoRngCore + ?Sized)) -> GmpInteger {
356356
let num = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS).get();
357357
GmpInteger::from_digits(num.as_words(), Order::Lsf)
358358
}
@@ -447,7 +447,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) {
447447
}
448448

449449
// Mimics the sequence of checks `glass-pumpkin` does to find a prime.
450-
fn prime_like_gp(bit_length: u32, rng: &mut impl CryptoRngCore) -> BoxedUint {
450+
fn prime_like_gp(bit_length: u32, rng: &mut (impl CryptoRngCore + ?Sized)) -> BoxedUint {
451451
loop {
452452
let start = random_odd_integer::<BoxedUint>(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb)
453453
.unwrap()
@@ -473,7 +473,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) {
473473
}
474474

475475
// Mimics the sequence of checks `glass-pumpkin` does to find a safe prime.
476-
fn safe_prime_like_gp(bit_length: u32, rng: &mut impl CryptoRngCore) -> BoxedUint {
476+
fn safe_prime_like_gp(bit_length: u32, rng: &mut (impl CryptoRngCore + ?Sized)) -> BoxedUint {
477477
loop {
478478
let start = random_odd_integer::<BoxedUint>(rng, NonZero::new(bit_length).unwrap(), SetBits::Msb)
479479
.unwrap()

src/generic.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn sieve_and_find<R, S>(
1515
) -> Option<S::Item>
1616
where
1717
S: SieveFactory,
18-
R: CryptoRngCore,
18+
R: CryptoRngCore + ?Sized,
1919
{
2020
// We could use `SieveIterator` here, but it requires cloning the `rng`.
2121
// Unlike the parallel version, it is avoidable here.
@@ -67,13 +67,13 @@ where
6767
/// A structure that chains the creation of sieves, returning the results from one until it is exhausted,
6868
/// and then creating a new one.
6969
#[derive(Debug)]
70-
pub struct SieveIterator<'a, R: CryptoRngCore, S: SieveFactory> {
70+
pub struct SieveIterator<'a, R: CryptoRngCore + ?Sized, S: SieveFactory> {
7171
sieve_factory: S,
7272
sieve: S::Sieve,
7373
rng: &'a mut R,
7474
}
7575

76-
impl<'a, R: CryptoRngCore, S: SieveFactory> SieveIterator<'a, R, S> {
76+
impl<'a, R: CryptoRngCore + ?Sized, S: SieveFactory> SieveIterator<'a, R, S> {
7777
/// Creates a new chained iterator producing results from sieves returned from `sieve_factory`.
7878
pub fn new(rng: &'a mut R, sieve_factory: S) -> Option<Self> {
7979
let mut sieve_factory = sieve_factory;
@@ -123,7 +123,7 @@ mod tests {
123123

124124
fn make_sieve(
125125
&mut self,
126-
_rng: &mut impl CryptoRngCore,
126+
_rng: &mut (impl CryptoRngCore + ?Sized),
127127
previous_sieve: Option<&Self::Sieve>,
128128
) -> Option<Self::Sieve> {
129129
self.count += 1;

src/hazmat/miller_rabin.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl<T: Integer + RandomMod> MillerRabin<T> {
105105
/// drawn using the provided RNG.
106106
///
107107
/// Note: panics if `candidate == 3` (so the range above is empty).
108-
pub fn test_random_base(&self, rng: &mut impl CryptoRngCore) -> Primality {
108+
pub fn test_random_base(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> Primality {
109109
// We sample a random base from the range `[3, candidate-2]`:
110110
// - we have a separate method for base 2;
111111
// - the test holds trivially for bases 1 or `candidate-1`.
@@ -167,7 +167,11 @@ mod tests {
167167
pseudoprimes::STRONG_BASE_2.iter().any(|x| *x == num)
168168
}
169169

170-
fn random_checks<T: Integer + RandomMod>(rng: &mut impl CryptoRngCore, mr: &MillerRabin<T>, count: usize) -> usize {
170+
fn random_checks<T: Integer + RandomMod>(
171+
rng: &mut (impl CryptoRngCore + ?Sized),
172+
mr: &MillerRabin<T>,
173+
count: usize,
174+
) -> usize {
171175
(0..count)
172176
.map(|_| -> usize { mr.test_random_base(rng).is_probably_prime().into() })
173177
.sum()

src/hazmat/sieve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum SetBits {
3434
/// Returns an error variant if `bit_length` is greater than the maximum allowed for `T`
3535
/// (applies to fixed-length types).
3636
pub fn random_odd_integer<T: Integer + RandomBits>(
37-
rng: &mut impl CryptoRngCore,
37+
rng: &mut (impl CryptoRngCore + ?Sized),
3838
bit_length: NonZeroU32,
3939
set_bits: SetBits,
4040
) -> Result<Odd<T>, RandomBitsError> {
@@ -325,7 +325,7 @@ impl<T: Integer + RandomBits> SieveFactory for SmallPrimesSieveFactory<T> {
325325
type Sieve = SmallPrimesSieve<T>;
326326
fn make_sieve(
327327
&mut self,
328-
rng: &mut impl CryptoRngCore,
328+
rng: &mut (impl CryptoRngCore + ?Sized),
329329
_previous_sieve: Option<&Self::Sieve>,
330330
) -> Option<Self::Sieve> {
331331
let start =

src/presets.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub fn is_safe_prime<T: Integer + RandomMod>(num: &T) -> bool {
8181
///
8282
/// See [`is_prime_with_rng`] for details about the performed checks.
8383
pub fn generate_prime_with_rng<T: Integer + RandomBits + RandomMod>(
84-
rng: &mut impl CryptoRngCore,
84+
rng: &mut (impl CryptoRngCore + ?Sized),
8585
bit_length: u32,
8686
) -> T {
8787
sieve_and_find(
@@ -99,7 +99,7 @@ pub fn generate_prime_with_rng<T: Integer + RandomBits + RandomMod>(
9999
///
100100
/// See [`is_prime_with_rng`] for details about the performed checks.
101101
pub fn generate_safe_prime_with_rng<T: Integer + RandomBits + RandomMod>(
102-
rng: &mut impl CryptoRngCore,
102+
rng: &mut (impl CryptoRngCore + ?Sized),
103103
bit_length: u32,
104104
) -> T {
105105
sieve_and_find(
@@ -187,7 +187,7 @@ where
187187
/// "Strengthening the Baillie-PSW primality test",
188188
/// Math. Comp. 90 1931-1955 (2021),
189189
/// DOI: [10.1090/mcom/3616](https://doi.org/10.1090/mcom/3616)
190-
pub fn is_prime_with_rng<T: Integer + RandomMod>(rng: &mut impl CryptoRngCore, num: &T) -> bool {
190+
pub fn is_prime_with_rng<T: Integer + RandomMod>(rng: &mut (impl CryptoRngCore + ?Sized), num: &T) -> bool {
191191
if num == &T::from_limb_like(Limb::from(2u32), num) {
192192
return true;
193193
}
@@ -201,7 +201,7 @@ pub fn is_prime_with_rng<T: Integer + RandomMod>(rng: &mut impl CryptoRngCore, n
201201
/// Probabilistically checks if the given number is a safe prime using the provided RNG.
202202
///
203203
/// See [`is_prime_with_rng`] for details about the performed checks.
204-
pub fn is_safe_prime_with_rng<T: Integer + RandomMod>(rng: &mut impl CryptoRngCore, num: &T) -> bool {
204+
pub fn is_safe_prime_with_rng<T: Integer + RandomMod>(rng: &mut (impl CryptoRngCore + ?Sized), num: &T) -> bool {
205205
// Since, by the definition of safe prime, `(num - 1) / 2` must also be prime,
206206
// and therefore odd, `num` has to be equal to 3 modulo 4.
207207
// 5 is the only exception, so we check for it.
@@ -228,7 +228,7 @@ pub fn is_safe_prime_with_rng<T: Integer + RandomMod>(rng: &mut impl CryptoRngCo
228228
/// If the outcome of M-R is "probably prime", then run a Lucas test
229229
/// If the Lucas test is inconclusive, run a Miller-Rabin with random base and unless this second
230230
/// M-R test finds it's composite, then conclude that it's prime.
231-
fn _is_prime_with_rng<T: Integer + RandomMod>(rng: &mut impl CryptoRngCore, candidate: Odd<T>) -> bool {
231+
fn _is_prime_with_rng<T: Integer + RandomMod>(rng: &mut (impl CryptoRngCore + ?Sized), candidate: Odd<T>) -> bool {
232232
let mr = MillerRabin::new(candidate.clone());
233233

234234
if !mr.test_base_two().is_probably_prime() {

src/traits.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ pub trait SieveFactory {
1414
/// Makes a sieve given an RNG and the previous exhausted sieve (if any).
1515
///
1616
/// Returning `None` signals that the prime generation should stop.
17-
fn make_sieve(&mut self, rng: &mut impl CryptoRngCore, previous_sieve: Option<&Self::Sieve>)
18-
-> Option<Self::Sieve>;
17+
fn make_sieve(
18+
&mut self,
19+
rng: &mut (impl CryptoRngCore + ?Sized),
20+
previous_sieve: Option<&Self::Sieve>,
21+
) -> Option<Self::Sieve>;
1922
}
2023

2124
/// Provides a generic way to access methods for random prime number generation
@@ -26,41 +29,41 @@ pub trait RandomPrimeWithRng {
2629
/// Panics if `bit_length` is less than 2, or greater than the bit size of the target `Uint`.
2730
///
2831
/// See [`is_prime_with_rng`] for details about the performed checks.
29-
fn generate_prime_with_rng(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self;
32+
fn generate_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self;
3033

3134
/// Returns a random safe prime (that is, such that `(n - 1) / 2` is also prime)
3235
/// of size `bit_length` using the provided RNG.
3336
///
3437
/// Panics if `bit_length` is less than 3, or greater than the bit size of the target `Uint`.
3538
///
3639
/// See [`is_prime_with_rng`] for details about the performed checks.
37-
fn generate_safe_prime_with_rng(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self;
40+
fn generate_safe_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self;
3841

3942
/// Probabilistically checks if the given number is prime using the provided RNG.
4043
///
4144
/// See [`is_prime_with_rng`] for details about the performed checks.
42-
fn is_prime_with_rng(&self, rng: &mut impl CryptoRngCore) -> bool;
45+
fn is_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool;
4346

4447
/// Probabilistically checks if the given number is a safe prime using the provided RNG.
4548
///
4649
/// See [`is_prime_with_rng`] for details about the performed checks.
47-
fn is_safe_prime_with_rng(&self, rng: &mut impl CryptoRngCore) -> bool;
50+
fn is_safe_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool;
4851
}
4952

5053
impl<T> RandomPrimeWithRng for T
5154
where
5255
T: Integer + RandomBits + RandomMod,
5356
{
54-
fn generate_prime_with_rng(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self {
57+
fn generate_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self {
5558
generate_prime_with_rng(rng, bit_length)
5659
}
57-
fn generate_safe_prime_with_rng(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self {
60+
fn generate_safe_prime_with_rng(rng: &mut (impl CryptoRngCore + ?Sized), bit_length: u32) -> Self {
5861
generate_safe_prime_with_rng(rng, bit_length)
5962
}
60-
fn is_prime_with_rng(&self, rng: &mut impl CryptoRngCore) -> bool {
63+
fn is_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool {
6164
is_prime_with_rng(rng, self)
6265
}
63-
fn is_safe_prime_with_rng(&self, rng: &mut impl CryptoRngCore) -> bool {
66+
fn is_safe_prime_with_rng(&self, rng: &mut (impl CryptoRngCore + ?Sized)) -> bool {
6467
is_safe_prime_with_rng(rng, self)
6568
}
6669
}

0 commit comments

Comments
 (0)