Skip to content

Commit 45152ad

Browse files
authored
Merge pull request #38 from fjarri/update-crypto-bigint
Bump `crypto-bigint` to 0.6.0-pre.5
2 parents 2379c91 + 685a6ee commit 45152ad

File tree

12 files changed

+429
-307
lines changed

12 files changed

+429
-307
lines changed

.github/workflows/crypto-primes.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
matrix:
1919
rust:
20-
- 1.65.0 # MSRV
20+
- 1.73.0 # MSRV
2121
- stable
2222
target:
2323
- wasm32-unknown-unknown
@@ -134,6 +134,6 @@ jobs:
134134
- uses: actions/checkout@v3
135135
- uses: actions-rs/toolchain@v1
136136
with:
137-
toolchain: 1.65.0
137+
toolchain: 1.73.0
138138
profile: minimal
139139
- run: cargo build --all-features --benches

CHANGELOG.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ 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.5.1] - Unreleased
7+
## [0.6.0-pre.0] - Unreleased
88

9-
### Fixed
9+
### Changed
1010

11-
- Bumped `crypto-bigint` to 0.5.4. ([#35])
11+
- Bumped `crypto-bigint` to 0.6.0-pre.5. ([#38])
12+
- 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])
14+
- All bit length-type parameters take `u32` instead of `usize`. (#[38])
1215

1316

14-
[#35]: https://github.com/entropyxyz/crypto-primes/pull/35
17+
[#35]: https://github.com/entropyxyz/crypto-primes/pull/38
1518

1619

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

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
[package]
22
name = "crypto-primes"
3-
version = "0.5.0"
3+
version = "0.6.0-pre.0"
44
edition = "2021"
55
license = "Apache-2.0 OR MIT"
66
description = "Random prime number generation and primality checking library"
77
repository = "https://github.com/entropyxyz/crypto-primes"
88
readme = "README.md"
99
categories = ["cryptography", "no-std"]
10-
rust-version = "1.65"
10+
rust-version = "1.73"
1111

1212
[dependencies]
13-
crypto-bigint = { version = "0.5.4", default-features = false, features = ["rand_core"] }
13+
crypto-bigint = { version = "0.6.0-pre.5", 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: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
2-
use crypto_bigint::{nlimbs, Uint, U1024};
2+
use crypto_bigint::{nlimbs, Odd, Uint, U1024};
33
use rand_chacha::ChaCha8Rng;
44
use rand_core::{CryptoRngCore, OsRng, SeedableRng};
55

@@ -23,13 +23,13 @@ fn make_rng() -> ChaCha8Rng {
2323
}
2424

2525
fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<L> {
26-
let start: Uint<L> = random_odd_uint(rng, Uint::<L>::BITS);
26+
let start = random_odd_uint::<L>(rng, Uint::<L>::BITS);
2727
Sieve::new(&start, Uint::<L>::BITS, false)
2828
}
2929

30-
fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Uint<L> {
30+
fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Odd<Uint<L>> {
3131
let mut sieve = make_sieve(rng);
32-
sieve.next().unwrap()
32+
Odd::new(sieve.next().unwrap()).unwrap()
3333
}
3434

3535
fn bench_sieve(c: &mut Criterion) {
@@ -85,14 +85,14 @@ fn bench_miller_rabin(c: &mut Criterion) {
8585
group.bench_function("(U128) creation", |b| {
8686
b.iter_batched(
8787
|| random_odd_uint::<{ nlimbs!(128) }>(&mut OsRng, 128),
88-
|start| MillerRabin::new(&start),
88+
MillerRabin::new,
8989
BatchSize::SmallInput,
9090
)
9191
});
9292

9393
group.bench_function("(U128) random base test (pre-sieved)", |b| {
9494
b.iter_batched(
95-
|| MillerRabin::new(&make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
95+
|| MillerRabin::new(make_presieved_num::<{ nlimbs!(128) }>(&mut OsRng)),
9696
|mr| mr.test_random_base(&mut OsRng),
9797
BatchSize::SmallInput,
9898
)
@@ -101,14 +101,14 @@ fn bench_miller_rabin(c: &mut Criterion) {
101101
group.bench_function("(U1024) creation", |b| {
102102
b.iter_batched(
103103
|| random_odd_uint::<{ nlimbs!(1024) }>(&mut OsRng, 1024),
104-
|start| MillerRabin::new(&start),
104+
MillerRabin::new,
105105
BatchSize::SmallInput,
106106
)
107107
});
108108

109109
group.bench_function("(U1024) random base test (pre-sieved)", |b| {
110110
b.iter_batched(
111-
|| MillerRabin::new(&make_presieved_num::<{ nlimbs!(1024) }>(&mut OsRng)),
111+
|| MillerRabin::new(make_presieved_num::<{ nlimbs!(1024) }>(&mut OsRng)),
112112
|mr| mr.test_random_base(&mut OsRng),
113113
BatchSize::SmallInput,
114114
)
@@ -171,12 +171,13 @@ fn bench_lucas(c: &mut Criterion) {
171171
// - V_{d * 2^t} checked for t == 0..s-1, but no V = 0 found
172172
// - s = 5, so the previous step has multiple checks
173173
// - Q != 1 (since we're using Selfridge base)
174-
let slow_path = U1024::from_be_hex(concat![
174+
let slow_path = Odd::new(U1024::from_be_hex(concat![
175175
"D1CB9F1B6F3414A4B40A7E51C53C6AE4689DFCDC49FF875E7066A229D704EA8E",
176176
"6B674231D8C5974001673C3CE7FF9D377C8564E5182165A23434BC7B7E6C0419",
177177
"FD25C9921B0E9C90AF2570DB0772E1A9C82ACABBC8FC0F0864CE8A12124FA29B",
178178
"7F870924041DFA13EE5F5541C1BF96CA679EFAE2C96F5F4E9DF6007185198F5F"
179-
]);
179+
]))
180+
.unwrap();
180181

181182
group.bench_function("(U1024) Selfridge base, strong check, slow path", |b| {
182183
b.iter(|| {
@@ -257,7 +258,7 @@ fn bench_gmp(c: &mut Criterion) {
257258
let mut group = c.benchmark_group("GMP");
258259

259260
fn random<const L: usize>(rng: &mut impl CryptoRngCore) -> Integer {
260-
let num: Uint<L> = random_odd_uint(rng, Uint::<L>::BITS);
261+
let num = random_odd_uint::<L>(rng, Uint::<L>::BITS);
261262
Integer::from_digits(num.as_words(), Order::Lsf)
262263
}
263264

src/hazmat/gcd.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use crypto_bigint::{Limb, NonZero, Uint};
1+
use crypto_bigint::{Limb, NonZero, Uint, 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<const L: usize>(n: &Uint<L>, m: u32) -> u32 {
6+
pub(crate) fn gcd_vartime<const L: usize>(n: &Uint<L>, 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`).
@@ -16,16 +16,14 @@ pub(crate) fn gcd<const L: usize>(n: &Uint<L>, m: u32) -> u32 {
1616
}
1717

1818
// Normalize input: the resulting (a, b) are both small, a >= b, and b != 0.
19-
let (mut a, mut b): (u32, u32) = if n.bits() > (u32::BITS as usize) {
19+
let (mut a, mut b): (Word, Word) = if n.bits() > Word::BITS {
2020
// `m` is non-zero, so we can unwrap.
21-
let (_quo, n) = n.div_rem_limb(NonZero::new(Limb::from(m)).unwrap());
22-
// `n` is a remainder of a division by `u32`, so it can be safely cast to `u32`.
23-
let b: u32 = n.0.try_into().unwrap();
24-
(m, b)
21+
let r = n.rem_limb(NonZero::new(Limb::from(m)).expect("divisor should be non-zero here"));
22+
(m, r.0)
2523
} else {
26-
// In this branch `n` is 32 bits or shorter,
27-
// so we can safely take the first limb and cast it to u32.
28-
let n: u32 = n.as_words()[0].try_into().unwrap();
24+
// In this branch `n` is `Word::BITS` bits or shorter,
25+
// so we can safely take the first limb.
26+
let n = n.as_words()[0];
2927
if n > m {
3028
(n, m)
3129
} else {
@@ -47,19 +45,22 @@ pub(crate) fn gcd<const L: usize>(n: &Uint<L>, m: u32) -> u32 {
4745

4846
#[cfg(test)]
4947
mod tests {
50-
use crypto_bigint::{Encoding, U128};
48+
use crypto_bigint::{Word, U128};
5149
use num_bigint::BigUint;
5250
use num_integer::Integer;
5351
use proptest::prelude::*;
5452

55-
use super::gcd;
53+
use super::gcd_vartime;
5654

5755
#[test]
5856
fn corner_cases() {
59-
assert_eq!(gcd(&U128::from(0u64), 5), 5);
60-
assert_eq!(gcd(&U128::from(1u64), 11 * 13 * 19), 1);
61-
assert_eq!(gcd(&U128::from(7u64 * 11 * 13), 1), 1);
62-
assert_eq!(gcd(&U128::from(7u64 * 11 * 13), 11 * 13 * 19), 11 * 13);
57+
assert_eq!(gcd_vartime(&U128::from(0u64), 5), 5);
58+
assert_eq!(gcd_vartime(&U128::from(1u64), 11 * 13 * 19), 1);
59+
assert_eq!(gcd_vartime(&U128::from(7u64 * 11 * 13), 1), 1);
60+
assert_eq!(
61+
gcd_vartime(&U128::from(7u64 * 11 * 13), 11 * 13 * 19),
62+
11 * 13
63+
);
6364
}
6465

6566
prop_compose! {
@@ -70,16 +71,16 @@ mod tests {
7071

7172
proptest! {
7273
#[test]
73-
fn fuzzy(m in any::<u32>(), n in uint()) {
74+
fn fuzzy(m in any::<Word>(), n in uint()) {
7475
if m == 0 {
7576
return Ok(());
7677
}
7778

7879
let m_bi = BigUint::from(m);
7980
let n_bi = BigUint::from_bytes_be(n.to_be_bytes().as_ref());
80-
let gcd_ref: u32 = n_bi.gcd(&m_bi).try_into().unwrap();
81+
let gcd_ref: Word = n_bi.gcd(&m_bi).try_into().unwrap();
8182

82-
let gcd_test = gcd(&n, m);
83+
let gcd_test = gcd_vartime(&n, m);
8384
assert_eq!(gcd_test, gcd_ref);
8485
}
8586
}

0 commit comments

Comments
 (0)