Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transition to Integer trait #36

Merged
merged 6 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Bumped `crypto-bigint` to 0.6.0-pre.5. ([#38])
- Bumped `crypto-bigint` to 0.6.0-pre.6. ([#38])
- Bumped MSRV to 1.73. (#[38])
- `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])
- `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])
- All bit length-type parameters take `u32` instead of `usize`. (#[38])
- All the API is based on the `Integer` trait instead of `Uint` specifically. (#[38])


[#35]: https://github.com/entropyxyz/crypto-primes/pull/38
[#36]: https://github.com/entropyxyz/crypto-primes/pull/36
[#38]: https://github.com/entropyxyz/crypto-primes/pull/38


## [0.5.0] - 2023-08-20
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ categories = ["cryptography", "no-std"]
rust-version = "1.73"

[dependencies]
crypto-bigint = { version = "0.6.0-pre.5", default-features = false, features = ["rand_core"] }
crypto-bigint = { version = "0.6.0-pre.6", default-features = false, features = ["rand_core"] }
rand_core = { version = "0.6.4", default-features = false }
openssl = { version = "0.10.39", optional = true, features = ["vendored"] }
rug = { version = "1.18", default-features = false, features = ["integer"], optional = true }
Expand Down
73 changes: 41 additions & 32 deletions benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use core::num::NonZeroU32;

use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use crypto_bigint::{nlimbs, Odd, Uint, U1024};
use crypto_bigint::{nlimbs, Integer, Odd, RandomBits, Uint, U1024, U128, U256};
use rand_chacha::ChaCha8Rng;
use rand_core::{CryptoRngCore, OsRng, SeedableRng};

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

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

use crypto_primes::{
generate_prime_with_rng, generate_safe_prime_with_rng,
hazmat::{
lucas_test, random_odd_uint, AStarBase, BruteForceBase, LucasCheck, MillerRabin,
lucas_test, random_odd_integer, AStarBase, BruteForceBase, LucasCheck, MillerRabin,
SelfridgeBase, Sieve,
},
is_prime_with_rng, is_safe_prime_with_rng,
Expand All @@ -22,9 +24,16 @@ fn make_rng() -> ChaCha8Rng {
ChaCha8Rng::from_seed(*b"01234567890123456789012345678901")
}

fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<L> {
let start = random_odd_uint::<L>(rng, Uint::<L>::BITS);
Sieve::new(&start, Uint::<L>::BITS, false)
fn random_odd_uint<T: RandomBits + Integer>(
rng: &mut impl CryptoRngCore,
bit_length: u32,
) -> Odd<T> {
random_odd_integer::<T>(rng, NonZeroU32::new(bit_length).unwrap())
}

fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<Uint<L>> {
let start = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS);
Sieve::new(&start, NonZeroU32::new(Uint::<L>::BITS).unwrap(), false)
}

fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Odd<Uint<L>> {
Expand All @@ -36,13 +45,13 @@ 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::<{ nlimbs!(128) }>(&mut OsRng, 128))
b.iter(|| random_odd_uint::<U128>(&mut OsRng, 128))
});

group.bench_function("(U128) creation", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
|start| Sieve::new(&start, 128, false),
|| random_odd_uint::<U128>(&mut OsRng, 128),
|start| Sieve::new(start.as_ref(), NonZeroU32::new(128).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand All @@ -57,13 +66,13 @@ fn bench_sieve(c: &mut Criterion) {
});

group.bench_function("(U1024) random start", |b| {
b.iter(|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024))
b.iter(|| random_odd_uint::<U1024>(&mut OsRng, 1024))
});

group.bench_function("(U1024) creation", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024),
|start| Sieve::new(&start, 1024, false),
|| random_odd_uint::<U1024>(&mut OsRng, 1024),
|start| Sieve::new(start.as_ref(), NonZeroU32::new(1024).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand All @@ -84,31 +93,31 @@ fn bench_miller_rabin(c: &mut Criterion) {

group.bench_function("(U128) creation", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
MillerRabin::new,
|| random_odd_uint::<U128>(&mut OsRng, 128),
|n| MillerRabin::new(&n),
BatchSize::SmallInput,
)
});

group.bench_function("(U128) random base test (pre-sieved)", |b| {
b.iter_batched(
|| MillerRabin::new(make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
|| MillerRabin::new(&make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
|mr| mr.test_random_base(&mut OsRng),
BatchSize::SmallInput,
)
});

group.bench_function("(U1024) creation", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024),
MillerRabin::new,
|| random_odd_uint::<U1024>(&mut OsRng, 1024),
|n| MillerRabin::new(&n),
BatchSize::SmallInput,
)
});

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

group.bench_function("(U128) Prime test", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
|num| is_prime_with_rng(&mut OsRng, &num),
|| random_odd_uint::<U128>(&mut OsRng, 128),
|num| is_prime_with_rng(&mut OsRng, num.as_ref()),
BatchSize::SmallInput,
)
});

group.bench_function("(U128) Safe prime test", |b| {
b.iter_batched(
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
|num| is_safe_prime_with_rng(&mut OsRng, &num),
|| random_odd_uint::<U128>(&mut OsRng, 128),
|num| is_safe_prime_with_rng(&mut OsRng, num.as_ref()),
BatchSize::SmallInput,
)
});

let mut rng = make_rng();
group.bench_function("(U128) Random prime", |b| {
b.iter(|| generate_prime_with_rng::<{ nlimbs!(128) }>(&mut rng, None))
b.iter(|| generate_prime_with_rng::<U128>(&mut rng, 128))
});

let mut rng = make_rng();
group.bench_function("(U1024) Random prime", |b| {
b.iter(|| generate_prime_with_rng::<{ nlimbs!(1024) }>(&mut rng, None))
b.iter(|| generate_prime_with_rng::<U1024>(&mut rng, 1024))
});

let mut rng = make_rng();
group.bench_function("(U128) Random safe prime", |b| {
b.iter(|| generate_safe_prime_with_rng::<{ nlimbs!(128) }>(&mut rng, None))
b.iter(|| generate_safe_prime_with_rng::<U128>(&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::<{ nlimbs!(1024) }>(&mut rng, None))
b.iter(|| generate_safe_prime_with_rng::<U1024>(&mut rng, 1024))
});

group.finish();
Expand All @@ -235,19 +244,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::<{ nlimbs!(128) }>(&mut rng, None))
b.iter(|| generate_safe_prime_with_rng::<U128>(&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::<{ nlimbs!(256) }>(&mut rng, Some(128)))
b.iter(|| generate_safe_prime_with_rng::<U256>(&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::<{ nlimbs!(256) }>(&mut rng, None))
b.iter(|| generate_safe_prime_with_rng::<U256>(&mut rng, 256))
});

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

fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> Integer {
let num = random_odd_uint::<L>(rng, Uint::<L>::BITS);
Integer::from_digits(num.as_words(), Order::Lsf)
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> GmpInteger {
let num = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS).get();
GmpInteger::from_digits(num.as_words(), Order::Lsf)
}

group.bench_function("(U128) Random prime", |b| {
Expand Down
2 changes: 1 addition & 1 deletion src/hazmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod sieve;

pub use lucas::{lucas_test, AStarBase, BruteForceBase, LucasBase, LucasCheck, SelfridgeBase};
pub use miller_rabin::MillerRabin;
pub use sieve::{random_odd_uint, Sieve};
pub use sieve::{random_odd_integer, Sieve};

/// Possible results of various primality tests.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down
8 changes: 4 additions & 4 deletions src/hazmat/gcd.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use crypto_bigint::{Limb, NonZero, Uint, Word};
use crypto_bigint::{Integer, Limb, NonZero, Word};

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

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

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