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
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
//! ### Random number generation
//!
//! When the `rand_core` or `rand` features of this crate are enabled, it's
//! possible to generate random numbers using any CSRNG by using the
//! possible to generate random numbers using any RNG by using the
//! [`Random`] trait:
//!
//! ```
Expand Down
8 changes: 4 additions & 4 deletions src/limb/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

use super::Limb;
use crate::{Encoding, NonZero, Random, RandomMod};
use rand_core::CryptoRngCore;
use rand_core::RngCore;
use subtle::ConstantTimeLess;

impl Random for Limb {
#[cfg(target_pointer_width = "32")]
fn random(rng: &mut impl CryptoRngCore) -> Self {
fn random(rng: &mut impl RngCore) -> Self {
Self(rng.next_u32())
}

#[cfg(target_pointer_width = "64")]
fn random(rng: &mut impl CryptoRngCore) -> Self {
fn random(rng: &mut impl RngCore) -> Self {
Self(rng.next_u64())
}
}

impl RandomMod for Limb {
fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self {
fn random_mod(rng: &mut impl RngCore, modulus: &NonZero<Self>) -> Self {
let mut bytes = <Self as Encoding>::Repr::default();

let n_bits = modulus.bits() as usize;
Expand Down
4 changes: 2 additions & 2 deletions src/modular/const_monty_form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use core::{fmt::Debug, marker::PhantomData};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};

#[cfg(feature = "rand_core")]
use crate::{rand_core::CryptoRngCore, Random, RandomMod};
use crate::{rand_core::RngCore, Random, RandomMod};

#[cfg(feature = "serde")]
use {
Expand Down Expand Up @@ -207,7 +207,7 @@ where
MOD: ConstMontyParams<LIMBS>,
{
#[inline]
fn random(rng: &mut impl CryptoRngCore) -> Self {
fn random(rng: &mut impl RngCore) -> Self {
Self::new(&Uint::random_mod(rng, MOD::MODULUS.as_nz_ref()))
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/non_zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use crate::{ArrayEncoding, ByteArray};

#[cfg(feature = "rand_core")]
use {crate::Random, rand_core::CryptoRngCore};
use {crate::Random, rand_core::RngCore};

#[cfg(feature = "serde")]
use serdect::serde::{
Expand Down Expand Up @@ -232,8 +232,7 @@ impl<T> Random for NonZero<T>
where
T: Random + Zero,
{
/// Generate a random `NonZero<T>`.
fn random(mut rng: &mut impl CryptoRngCore) -> Self {
fn random(mut rng: &mut impl RngCore) -> Self {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

// Use rejection sampling to eliminate zero values.
// While this method isn't constant-time, the attacker shouldn't learn
// anything about unrelated outputs so long as `rng` is a CSRNG.
Expand Down
6 changes: 3 additions & 3 deletions src/odd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use crate::BoxedUint;

#[cfg(feature = "rand_core")]
use {crate::Random, rand_core::CryptoRngCore};
use {crate::Random, rand_core::RngCore};

#[cfg(all(feature = "alloc", feature = "rand_core"))]
use crate::RandomBits;
Expand Down Expand Up @@ -153,7 +153,7 @@ impl PartialOrd<Odd<BoxedUint>> for BoxedUint {
#[cfg(feature = "rand_core")]
impl<const LIMBS: usize> Random for Odd<Uint<LIMBS>> {
/// Generate a random `Odd<Uint<T>>`.
fn random(rng: &mut impl CryptoRngCore) -> Self {
fn random(rng: &mut impl RngCore) -> Self {
let mut ret = Uint::random(rng);
ret.limbs[0] |= Limb::ONE;
Odd(ret)
Expand All @@ -163,7 +163,7 @@ impl<const LIMBS: usize> Random for Odd<Uint<LIMBS>> {
#[cfg(all(feature = "alloc", feature = "rand_core"))]
impl Odd<BoxedUint> {
/// Generate a random `Odd<Uint<T>>`.
pub fn random(rng: &mut impl CryptoRngCore, bit_length: u32) -> Self {
pub fn random(rng: &mut impl RngCore, bit_length: u32) -> Self {
let mut ret = BoxedUint::random_bits(rng, bit_length);
ret.limbs[0] |= Limb::ONE;
Odd(ret)
Expand Down
40 changes: 21 additions & 19 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

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

The doc comment is no longer accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a note

}

/// Possible errors of the methods in [`RandomBits`] trait.
Expand Down Expand Up @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

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

The doc comment is no longer accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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>;
Copy link
Contributor

Choose a reason for hiding this comment

The 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,
Copy link
Contributor

Choose a reason for hiding this comment

The 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>;
Expand All @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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`.
Expand Down
26 changes: 12 additions & 14 deletions src/uint/boxed/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand Down
25 changes: 10 additions & 15 deletions src/uint/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The 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 {
Expand All @@ -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> {
Expand Down Expand Up @@ -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> {
Expand All @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/wrapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::{
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};

#[cfg(feature = "rand_core")]
use {crate::Random, rand_core::CryptoRngCore};
use {crate::Random, rand_core::RngCore};

#[cfg(feature = "serde")]
use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
Expand Down Expand Up @@ -259,7 +259,7 @@ impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {

#[cfg(feature = "rand_core")]
impl<T: Random> Random for Wrapping<T> {
fn random(rng: &mut impl CryptoRngCore) -> Self {
fn random(rng: &mut impl RngCore) -> Self {
Wrapping(Random::random(rng))
}
}
Expand Down
Loading