Skip to content
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
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ categories = ["cryptography", "no-std"]
rust-version = "1.85"

[dependencies]
crypto-bigint = { version = "0.7.0-rc.22", default-features = false, features = ["rand_core"] }
crypto-bigint = { version = "0.7.0-rc.27", default-features = false, features = ["rand_core"] }
libm = { version = "0.2.13", default-features = false, features = ["arch"] }
rand_core = { version = "0.10.0-rc-6", default-features = false }
rand_core = { version = "0.10", default-features = false }
rayon = { version = "1", optional = true, default-features = false }

# Optional dependencies used in tests and benchmarks
Expand All @@ -21,9 +21,9 @@ rug = { version = "1.26", optional = true, default-features = false, features =
glass_pumpkin = { version = "1", optional = true }

[dev-dependencies]
rand = { version = "0.10.0-rc.7", features = ["chacha"] }
rand = { version = "0.10", features = ["chacha"] }
# need `crypto-bigint` with `alloc` to test `BoxedUint`
crypto-bigint = { version = "0.7.0-pre.22", default-features = false, features = ["alloc"] }
crypto-bigint = { version = "0.7.0-pre.27", default-features = false, features = ["alloc"] }
criterion = { version = "0.5", features = ["html_reports"] }
num-modular = { version = "0.5", features = ["num-bigint"] }
num-bigint = "0.4"
Expand Down Expand Up @@ -62,6 +62,6 @@ harness = false
name = "cctv"
harness = false

[patch.crates-io.rand]
git = "https://github.com/rust-random/rand"
branch = "rand_core/v0.10.0-rc-6"
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = ['cfg(cpubits, values("16", "32", "64"))']
Comment on lines +65 to +67
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This little bit is unfortunately a viral property of the cpubits crate. It allows the selection to be overridden using e.g. --cfg cpubits="64", and in order for that to work any crate which uses the cpubits! macro needs this configured (and it needs to include 16 since the macro emits it as an option, even though selecting 16-bits for crypto-bigint will cause a compile error)

24 changes: 12 additions & 12 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ 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 rng),
|| make_sieve::<{ nlimbs(128) }, _>(&mut rng),
|sieve| sieve.take(5).for_each(drop),
BatchSize::SmallInput,
)
Expand All @@ -86,7 +86,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 rng),
|| make_sieve::<{ nlimbs(1024) }, _>(&mut rng),
|sieve| sieve.take(42).for_each(drop),
BatchSize::SmallInput,
)
Expand All @@ -96,7 +96,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 rng),
|| make_sieve::<{ nlimbs(1024) }, _>(&mut rng),
|sieve| sieve.take(42 * 42).for_each(drop),
BatchSize::SmallInput,
)
Expand All @@ -119,7 +119,7 @@ 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 rng.clone())),
|| MillerRabin::new(make_presieved_num::<{ nlimbs(128) }, _>(&mut rng.clone())),
|mr| mr.test_random_base(&mut rng.clone()),
BatchSize::SmallInput,
)
Expand All @@ -135,7 +135,7 @@ 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 rng.clone())),
|| MillerRabin::new(make_presieved_num::<{ nlimbs(1024) }, _>(&mut rng.clone())),
|mr| mr.test_random_base(&mut rng.clone()),
BatchSize::SmallInput,
)
Expand All @@ -148,7 +148,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,
)
Expand All @@ -157,7 +157,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,
)
Expand All @@ -166,7 +166,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,
)
Expand All @@ -175,7 +175,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,
)
Expand All @@ -184,7 +184,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,
)
Expand Down Expand Up @@ -405,15 +405,15 @@ fn bench_gmp(c: &mut Criterion) {

group.bench_function("(U128) Random prime", |b| {
b.iter_batched(
|| random::<{ nlimbs!(128) }, _>(&mut rng),
|| random::<{ nlimbs(128) }, _>(&mut rng),
|n| n.next_prime(),
BatchSize::SmallInput,
)
});

group.bench_function("(U1024) Random prime", |b| {
b.iter_batched(
|| random::<{ nlimbs!(1024) }, _>(&mut rng),
|| random::<{ nlimbs(1024) }, _>(&mut rng),
|n| n.next_prime(),
BatchSize::SmallInput,
)
Expand Down
6 changes: 3 additions & 3 deletions src/fips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! [^FIPS]: FIPS-186.5 standard, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf>

use crypto_bigint::{RandomMod, UnsignedMontyForm};
use crypto_bigint::{RandomMod, UnsignedWithMontyForm};
use rand_core::CryptoRng;

use crate::{
Expand Down Expand Up @@ -84,7 +84,7 @@ impl FipsOptions {
/// [^FIPS]: FIPS-186.5 standard, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf>
pub fn is_prime<T>(rng: &mut (impl CryptoRng + ?Sized), flavor: Flavor, candidate: &T, options: FipsOptions) -> bool
where
T: UnsignedMontyForm + RandomMod,
T: UnsignedWithMontyForm + RandomMod,
{
match flavor {
Flavor::Any => {}
Expand Down Expand Up @@ -128,7 +128,7 @@ where
/// [^FIPS]: FIPS-186.5 standard, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf>
fn is_safe_prime<T>(rng: &mut (impl CryptoRng + ?Sized), candidate: &T, options: FipsOptions) -> bool
where
T: UnsignedMontyForm + RandomMod,
T: UnsignedWithMontyForm + RandomMod,
{
// Since, by the definition of safe prime, `(candidate - 1) / 2` must also be prime,
// and therefore odd, `candidate` has to be equal to 3 modulo 4.
Expand Down
46 changes: 25 additions & 21 deletions src/hazmat/float.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Const-context floating point functions that are currently not present in `core`.

use core::f64;
use crypto_bigint::Uint;
use crypto_bigint::{Uint, cpubits};

/// Calculates `base^exp`.
const fn pow(mut base: f64, mut exp: u32) -> f64 {
Expand Down Expand Up @@ -122,19 +122,19 @@ pub(crate) fn ln<const LIMBS: usize>(x: &Uint<LIMBS>) -> f64 {
// if x is small enough to be cast losslessly to an f64 we use the normal 64-bit log2() from `libm`.
if ilog2_x < f64::MANTISSA_DIGITS {
let x = {
#[cfg(target_pointer_width = "64")]
{
x.as_limbs()[0].0
}
#[cfg(target_pointer_width = "32")]
{
// Small enough to fit in 32 bits
if ilog2_x < 32 {
x.as_limbs()[0].0 as u64
} else {
let lo = x.as_limbs()[0].0;
let hi = x.as_limbs()[1].0;
(hi as u64) << 32 | lo as u64
cpubits! {
32 => {
// Small enough to fit in 32 bits
if ilog2_x < 32 {
x.as_limbs()[0].0 as u64
} else {
let lo = x.as_limbs()[0].0;
let hi = x.as_limbs()[1].0;
(hi as u64) << 32 | lo as u64
}
}
64 => {
x.as_limbs()[0].0
}
}
};
Expand All @@ -145,14 +145,18 @@ pub(crate) fn ln<const LIMBS: usize>(x: &Uint<LIMBS>) -> f64 {
// log2(x) ~ log2(M*2^shift) ~ log2(M) + shift ~ log2(M) + ilog2(x) - 52
let shift = ilog2_x.saturating_sub(f64::MANTISSA_DIGITS - 1);
let shifted_x = x.wrapping_shr_vartime(shift);
#[cfg(target_pointer_width = "64")]
let fraction = shifted_x.as_limbs()[0].0 as f64;
#[cfg(target_pointer_width = "32")]
let fraction = {
let lo = shifted_x.as_limbs()[0].0;
let hi = shifted_x.as_limbs()[1].0;
let fraction = (hi as u64) << 32 | lo as u64;
fraction as f64
cpubits! {
32 => {
let lo = shifted_x.as_limbs()[0].0;
let hi = shifted_x.as_limbs()[1].0;
let fraction = (hi as u64) << 32 | lo as u64;
fraction as f64
}
64 => {
shifted_x.as_limbs()[0].0 as f64
}
}
};

// Fraction is now m * 2^52, where m is the top 53 bits of x. Take log2(m) and subtract 52 to scale the result back
Expand Down
36 changes: 18 additions & 18 deletions src/hazmat/lucas.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Lucas primality test.
use core::num::NonZero;
use crypto_bigint::{Limb, MontyForm, MontyMultiplier, Odd, Square, UnsignedMontyForm, Word};
use crypto_bigint::{Limb, MontyForm, MontyMultiplier, Odd, Square, UnsignedWithMontyForm, Word};

use super::{
Primality,
Expand Down Expand Up @@ -28,7 +28,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: UnsignedMontyForm>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality>;
fn generate<T: UnsignedWithMontyForm>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality>;
}

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

impl LucasBase for SelfridgeBase {
fn generate<T: UnsignedMontyForm>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: UnsignedWithMontyForm>(&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 @@ -109,7 +109,7 @@ impl LucasBase for SelfridgeBase {
pub struct AStarBase;

impl LucasBase for AStarBase {
fn generate<T: UnsignedMontyForm>(&self, n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: UnsignedWithMontyForm>(&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 @@ -131,7 +131,7 @@ impl LucasBase for AStarBase {
pub struct BruteForceBase;

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

Expand Down Expand Up @@ -178,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>(n: &Odd<T>) -> (u32, Odd<T>)
where
T: UnsignedMontyForm,
T: UnsignedWithMontyForm,
{
// 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 @@ -320,7 +320,7 @@ pub enum LucasCheck {
/// [^FIPS]: FIPS-186.5 standard, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf>
pub fn lucas_test<T>(candidate: Odd<T>, base: impl LucasBase, check: LucasCheck) -> Primality
where
T: UnsignedMontyForm,
T: UnsignedWithMontyForm,
{
// The comments in this function use references in `LucasCheck`, plus this one:
//
Expand Down Expand Up @@ -375,10 +375,10 @@ where
let (s, d) = decompose(&candidate);

// Some constants in Montgomery form
let params = <T as UnsignedMontyForm>::MontyForm::new_params_vartime(candidate.clone());
let params = <T as UnsignedWithMontyForm>::MontyForm::new_params_vartime(candidate.clone());

let zero = <T as UnsignedMontyForm>::MontyForm::zero(&params);
let one = <T as UnsignedMontyForm>::MontyForm::one(&params);
let zero = <T as UnsignedWithMontyForm>::MontyForm::zero(&params);
let one = <T as UnsignedWithMontyForm>::MontyForm::one(&params);
let two = one.clone() + &one;
let minus_two = -two.clone();

Expand All @@ -387,7 +387,7 @@ where
let q = if q_is_one {
one.clone()
} else {
let abs_q = <T as UnsignedMontyForm>::MontyForm::new(to_integer(abs_q), &params);
let abs_q = <T as UnsignedWithMontyForm>::MontyForm::new(to_integer(abs_q), &params);
if q_is_negative { -abs_q } else { abs_q }
};

Expand All @@ -396,7 +396,7 @@ where
let p = if p_is_one {
one.clone()
} else {
<T as UnsignedMontyForm>::MontyForm::new(to_integer(p), &params)
<T as UnsignedWithMontyForm>::MontyForm::new(to_integer(p), &params)
};

// Compute d-th element of Lucas sequence (U_d(P, Q), V_d(P, Q)), where:
Expand All @@ -415,15 +415,15 @@ where

// Starting with k = 0
let mut vk = two.clone(); // keeps V_k
let mut uk = <T as UnsignedMontyForm>::MontyForm::zero(&params); // keeps U_k
let mut uk = <T as UnsignedWithMontyForm>::MontyForm::zero(&params); // keeps U_k
let mut qk = one.clone(); // keeps Q^k

let mut temp = <T as UnsignedMontyForm>::MontyForm::zero(&params);
let mut temp = <T as UnsignedWithMontyForm>::MontyForm::zero(&params);

let mut mm = <<T as UnsignedMontyForm>::MontyForm as MontyForm>::Multiplier::from(&params);
let mut mm = <<T as UnsignedWithMontyForm>::MontyForm as MontyForm>::Multiplier::from(&params);

// D in Montgomery representation - note that it can be negative.
let abs_d = <T as UnsignedMontyForm>::MontyForm::new(to_integer(abs_d), &params);
let abs_d = <T as UnsignedWithMontyForm>::MontyForm::new(to_integer(abs_d), &params);
let d_m = if d_is_negative { -abs_d } else { abs_d };

for i in (0..d.bits_vartime()).rev() {
Expand Down Expand Up @@ -606,7 +606,7 @@ mod tests {

use alloc::format;

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

#[cfg(feature = "tests-exhaustive")]
use num_prime::nt_funcs::is_prime64;
Expand Down Expand Up @@ -657,7 +657,7 @@ mod tests {
struct TestBase;

impl LucasBase for TestBase {
fn generate<T: UnsignedMontyForm>(&self, _n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
fn generate<T: UnsignedWithMontyForm>(&self, _n: &Odd<T>) -> Result<(Word, Word, bool), Primality> {
Ok((5, 5, false))
}
}
Expand Down
Loading
Loading