Skip to content

Commit

Permalink
Address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
pitdicker committed May 15, 2018
1 parent 57536ad commit 727b9cd
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 49 deletions.
2 changes: 2 additions & 0 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
//! - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//! - [`Binomial`] distribution
//! - [`Bernoulli`] distribution, similar to [`Rng::gen_bool`].
//! - Related to positive real-valued quantities that grow exponentially
//! (e.g. prices, incomes, populations):
//! - [`LogNormal`] distribution
Expand Down Expand Up @@ -145,6 +146,7 @@
//! [Floating point implementation]: struct.Standard.html#floating-point-implementation
// distributions
//! [`Alphanumeric`]: struct.Alphanumeric.html
//! [`Bernoulli`]: struct.Bernoulli.html
//! [`Binomial`]: struct.Binomial.html
//! [`ChiSquared`]: struct.ChiSquared.html
//! [`Exp`]: struct.Exp.html
Expand Down
9 changes: 9 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@
//! [`OsRng`], [`EntropyRng`] and [`ReadRng`]. Other RNGs, like [`ThreadRng`]
//! and [`StdRng`], can be used with all methods without concern.
//!
//! One further problem is that if Rand is unable to get any external randomness
//! when initializing an RNG with [`EntropyRng`], it will panic in
//! [`FromEntropy::from_entropy`], and notably in [`thread_rng`]. Except by
//! compromising security, this problem is as unsolvable as running out of
//! memory.
//!
//!
//! # Distinction between Rand and `rand_core`
//!
Expand Down Expand Up @@ -366,6 +372,7 @@ pub trait Rng: RngCore {
/// println!("{}", x);
/// println!("{:?}", rng.gen::<(f64, bool)>());
/// ```
#[inline]
fn gen<T>(&mut self) -> T where Standard: Distribution<T> {
Standard.sample(self)
}
Expand Down Expand Up @@ -943,6 +950,7 @@ pub fn weak_rng() -> XorShiftRng {
/// [`thread_rng`]: fn.thread_rng.html
/// [`Standard`]: distributions/struct.Standard.html
#[cfg(feature="std")]
#[inline]
pub fn random<T>() -> T where Standard: Distribution<T> {
thread_rng().gen()
}
Expand All @@ -963,6 +971,7 @@ pub fn random<T>() -> T where Standard: Distribution<T> {
/// println!("{:?}", sample);
/// ```
#[cfg(feature="std")]
#[inline]
#[deprecated(since="0.4.0", note="renamed to seq::sample_iter")]
pub fn sample<T, I, R>(rng: &mut R, iterable: I, amount: usize) -> Vec<T>
where I: IntoIterator<Item=T>,
Expand Down
99 changes: 55 additions & 44 deletions src/prng/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
//!
//! As mentioned there, PRNGs fall in two broad categories:
//!
//! - [normal PRNGs], primarily designed for simulations
//! - [basic PRNGs], primarily designed for simulations
//! - [CSPRNGs], primarily designed for cryptography
//!
//! In simple terms, the normal PRNGs are often predictable; CSPRNGs should not
//! In simple terms, the basic PRNGs are often predictable; CSPRNGs should not
//! be predictable *when used correctly*.
//!
//! Contents of this documentation:
Expand All @@ -34,9 +34,9 @@
//!
//! # The generators
//!
//! ## Normal pseudo-random number generators (PRNGs)
//! ## Basic pseudo-random number generators (PRNGs)
//!
//! The goal of normal, non-cryptographic PRNGs is usually to find a good
//! The goal of regular, non-cryptographic PRNGs is usually to find a good
//! balance between simplicity, quality, memory usage and performance. These
//! algorithms are very important to Monte Carlo simulations, and also suitable
//! for several other problems such as randomized algorithms and games (except
Expand All @@ -47,13 +47,33 @@
//!
//! | name | full name | performance | memory | quality | period | features |
//! |------|-----------|-------------|--------|---------|--------|----------|
//! | [`XorShiftRng`] | Xorshift 32/128 | ⭐⭐⭐ | 16 bytes | | `u32` * 2<sup>128</sup> - 1 | — |
//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★☆☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2<sup>128</sup> - 1 | — |
//!
// Quality stars [not rendered in documentation]:
// 5. reserved for crypto-level (e.g. ChaCha8, ISAAC)
// 4. good performance on TestU01 and PractRand, good theory
// (e.g. PCG, truncated Xorshift*)
// 3. good performance on TestU01 and PractRand, but "falling through the
// cracks" or insufficient theory (e.g. SFC, Xoshiro)
// 2. imperfect performance on tests or other limiting properties, but not
// terrible (e.g. Xoroshiro128+)
// 1. clear deficiencies in test results, cycle length, theory, or other
// properties (e.g. Xorshift)
//
// Performance stars [not rendered in documentation]:
// Meant to give an indication of relative performance. Roughly follows a log
// scale, based on the performance of `next_u64` on a current i5/i7:
// - 5. 8000 MB/s+
// - 4. 4000 MB/s+
// - 3. 2000 MB/s+
// - 2. 1000 MB/s+
// - 1. < 1000 MB/s
//
//! ## Cryptographically secure pseudo-random number generators (CSPRNGs)
//!
//! CSPRNGs have much higher requirements than normal PRNGs. The primary
//! CSPRNGs have much higher requirements than basic PRNGs. The primary
//! consideration is security. Performance and simplicity are also important,
//! but in general CSPRNGs are more complex and slower than normal PRNGs.
//! but in general CSPRNGs are more complex and slower than regular PRNGs.
//! Quality is no longer a concern, as it is a requirement for a
//! CSPRNG that the output is basically indistinguishable from true randomness
//! since any bias or correlation makes the output more predictable.
Expand All @@ -65,12 +85,12 @@
//!
//! Rand currently provides two trustworthy CSPRNGs and two CSPRNG-like PRNGs:
//!
//! | name | full name | performance | initialization | memory | predictability | backtracking resistance |
//! | name | full name | performance | initialization | memory | predictability | forward secrecy |
//! |------|-----------|--------------|--------------|----------|----------------|-------------------------|
//! | [`ChaChaRng`] | ChaCha20 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 136 bytes | secure | no |
//! | [`Hc128Rng`] | HC-128 | ⭐⭐⭐⭐⭐ | | 4176 bytes | secure | no |
//! | [`IsaacRng`] | ISAAC | ⭐⭐⭐⭐ | | 2072 bytes | unknown | unknown |
//! | [`Isaac64Rng`] | ISAAC-64 | ⭐⭐⭐⭐⭐ | | 4136 bytes| unknown | unknown |
//! | [`ChaChaRng`] | ChaCha20 | ★☆☆☆☆ | fast | 136 bytes | secure | no |
//! | [`Hc128Rng`] | HC-128 | ★★☆☆☆ | slow | 4176 bytes | secure | no |
//! | [`IsaacRng`] | ISAAC | ★★☆☆☆ | slow | 2072 bytes | unknown | unknown |
//! | [`Isaac64Rng`] | ISAAC-64 | ★★☆☆☆ | slow | 4136 bytes| unknown | unknown |
//!
//! It should be noted that the ISAAC generators are only included for
//! historical reasons, they have been with the Rust language since the very
Expand All @@ -83,7 +103,7 @@
//! First it has to be said most PRNGs are very fast, and will rarely be a
//! performance bottleneck.
//!
//! Performance of normal PRNGs is a bit of a subtle thing. It depends a lot on
//! Performance of basic PRNGs is a bit of a subtle thing. It depends a lot on
//! the CPU architecture (32 vs. 64 bits), inlining, and also on the number of
//! available registers. This often causes the performance to be affected by
//! surrounding code due to inlining and other usage of registers.
Expand All @@ -98,21 +118,22 @@
//! CSPRNGs are a little different in that they typically generate a block of
//! output in a cache, and pull outputs from the cache. This allows them to have
//! good amortised performance, and reduces or completely removes the influence
//! of surrounding code on the CSPRNG performance. It does however cause *poor
//! worst case performance*.
//! of surrounding code on the CSPRNG performance.
//!
//! ## State size
//! ### Worst-case performance
//! Because CSPRNGs usually produce a block of values into a cache, they have
//! poor worst case performance (in contrast to regular PRNGs).
//!
//! Normal PRNGs often use very little memory, commonly only a few words, where
//! a *word* is usually either `u32` or `u64`. This is not universal however,
//! for example the historically popular Mersenne Twister MT19937 algorithm
//! requires 2.5 kB of state.
//! Simple PRNGs often use very little memory, commonly only a few words, where
//! a *word* is usually either `u32` or `u64`. This is not true for all
//! non-cryptographic PRNGs however, for example the historically popular
//! Mersenne Twister MT19937 algorithm requires 2.5 kB of state.
//!
//! CSPRNGs typically require more memory; since the seed size is recommended
//! to be at least 192 bits and some more may be required for the algorithm,
//! 256 bits would be approximately the minimum secure size. In practice,
//! CSPRNGs tend to use quite a bit more, [`ChaChaRng`] is relatively small with
//! 136 bytes.
//! 136 bytes of state.
//!
//! ## Initialization time
//!
Expand All @@ -124,7 +145,7 @@
//!
//! # Quality
//!
//! Many normal PRNGs are not much more than a couple of bitwise and arithmetic
//! Many basic PRNGs are not much more than a couple of bitwise and arithmetic
//! operations. Their simplicity gives good performance, but also means there
//! are small regularities hidden in the generated random number stream.
//!
Expand All @@ -146,16 +167,6 @@
//! output values.
//!
//! ### Quality stars:
// 5. reserved for crypto-level (e.g. ChaCha8, ISAAC)
// 4. good performance on TestU01 and PractRand, good theory
// (e.g. PCG, truncated Xorshift*)
// 3. good performance on TestU01 and PractRand, but "falling through the
// cracks" or insufficient theory (e.g. SFC, Xoshiro)
// 2. imperfect performance on tests or other limiting properties, but not
// terrible (e.g. Xoroshiro128+)
// 1. clear deficiencies in test results, cycle length, theory, or other
// properties (e.g. Xorshift)
//!
//! PRNGs with 3 stars or more should be good enough for any purpose.
//! 1 or 2 stars may be good enough for typical apps and games, but do not work
//! well with all algorithms.
Expand Down Expand Up @@ -204,27 +215,27 @@
//!
//! From the context of any PRNG, one can ask the question *given some previous
//! output from the PRNG, is it possible to predict the next output value?*
//! This is an important property in any situation where there might be an
//! adversary.
//!
//! Normal PRNGs tend to fall into one of two categories here; *yes* and
//! *with effort*. In some cases prediction is trivial; e.g. plain Xorshift
//! outputs part of its state without mutation, and prediction is as simple as
//! seeding a new Xorshift generator from four `u32` outputs. The widely-used
//! Mersenne Twister algorithms are also easy to predict, though more samples
//! are required (624 `u32` samples, in the case of MT19937). Other generators,
//! like [PCG](http://www.pcg-random.org/predictability.html) and truncated
//! Xorshift* are harder to predict, but not outside the realm of common
//! mathematics and a desktop PC.
//! Regular PRNGs tend to be predictable, although with varying difficulty. In
//! some cases prediction is trivial, for example plain Xorshift outputs part of
//! its state without mutation, and prediction is as simple as seeding a new
//! Xorshift generator from four `u32` outputs. Other generators, like
//! [PCG](http://www.pcg-random.org/predictability.html) and truncated Xorshift*
//! are harder to predict, but not outside the realm of common mathematics and a
//! desktop PC.
//!
//! The basic security that CSPRNGs must provide is the infeasibility to predict
//! output. This requirement is formalized as the [next-bit test]; this is
//! roughly stated as: given the first *k* bits of a random sequence, the
//! sequence satisfies the next-bit test if there is no algorithm able to
//! predict the next bit using reasonable computing power.
//!
//! A further security that *some* CSPRNGs provide is backtracking resistance:
//! A further security that *some* CSPRNGs provide is forward secrecy:
//! in the event that the CSPRNGs state is revealed at some point, it must be
//! infeasible to reconstruct previous states or output. Note that many CSPRNGs
//! *do not* have backtracking resistance in their usual formulations.
//! *do not* have forward secrecy in their usual formulations.
//!
//! As an outsider it is hard to get a good idea about the security of an
//! algorithm. People in the field of cryptography spend a lot of effort
Expand Down Expand Up @@ -283,7 +294,7 @@
//!
//!
//! [`rngs` module]: ../rngs/index.html
//! [normal PRNGs]: #normal-pseudo-random-number-generators-prngs
//! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs
//! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs
//! [`XorShiftRng`]: struct.XorShiftRng.html
//! [`ChaChaRng`]: chacha/struct.ChaChaRng.html
Expand Down
13 changes: 8 additions & 5 deletions src/rngs/entropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ use rngs::{OsRng, JitterRng};

/// An interface returning random data from external source(s), provided
/// specifically for securely seeding algorithmic generators (PRNGs).
///
///
/// Where possible, `EntropyRng` retrieves random data from the operating
/// system's interface for random numbers ([`OsRng`]); if that fails it will
/// fall back to the [`JitterRng`] entropy collector. In the latter case it will
/// still try to use [`OsRng`] on the next usage.
///
///
/// If no secure source of entropy is available `EntropyRng` will panic on use;
/// i.e. it should never output predictable data.
///
Expand All @@ -32,9 +32,12 @@ use rngs::{OsRng, JitterRng};
///
/// # Panics
///
/// In the extraordinary situation that both [`OsRng`] and [`JitterRng`] fail,
/// only [`try_fill_bytes`] is able to report the error, and only the one from
/// `OsRng`. The other [`RngCore`] methods will panic in case of an error.
/// On most systems, like Windows, Linux, macOS and *BSD on common hardware, it
/// is highly unlikely for both [`OsRng`] and [`JitterRng`] to fail. But on
/// combinations like webassembly without Emscripten or stdweb both sources are
/// unavailable. If both sources fail, only [`try_fill_bytes`] is able to
/// report the error, and only the one from `OsRng`. The other [`RngCore`]
/// methods will panic in case of an error.
///
/// [`OsRng`]: struct.OsRng.html
/// [`JitterRng`]: jitter/struct.JitterRng.html
Expand Down

0 comments on commit 727b9cd

Please sign in to comment.