-
Notifications
You must be signed in to change notification settings - Fork 69
Require RngCore
instead of CryptoRngCore
for various random methods
#710
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,7 @@ use subtle::{ | |
}; | ||
|
||
#[cfg(feature = "rand_core")] | ||
use rand_core::CryptoRngCore; | ||
use rand_core::RngCore; | ||
|
||
/// Integers whose representation takes a bounded amount of space. | ||
pub trait Bounded { | ||
|
@@ -282,8 +282,10 @@ pub trait Constants: ConstZero { | |
/// Random number generation support. | ||
#[cfg(feature = "rand_core")] | ||
pub trait Random: Sized { | ||
/// Generate a cryptographically secure random value. | ||
fn random(rng: &mut impl CryptoRngCore) -> Self; | ||
/// Generate a random value. | ||
/// | ||
/// If `rng` is a CSRNG, the generation is cryptographically secure as well. | ||
fn random(rng: &mut impl RngCore) -> Self; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc comment is no longer accurate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a note |
||
} | ||
|
||
/// Possible errors of the methods in [`RandomBits`] trait. | ||
|
@@ -343,42 +345,43 @@ impl core::error::Error for RandomBitsError {} | |
/// Random bits generation support. | ||
#[cfg(feature = "rand_core")] | ||
pub trait RandomBits: Sized { | ||
/// Generate a cryptographically secure random value in range `[0, 2^bit_length)`. | ||
/// Generate a random value in range `[0, 2^bit_length)`. | ||
/// | ||
/// A wrapper for [`RandomBits::try_random_bits`] that panics on error. | ||
fn random_bits(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self { | ||
fn random_bits(rng: &mut impl RngCore, bit_length: u32) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc comment is no longer accurate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added notes for the methods in this trait |
||
Self::try_random_bits(rng, bit_length).expect("try_random_bits() failed") | ||
} | ||
|
||
/// Generate a cryptographically secure random value in range `[0, 2^bit_length)`. | ||
/// Generate a random value in range `[0, 2^bit_length)`. | ||
/// | ||
/// This method is variable time wrt `bit_length`. | ||
fn try_random_bits( | ||
rng: &mut impl CryptoRngCore, | ||
bit_length: u32, | ||
) -> Result<Self, RandomBitsError>; | ||
/// | ||
/// If `rng` is a CSRNG, the generation is cryptographically secure as well. | ||
fn try_random_bits(rng: &mut impl RngCore, bit_length: u32) -> Result<Self, RandomBitsError>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc comment is no longer accurate. |
||
|
||
/// Generate a cryptographically secure random value in range `[0, 2^bit_length)`, | ||
/// Generate a random value in range `[0, 2^bit_length)`, | ||
/// returning an integer with the closest available size to `bits_precision` | ||
/// (if the implementing type supports runtime sizing). | ||
/// | ||
/// A wrapper for [`RandomBits::try_random_bits_with_precision`] that panics on error. | ||
fn random_bits_with_precision( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc comment is no longer accurate. |
||
bit_length: u32, | ||
bits_precision: u32, | ||
) -> Self { | ||
Self::try_random_bits_with_precision(rng, bit_length, bits_precision) | ||
.expect("try_random_bits_with_precision() failed") | ||
} | ||
|
||
/// Generate a cryptographically secure random value in range `[0, 2^bit_length)`, | ||
/// Generate a random value in range `[0, 2^bit_length)`, | ||
/// returning an integer with the closest available size to `bits_precision` | ||
/// (if the implementing type supports runtime sizing). | ||
/// | ||
/// This method is variable time wrt `bit_length`. | ||
/// | ||
/// If `rng` is a CSRNG, the generation is cryptographically secure as well. | ||
fn try_random_bits_with_precision( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
bit_length: u32, | ||
bits_precision: u32, | ||
) -> Result<Self, RandomBitsError>; | ||
|
@@ -387,18 +390,17 @@ pub trait RandomBits: Sized { | |
/// Modular random number generation support. | ||
#[cfg(feature = "rand_core")] | ||
pub trait RandomMod: Sized + Zero { | ||
/// Generate a cryptographically secure random number which is less than | ||
/// a given `modulus`. | ||
/// Generate a random number which is less than a given `modulus`. | ||
/// | ||
/// This function uses rejection sampling, a method which produces an | ||
/// unbiased distribution of in-range values provided the underlying | ||
/// CSRNG is unbiased, but runs in variable-time. | ||
/// RNG is unbiased, but runs in variable-time. | ||
/// | ||
/// The variable-time nature of the algorithm should not pose a security | ||
/// issue so long as the underlying random number generator is truly a | ||
/// issue so long as the underlying random number generator is a | ||
/// CSRNG, where previous outputs are unrelated to subsequent | ||
/// outputs and do not reveal information about the RNG's internal state. | ||
fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self; | ||
fn random_mod(rng: &mut impl RngCore, modulus: &NonZero<Self>) -> Self; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be very careful about this doc comment, as the user may not be aware of what constitutes a CSPRNG. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At any rate, the top-line comment is no longer accurate. |
||
} | ||
|
||
/// Compute `self + rhs mod p`. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,18 +5,15 @@ use crate::{ | |
uint::rand::{random_bits_core, random_mod_core}, | ||
NonZero, RandomBits, RandomBitsError, RandomMod, | ||
}; | ||
use rand_core::CryptoRngCore; | ||
use rand_core::RngCore; | ||
|
||
impl RandomBits for BoxedUint { | ||
fn try_random_bits( | ||
rng: &mut impl CryptoRngCore, | ||
bit_length: u32, | ||
) -> Result<Self, RandomBitsError> { | ||
fn try_random_bits(rng: &mut impl RngCore, bit_length: u32) -> Result<Self, RandomBitsError> { | ||
Self::try_random_bits_with_precision(rng, bit_length, bit_length) | ||
} | ||
|
||
fn try_random_bits_with_precision( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
bit_length: u32, | ||
bits_precision: u32, | ||
) -> Result<Self, RandomBitsError> { | ||
|
@@ -34,16 +31,17 @@ impl RandomBits for BoxedUint { | |
} | ||
|
||
impl RandomMod for BoxedUint { | ||
/// Generate a cryptographically secure random [`BoxedUint`] which is less than a given | ||
/// `modulus`. | ||
/// Generate a random [`BoxedUint`] which is less than a given `modulus`. | ||
/// | ||
/// This function uses rejection sampling, a method which produces an unbiased distribution of | ||
/// in-range values provided the underlying CSRNG is unbiased, but runs in variable-time. | ||
/// This function uses rejection sampling, a method which produces an | ||
/// unbiased distribution of in-range values provided the underlying | ||
/// RNG is unbiased, but runs in variable-time. | ||
/// | ||
/// The variable-time nature of the algorithm should not pose a security issue so long as the | ||
/// underlying random number generator is truly a CSRNG, where previous outputs are unrelated to | ||
/// subsequent outputs and do not reveal information about the RNG's internal state. | ||
fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self { | ||
/// The variable-time nature of the algorithm should not pose a security | ||
/// issue so long as the underlying random number generator is a | ||
/// CSRNG, where previous outputs are unrelated to subsequent | ||
/// outputs and do not reveal information about the RNG's internal state. | ||
fn random_mod(rng: &mut impl RngCore, modulus: &NonZero<Self>) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be very careful about this doc comment, as the user may not be aware of what constitutes a CSPRNG. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At any rate, the top-line comment is no longer accurate. |
||
let mut n = BoxedUint::zero_with_precision(modulus.bits_precision()); | ||
random_mod_core(rng, &mut n, modulus, modulus.bits()); | ||
n | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,11 @@ | |
|
||
use super::{Uint, Word}; | ||
use crate::{Encoding, Limb, NonZero, Random, RandomBits, RandomBitsError, RandomMod, Zero}; | ||
use rand_core::CryptoRngCore; | ||
use rand_core::RngCore; | ||
use subtle::ConstantTimeLess; | ||
|
||
impl<const LIMBS: usize> Random for Uint<LIMBS> { | ||
/// Generate a cryptographically secure random [`Uint`]. | ||
fn random(mut rng: &mut impl CryptoRngCore) -> Self { | ||
fn random(mut rng: &mut impl RngCore) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc comment is no longer accurate. |
||
let mut limbs = [Limb::ZERO; LIMBS]; | ||
|
||
for limb in &mut limbs { | ||
|
@@ -22,7 +21,7 @@ impl<const LIMBS: usize> Random for Uint<LIMBS> { | |
/// | ||
/// NOTE: Assumes that the limbs in the given slice are zeroed! | ||
pub(crate) fn random_bits_core( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
zeroed_limbs: &mut [Limb], | ||
bit_length: u32, | ||
) -> Result<(), RandomBitsError> { | ||
|
@@ -51,15 +50,12 @@ pub(crate) fn random_bits_core( | |
} | ||
|
||
impl<const LIMBS: usize> RandomBits for Uint<LIMBS> { | ||
fn try_random_bits( | ||
rng: &mut impl CryptoRngCore, | ||
bit_length: u32, | ||
) -> Result<Self, RandomBitsError> { | ||
fn try_random_bits(rng: &mut impl RngCore, bit_length: u32) -> Result<Self, RandomBitsError> { | ||
Self::try_random_bits_with_precision(rng, bit_length, Self::BITS) | ||
} | ||
|
||
fn try_random_bits_with_precision( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
bit_length: u32, | ||
bits_precision: u32, | ||
) -> Result<Self, RandomBitsError> { | ||
|
@@ -82,18 +78,17 @@ impl<const LIMBS: usize> RandomBits for Uint<LIMBS> { | |
} | ||
|
||
impl<const LIMBS: usize> RandomMod for Uint<LIMBS> { | ||
/// Generate a cryptographically secure random [`Uint`] which is less than | ||
/// a given `modulus`. | ||
/// Generate a random number which is less than a given `modulus`. | ||
/// | ||
/// This function uses rejection sampling, a method which produces an | ||
/// unbiased distribution of in-range values provided the underlying | ||
/// CSRNG is unbiased, but runs in variable-time. | ||
/// RNG is unbiased, but runs in variable-time. | ||
/// | ||
/// The variable-time nature of the algorithm should not pose a security | ||
/// issue so long as the underlying random number generator is truly a | ||
/// issue so long as the underlying random number generator is a | ||
/// CSRNG, where previous outputs are unrelated to subsequent | ||
/// outputs and do not reveal information about the RNG's internal state. | ||
fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self { | ||
fn random_mod(rng: &mut impl RngCore, modulus: &NonZero<Self>) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See earlier comments. |
||
let mut n = Self::ZERO; | ||
random_mod_core(rng, &mut n, modulus, modulus.bits_vartime()); | ||
n | ||
|
@@ -103,7 +98,7 @@ impl<const LIMBS: usize> RandomMod for Uint<LIMBS> { | |
/// Generic implementation of `random_mod` which can be shared with `BoxedUint`. | ||
// TODO(tarcieri): obtain `n_bits` via a trait like `Integer` | ||
pub(super) fn random_mod_core<T>( | ||
rng: &mut impl CryptoRngCore, | ||
rng: &mut impl RngCore, | ||
n: &mut T, | ||
modulus: &NonZero<T>, | ||
n_bits: u32, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be useful to move aspects of the internal comment to the doc comment now that a CSPRNG is no longer guaranteed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this doc comment and allowed the
Random::random()
one take over.