Skip to content

Commit 752bdee

Browse files
authored
Merge pull request #36 from fjarri/uint-traits
Transition to `Integer` trait
2 parents 45152ad + 265696b commit 752bdee

File tree

11 files changed

+302
-312
lines changed

11 files changed

+302
-312
lines changed

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Changed
1010

11-
- Bumped `crypto-bigint` to 0.6.0-pre.5. ([#38])
11+
- Bumped `crypto-bigint` to 0.6.0-pre.6. ([#38])
1212
- Bumped MSRV to 1.73. (#[38])
13-
- `MillerRabin::new()` takes an `Odd`-wrapped integer by value. `random_odd_uint()` returns an `Odd`-wrapped integer. `LucasBase::generate()` takes an `Odd`-wrapped integer. `lucas_test` takes an `Odd`-wrapped integer. (#[38])
13+
- `MillerRabin::new()` takes an `Odd`-wrapped integer. `random_odd_uint()` is renamed to `random_odd_integer()`, takes a `NonZeroU32` for `bit_length`, and returns an `Odd`-wrapped integer. `LucasBase::generate()` takes an `Odd`-wrapped integer. `lucas_test` takes an `Odd`-wrapped integer. (#[38])
1414
- All bit length-type parameters take `u32` instead of `usize`. (#[38])
15+
- All the API is based on the `Integer` trait instead of `Uint` specifically. (#[38])
1516

1617

17-
[#35]: https://github.com/entropyxyz/crypto-primes/pull/38
18+
[#36]: https://github.com/entropyxyz/crypto-primes/pull/36
19+
[#38]: https://github.com/entropyxyz/crypto-primes/pull/38
1820

1921

2022
## [0.5.0] - 2023-08-20

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ categories = ["cryptography", "no-std"]
1010
rust-version = "1.73"
1111

1212
[dependencies]
13-
crypto-bigint = { version = "0.6.0-pre.5", default-features = false, features = ["rand_core"] }
13+
crypto-bigint = { version = "0.6.0-pre.6", default-features = false, features = ["rand_core"] }
1414
rand_core = { version = "0.6.4", default-features = false }
1515
openssl = { version = "0.10.39", optional = true, features = ["vendored"] }
1616
rug = { version = "1.18", default-features = false, features = ["integer"], optional = true }

benches/bench.rs

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1+
use core::num::NonZeroU32;
2+
13
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
2-
use crypto_bigint::{nlimbs, Odd, Uint, U1024};
4+
use crypto_bigint::{nlimbs, Integer, Odd, RandomBits, Uint, U1024, U128, U256};
35
use rand_chacha::ChaCha8Rng;
46
use rand_core::{CryptoRngCore, OsRng, SeedableRng};
57

68
#[cfg(feature = "tests-gmp")]
7-
use rug::{integer::Order, Integer};
9+
use rug::{integer::Order, Integer as GmpInteger};
810

911
#[cfg(feature = "tests-openssl")]
1012
use openssl::bn::BigNum;
1113

1214
use crypto_primes::{
1315
generate_prime_with_rng, generate_safe_prime_with_rng,
1416
hazmat::{
15-
lucas_test, random_odd_uint, AStarBase, BruteForceBase, LucasCheck, MillerRabin,
17+
lucas_test, random_odd_integer, AStarBase, BruteForceBase, LucasCheck, MillerRabin,
1618
SelfridgeBase, Sieve,
1719
},
1820
is_prime_with_rng, is_safe_prime_with_rng,
@@ -22,9 +24,16 @@ fn make_rng() -> ChaCha8Rng {
2224
ChaCha8Rng::from_seed(*b"01234567890123456789012345678901")
2325
}
2426

25-
fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<L> {
26-
let start = random_odd_uint::<L>(rng, Uint::<L>::BITS);
27-
Sieve::new(&start, Uint::<L>::BITS, false)
27+
fn random_odd_uint<T: RandomBits + Integer>(
28+
rng: &mut impl CryptoRngCore,
29+
bit_length: u32,
30+
) -> Odd<T> {
31+
random_odd_integer::<T>(rng, NonZeroU32::new(bit_length).unwrap())
32+
}
33+
34+
fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<Uint<L>> {
35+
let start = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS);
36+
Sieve::new(&start, NonZeroU32::new(Uint::<L>::BITS).unwrap(), false)
2837
}
2938

3039
fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Odd<Uint<L>> {
@@ -36,13 +45,13 @@ fn bench_sieve(c: &mut Criterion) {
3645
let mut group = c.benchmark_group("Sieve");
3746

3847
group.bench_function("(U128) random start", |b| {
39-
b.iter(|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128))
48+
b.iter(|| random_odd_uint::<U128>(&mut OsRng, 128))
4049
});
4150

4251
group.bench_function("(U128) creation", |b| {
4352
b.iter_batched(
44-
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
45-
|start| Sieve::new(&start, 128, false),
53+
|| random_odd_uint::<U128>(&mut OsRng, 128),
54+
|start| Sieve::new(start.as_ref(), NonZeroU32::new(128).unwrap(), false),
4655
BatchSize::SmallInput,
4756
)
4857
});
@@ -57,13 +66,13 @@ fn bench_sieve(c: &mut Criterion) {
5766
});
5867

5968
group.bench_function("(U1024) random start", |b| {
60-
b.iter(|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024))
69+
b.iter(|| random_odd_uint::<U1024>(&mut OsRng, 1024))
6170
});
6271

6372
group.bench_function("(U1024) creation", |b| {
6473
b.iter_batched(
65-
|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024),
66-
|start| Sieve::new(&start, 1024, false),
74+
|| random_odd_uint::<U1024>(&mut OsRng, 1024),
75+
|start| Sieve::new(start.as_ref(), NonZeroU32::new(1024).unwrap(), false),
6776
BatchSize::SmallInput,
6877
)
6978
});
@@ -84,31 +93,31 @@ fn bench_miller_rabin(c: &mut Criterion) {
8493

8594
group.bench_function("(U128) creation", |b| {
8695
b.iter_batched(
87-
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
88-
MillerRabin::new,
96+
|| random_odd_uint::<U128>(&mut OsRng, 128),
97+
|n| MillerRabin::new(&n),
8998
BatchSize::SmallInput,
9099
)
91100
});
92101

93102
group.bench_function("(U128) random base test (pre-sieved)", |b| {
94103
b.iter_batched(
95-
|| MillerRabin::new(make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
104+
|| MillerRabin::new(&make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
96105
|mr| mr.test_random_base(&mut OsRng),
97106
BatchSize::SmallInput,
98107
)
99108
});
100109

101110
group.bench_function("(U1024) creation", |b| {
102111
b.iter_batched(
103-
|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024),
104-
MillerRabin::new,
112+
|| random_odd_uint::<U1024>(&mut OsRng, 1024),
113+
|n| MillerRabin::new(&n),
105114
BatchSize::SmallInput,
106115
)
107116
});
108117

109118
group.bench_function("(U1024) random base test (pre-sieved)", |b| {
110119
b.iter_batched(
111-
|| MillerRabin::new(make_presieved_num::<{ nlimbs!(1024) }>(&mut OsRng)),
120+
|| MillerRabin::new(&make_presieved_num::<{ nlimbs!(1024) }>(&mut OsRng)),
112121
|mr| mr.test_random_base(&mut OsRng),
113122
BatchSize::SmallInput,
114123
)
@@ -193,39 +202,39 @@ fn bench_presets(c: &mut Criterion) {
193202

194203
group.bench_function("(U128) Prime test", |b| {
195204
b.iter_batched(
196-
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
197-
|num| is_prime_with_rng(&mut OsRng, &num),
205+
|| random_odd_uint::<U128>(&mut OsRng, 128),
206+
|num| is_prime_with_rng(&mut OsRng, num.as_ref()),
198207
BatchSize::SmallInput,
199208
)
200209
});
201210

202211
group.bench_function("(U128) Safe prime test", |b| {
203212
b.iter_batched(
204-
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
205-
|num| is_safe_prime_with_rng(&mut OsRng, &num),
213+
|| random_odd_uint::<U128>(&mut OsRng, 128),
214+
|num| is_safe_prime_with_rng(&mut OsRng, num.as_ref()),
206215
BatchSize::SmallInput,
207216
)
208217
});
209218

210219
let mut rng = make_rng();
211220
group.bench_function("(U128) Random prime", |b| {
212-
b.iter(|| generate_prime_with_rng::<{ nlimbs!(128) }>(&mut rng, None))
221+
b.iter(|| generate_prime_with_rng::<U128>(&mut rng, 128))
213222
});
214223

215224
let mut rng = make_rng();
216225
group.bench_function("(U1024) Random prime", |b| {
217-
b.iter(|| generate_prime_with_rng::<{ nlimbs!(1024) }>(&mut rng, None))
226+
b.iter(|| generate_prime_with_rng::<U1024>(&mut rng, 1024))
218227
});
219228

220229
let mut rng = make_rng();
221230
group.bench_function("(U128) Random safe prime", |b| {
222-
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(128) }>(&mut rng, None))
231+
b.iter(|| generate_safe_prime_with_rng::<U128>(&mut rng, 128))
223232
});
224233

225234
group.sample_size(20);
226235
let mut rng = make_rng();
227236
group.bench_function("(U1024) Random safe prime", |b| {
228-
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(1024) }>(&mut rng, None))
237+
b.iter(|| generate_safe_prime_with_rng::<U1024>(&mut rng, 1024))
229238
});
230239

231240
group.finish();
@@ -235,19 +244,19 @@ fn bench_presets(c: &mut Criterion) {
235244

236245
let mut rng = make_rng();
237246
group.bench_function("(U128) Random safe prime", |b| {
238-
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(128) }>(&mut rng, None))
247+
b.iter(|| generate_safe_prime_with_rng::<U128>(&mut rng, 128))
239248
});
240249

241250
// The performance should scale with the prime size, not with the Uint size.
242251
// So we should strive for this test's result to be as close as possible
243252
// to that of the previous one and as far away as possible from the next one.
244253
group.bench_function("(U256) Random 128 bit safe prime", |b| {
245-
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(256) }>(&mut rng, Some(128)))
254+
b.iter(|| generate_safe_prime_with_rng::<U256>(&mut rng, 128))
246255
});
247256

248257
// The upper bound for the previous test.
249258
group.bench_function("(U256) Random 256 bit safe prime", |b| {
250-
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(256) }>(&mut rng, None))
259+
b.iter(|| generate_safe_prime_with_rng::<U256>(&mut rng, 256))
251260
});
252261

253262
group.finish();
@@ -257,9 +266,9 @@ fn bench_presets(c: &mut Criterion) {
257266
fn bench_gmp(c: &mut Criterion) {
258267
let mut group = c.benchmark_group("GMP");
259268

260-
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> Integer {
261-
let num = random_odd_uint::<L>(rng, Uint::<L>::BITS);
262-
Integer::from_digits(num.as_words(), Order::Lsf)
269+
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> GmpInteger {
270+
let num = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS).get();
271+
GmpInteger::from_digits(num.as_words(), Order::Lsf)
263272
}
264273

265274
group.bench_function("(U128) Random prime", |b| {

src/hazmat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod sieve;
1414

1515
pub use lucas::{lucas_test, AStarBase, BruteForceBase, LucasBase, LucasCheck, SelfridgeBase};
1616
pub use miller_rabin::MillerRabin;
17-
pub use sieve::{random_odd_uint, Sieve};
17+
pub use sieve::{random_odd_integer, Sieve};
1818

1919
/// Possible results of various primality tests.
2020
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

src/hazmat/gcd.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
use crypto_bigint::{Limb, NonZero, Uint, Word};
1+
use crypto_bigint::{Integer, Limb, NonZero, Word};
22

33
/// Calculates the greatest common divisor of `n` and `m`.
44
/// By definition, `gcd(0, m) == m`.
55
/// `n` must be non-zero.
6-
pub(crate) fn gcd_vartime<const L: usize>(n: &Uint<L>, m: Word) -> Word {
6+
pub(crate) fn gcd_vartime<T: Integer>(n: &T, m: Word) -> Word {
77
// This is an internal function, and it will never be called with `m = 0`.
88
// Allowing `m = 0` would require us to have the return type of `Uint<L>`
99
// (since `gcd(n, 0) = n`).
1010
debug_assert!(m != 0);
1111

1212
// This we can check since it doesn't affect the return type,
1313
// even though `n` will not be 0 either in the application.
14-
if n == &Uint::<L>::ZERO {
14+
if n.is_zero().into() {
1515
return m;
1616
}
1717

@@ -23,7 +23,7 @@ pub(crate) fn gcd_vartime<const L: usize>(n: &Uint<L>, m: Word) -> Word {
2323
} else {
2424
// In this branch `n` is `Word::BITS` bits or shorter,
2525
// so we can safely take the first limb.
26-
let n = n.as_words()[0];
26+
let n = n.as_ref()[0].0;
2727
if n > m {
2828
(n, m)
2929
} else {

0 commit comments

Comments
 (0)