-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix
random_mod
performance for small moduli; NonZero
moduli
Changes the modulus for `random_mod` to be `NonZero`. Changes the algorithm used by `random_mod` to generate a number that can be represented by the same number of bytes as the modulus. Such a number can still be larger than the modulus, but is much more likely not to overflow than a "full-width" number provided the modulus is small relative to the width. Closes #3
- Loading branch information
Showing
7 changed files
with
102 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ mod bit_and; | |
mod bit_not; | ||
mod bit_or; | ||
mod bit_xor; | ||
mod bits; | ||
mod cmp; | ||
mod encoding; | ||
mod from; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
use super::{Limb, BIT_SIZE}; | ||
|
||
impl Limb { | ||
/// Calculate the number of bits needed to represent this number. | ||
pub const fn bits(self) -> usize { | ||
BIT_SIZE - (self.0.leading_zeros() as usize) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,45 @@ | ||
//! Random number generator support | ||
|
||
use super::Limb; | ||
use super::{Limb, BYTE_SIZE}; | ||
use crate::{Encoding, NonZero, Random, RandomMod}; | ||
use rand_core::{CryptoRng, RngCore}; | ||
use subtle::ConstantTimeLess; | ||
|
||
impl Limb { | ||
/// Generate a random limb | ||
impl Random for Limb { | ||
#[cfg(target_pointer_width = "32")] | ||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))] | ||
pub fn random(mut rng: impl CryptoRng + RngCore) -> Self { | ||
fn random(mut rng: impl CryptoRng + RngCore) -> Self { | ||
Self(rng.next_u32()) | ||
} | ||
|
||
/// Generate a random limb | ||
#[cfg(target_pointer_width = "64")] | ||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))] | ||
pub fn random(mut rng: impl CryptoRng + RngCore) -> Self { | ||
fn random(mut rng: impl CryptoRng + RngCore) -> Self { | ||
Self(rng.next_u64()) | ||
} | ||
} | ||
|
||
impl RandomMod for Limb { | ||
fn random_mod(mut rng: impl CryptoRng + RngCore, modulus: &NonZero<Self>) -> Self { | ||
let mut bytes = <Self as Encoding>::Repr::default(); | ||
|
||
// TODO(tarcieri): use `div_ceil` when available | ||
// See: https://github.com/rust-lang/rust/issues/88581 | ||
let mut n_bytes = modulus.bits() / 8; | ||
|
||
// Ensure the randomly generated value can always be larger than | ||
// the modulus in order to ensure a uniform distribution | ||
if n_bytes < BYTE_SIZE { | ||
n_bytes += 1; | ||
} | ||
|
||
loop { | ||
rng.fill_bytes(&mut bytes[..n_bytes]); | ||
let n = Limb::from_le_bytes(bytes); | ||
|
||
if n.ct_lt(modulus).into() { | ||
return n; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters