Skip to content

Commit

Permalink
Dissolve UintLike, Integer supports all we need now
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Dec 28, 2023
1 parent e97198a commit e9c3319
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 235 deletions.
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 = ["alloc", "rand_core"] }
crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint@42ea8e6965573e8039294adfaa6a59909859eadd", default-features = false, features = ["alloc", "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
25 changes: 17 additions & 8 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};
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 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, Uint::<L>::BITS, false)
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 @@ -42,7 +51,7 @@ fn bench_sieve(c: &mut Criterion) {
group.bench_function("(U128) creation", |b| {
b.iter_batched(
|| random_odd_uint::<Uint<{ nlimbs!(128) }>>(&mut OsRng, 128),
|start| Sieve::new(start.as_ref(), 128, false),
|start| Sieve::new(start.as_ref(), NonZeroU32::new(128).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand All @@ -63,7 +72,7 @@ fn bench_sieve(c: &mut Criterion) {
group.bench_function("(U1024) creation", |b| {
b.iter_batched(
|| random_odd_uint::<Uint<{ nlimbs!(1024) }>>(&mut OsRng, 1024),
|start| Sieve::new(start.as_ref(), 1024, false),
|start| Sieve::new(start.as_ref(), NonZeroU32::new(1024).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand Down Expand Up @@ -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 {
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> GmpInteger {
let num = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS).get();
Integer::from_digits(num.as_words(), Order::Lsf)
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
24 changes: 10 additions & 14 deletions src/hazmat/lucas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use super::{
jacobi::{jacobi_symbol_vartime, JacobiSymbol},
Primality,
};
use crate::UintLike;

/// The maximum number of attempts to find `D` such that `(D/n) == -1`.
// This is widely believed to be impossible.
Expand All @@ -28,7 +27,7 @@ pub trait LucasBase {
/// Given an odd integer, returns `Ok((P, abs(Q), is_negative(Q)))` on success,
/// or `Err(Primality)` if the primality for the given integer was discovered
/// during the search for a base.
fn generate<T: UintLike>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality>;
fn generate<T: Integer>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality>;
}

/// "Method A" for selecting the base given in Baillie & Wagstaff[^Baillie1980],
Expand All @@ -46,7 +45,7 @@ pub trait LucasBase {
pub struct SelfridgeBase;

impl LucasBase for SelfridgeBase {
fn generate<T: UintLike>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: Integer>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
let mut abs_d = 5;
let mut d_is_negative = false;
let n_is_small = n.bits_vartime() < Word::BITS; // if true, `n` fits into one `Word`
Expand Down Expand Up @@ -111,7 +110,7 @@ impl LucasBase for SelfridgeBase {
pub struct AStarBase;

impl LucasBase for AStarBase {
fn generate<T: UintLike>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: Integer>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
SelfridgeBase.generate(n).map(|(p, abs_q, q_is_negative)| {
if abs_q == 1 && q_is_negative {
(5, 5, false)
Expand All @@ -134,7 +133,7 @@ impl LucasBase for AStarBase {
pub struct BruteForceBase;

impl LucasBase for BruteForceBase {
fn generate<T: UintLike>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: Integer>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
let mut p = 3;
let mut attempts = 0;

Expand Down Expand Up @@ -179,7 +178,7 @@ impl LucasBase for BruteForceBase {
}

/// For the given odd `n`, finds `s` and odd `d` such that `n + 1 == 2^s * d`.
fn decompose<T: UintLike>(n: &Odd<T>) -> (u32, Odd<T>) {
fn decompose<T: Integer>(n: &Odd<T>) -> (u32, Odd<T>) {
// Need to be careful here since `n + 1` can overflow.
// Instead of adding 1 and counting trailing 0s, we count trailing ones on the original `n`.

Expand Down Expand Up @@ -283,7 +282,7 @@ pub enum LucasCheck {
/// Performs the primality test based on Lucas sequence.
/// See [`LucasCheck`] for possible checks, and the implementors of [`LucasBase`]
/// for the corresponding bases.
pub fn lucas_test<T: UintLike>(
pub fn lucas_test<T: Integer>(
candidate: &Odd<T>,
base: impl LucasBase,
check: LucasCheck,
Expand Down Expand Up @@ -340,7 +339,7 @@ pub fn lucas_test<T: UintLike>(

// Some constants in Montgomery form

let params = <T as Integer>::Monty::new_params(candidate.clone());
let params = <T as Integer>::Monty::new_params_vartime(candidate.clone());

let zero = <T as Integer>::Monty::zero(params.clone());
let one = <T as Integer>::Monty::one(params.clone());
Expand Down Expand Up @@ -501,18 +500,15 @@ mod tests {

use alloc::format;

use crypto_bigint::{Odd, Uint, Word, U128, U64};
use crypto_bigint::{Integer, Odd, Uint, Word, U128, U64};

#[cfg(feature = "tests-exhaustive")]
use num_prime::nt_funcs::is_prime64;

use super::{
decompose, lucas_test, AStarBase, BruteForceBase, LucasBase, LucasCheck, SelfridgeBase,
};
use crate::{
hazmat::{primes, pseudoprimes, Primality},
UintLike,
};
use crate::hazmat::{primes, pseudoprimes, Primality};

#[test]
fn bases_derived_traits() {
Expand Down Expand Up @@ -557,7 +553,7 @@ mod tests {
struct TestBase;

impl LucasBase for TestBase {
fn generate<T: UintLike>(&self, _n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: Integer>(&self, _n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
Ok((5, 5, false))
}
}
Expand Down
23 changes: 10 additions & 13 deletions src/hazmat/miller_rabin.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//! Miller-Rabin primality test.
use crypto_bigint::{Integer, Monty, NonZero, Odd, PowBoundedExp, Square};
use crypto_bigint::{Integer, Monty, NonZero, Odd, PowBoundedExp, RandomMod, Square};
use rand_core::CryptoRngCore;

use super::Primality;
use crate::UintLike;

/// Precomputed data used to perform Miller-Rabin primality test[^Pomerance1980].
/// The numbers that pass it are commonly called "strong probable primes"
Expand All @@ -15,7 +14,7 @@ use crate::UintLike;
/// Math. Comp. 35 1003-1026 (1980),
/// DOI: [10.2307/2006210](https://dx.doi.org/10.2307/2006210)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MillerRabin<T: UintLike> {
pub struct MillerRabin<T: Integer> {
candidate: T,
bit_length: u32,
montgomery_params: <<T as Integer>::Monty as Monty>::Params,
Expand All @@ -25,10 +24,10 @@ pub struct MillerRabin<T: UintLike> {
d: T,
}

impl<T: UintLike> MillerRabin<T> {
impl<T: Integer + RandomMod> MillerRabin<T> {
/// Initializes a Miller-Rabin test for `candidate`.
pub fn new(candidate: Odd<T>) -> Self {
let params = <T as Integer>::Monty::new_params(candidate.clone());
let params = <T as Integer>::Monty::new_params_vartime(candidate.clone());
let one = <T as Integer>::Monty::one(params.clone());
let minus_one = -one.clone();

Expand Down Expand Up @@ -118,19 +117,17 @@ impl<T: UintLike> MillerRabin<T> {
mod tests {

use alloc::format;
use core::num::NonZeroU32;

use crypto_bigint::{Odd, Uint, U1024, U128, U1536, U64};
use crypto_bigint::{Integer, Odd, RandomMod, Uint, U1024, U128, U1536, U64};
use rand_chacha::ChaCha8Rng;
use rand_core::{CryptoRngCore, OsRng, SeedableRng};

#[cfg(feature = "tests-exhaustive")]
use num_prime::nt_funcs::is_prime64;

use super::MillerRabin;
use crate::{
hazmat::{primes, pseudoprimes, random_odd_uint, Sieve},
UintLike,
};
use crate::hazmat::{primes, pseudoprimes, random_odd_integer, Sieve};

#[test]
fn miller_rabin_derived_traits() {
Expand All @@ -152,7 +149,7 @@ mod tests {
pseudoprimes::STRONG_BASE_2.iter().any(|x| *x == num)
}

fn random_checks<T: UintLike>(
fn random_checks<T: Integer + RandomMod>(
rng: &mut impl CryptoRngCore,
mr: &MillerRabin<T>,
count: usize,
Expand Down Expand Up @@ -192,8 +189,8 @@ mod tests {
#[test]
fn trivial() {
let mut rng = ChaCha8Rng::from_seed(*b"01234567890123456789012345678901");
let start = random_odd_uint::<U1024>(&mut rng, 1024);
for num in Sieve::new(start.as_ref(), 1024, false).take(10) {
let start = random_odd_integer::<U1024>(&mut rng, NonZeroU32::new(1024).unwrap());
for num in Sieve::new(start.as_ref(), NonZeroU32::new(1024).unwrap(), false).take(10) {
let mr = MillerRabin::new(Odd::new(num).unwrap());

// Trivial tests, must always be true.
Expand Down
Loading

0 comments on commit e9c3319

Please sign in to comment.