Move user-guide documentation to the book
This commit is contained in:
@@ -63,6 +63,8 @@ impl Distribution<f64> for Exp1 {
|
||||
///
|
||||
/// This distribution has density function: `f(x) = lambda * exp(-lambda * x)`
|
||||
/// for `x > 0`.
|
||||
///
|
||||
/// Note that [`Exp1`](struct.Exp1.html) is an optimised implementation for `lambda = 1`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
||||
@@ -74,8 +74,11 @@ impl Distribution<f64> for StandardNormal {
|
||||
|
||||
/// The normal distribution `N(mean, std_dev**2)`.
|
||||
///
|
||||
/// This uses the ZIGNOR variant of the Ziggurat method, see `StandardNormal`
|
||||
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
|
||||
/// for more details.
|
||||
///
|
||||
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
|
||||
/// standard deviation 1.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -87,6 +90,8 @@ impl Distribution<f64> for StandardNormal {
|
||||
/// let v = normal.sample(&mut rand::thread_rng());
|
||||
/// println!("{} is from a N(2, 9) distribution", v)
|
||||
/// ```
|
||||
///
|
||||
/// [`StandardNormal`]: struct.StandardNormal.html
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Normal {
|
||||
mean: f64,
|
||||
|
||||
+20
-189
@@ -12,208 +12,39 @@
|
||||
//! Rand provides utilities to generate random numbers, to convert them to
|
||||
//! useful types and distributions, and some randomness-related algorithms.
|
||||
//!
|
||||
//! # Basic usage
|
||||
//!
|
||||
//! # Quick Start
|
||||
//!
|
||||
//! To get you started quickly, the easiest and highest-level way to get
|
||||
//! a random value is to use [`random()`].
|
||||
//!
|
||||
//! ```
|
||||
//! let x: u8 = rand::random(); // generates an integer within u8 bounds
|
||||
//! println!("{}", x);
|
||||
//!
|
||||
//! let y = rand::random::<f64>(); // generates a float between 0 and 1
|
||||
//! println!("{}", y);
|
||||
//!
|
||||
//! if rand::random() { // generates a boolean
|
||||
//! println!("Heads!");
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! This supports generating most common types but is not very flexible, thus
|
||||
//! you probably want to learn a bit more about the Rand library.
|
||||
//!
|
||||
//!
|
||||
//! # The two-step process to get a random value
|
||||
//!
|
||||
//! Generating random values is typically a two-step process:
|
||||
//!
|
||||
//! - get some *random data* (an integer or bit/byte sequence) from a random
|
||||
//! number generator (RNG);
|
||||
//! - use some function to transform that *data* into the type of value you want
|
||||
//! (this function is an implementation of some *distribution* describing the
|
||||
//! kind of value produced).
|
||||
//!
|
||||
//! Rand represents the first step with the [`RngCore`] trait and the second
|
||||
//! step via a combination of the [`Rng`] extension trait and the
|
||||
//! [`distributions` module].
|
||||
//! In practice you probably won't use [`RngCore`] directly unless you are
|
||||
//! implementing a random number generator (RNG).
|
||||
//!
|
||||
//! There are many kinds of RNGs, with different trade-offs. You can read more
|
||||
//! about them in the [`rngs` module] and even more in the [`prng` module],
|
||||
//! however, often you can just use [`thread_rng()`]. This function
|
||||
//! automatically initializes an RNG in thread-local memory, then returns a
|
||||
//! reference to it. It is fast, good quality, and secure (unpredictable).
|
||||
//!
|
||||
//! To turn the output of the RNG into something usable, you usually want to use
|
||||
//! the methods from the [`Rng`] trait. Some of the most useful methods are:
|
||||
//!
|
||||
//! - [`gen`] generates a random value appropriate for the type (just like
|
||||
//! [`random()`]). For integers this is normally the full representable range
|
||||
//! (e.g. from `0u32` to `std::u32::MAX`), for floats this is between 0 and 1,
|
||||
//! and some other types are supported, including arrays and tuples. See the
|
||||
//! [`Standard`] distribution which provides the implementations.
|
||||
//! - [`gen_range`] samples from a specific range of values; this is like
|
||||
//! [`gen`] but with specific upper and lower bounds.
|
||||
//! - [`sample`] samples directly from some distribution.
|
||||
//!
|
||||
//! [`random()`] is defined using just the above: `thread_rng().gen()`.
|
||||
//!
|
||||
//! ## Distributions
|
||||
//!
|
||||
//! What are distributions, you ask? Specifying only the type and range of
|
||||
//! values (known as the *sample space*) is not enough; samples must also have
|
||||
//! a *probability distribution*, describing the relative probability of
|
||||
//! sampling each value in that space.
|
||||
//!
|
||||
//! In many cases a *uniform* distribution is used, meaning roughly that each
|
||||
//! value is equally likely (or for "continuous" types like floats, that each
|
||||
//! equal-sized sub-range has the same probability of containing a sample).
|
||||
//! [`gen`] and [`gen_range`] both use statistically uniform distributions.
|
||||
//!
|
||||
//! The [`distributions` module] provides implementations
|
||||
//! of some other distributions, including Normal, Log-Normal and Exponential.
|
||||
//!
|
||||
//! It is worth noting that the functionality already mentioned is implemented
|
||||
//! with distributions: [`gen`] samples values using the [`Standard`]
|
||||
//! distribution, while [`gen_range`] uses [`Uniform`].
|
||||
//!
|
||||
//! ## Importing (prelude)
|
||||
//!
|
||||
//! The most convenient way to import items from Rand is to use the [prelude].
|
||||
//! This includes the most important parts of Rand, but only those unlikely to
|
||||
//! cause name conflicts.
|
||||
//!
|
||||
//! Note that Rand 0.5 has significantly changed the module organization and
|
||||
//! contents relative to previous versions. Where possible old names have been
|
||||
//! kept (but are hidden in the documentation), however these will be removed
|
||||
//! in the future. We therefore recommend migrating to use the prelude or the
|
||||
//! new module organization in your imports.
|
||||
//!
|
||||
//!
|
||||
//! ## Examples
|
||||
//! a random value is to use [`random()`]; alternatively you can use
|
||||
//! [`thread_rng()`]. The [`Rng`] trait provides a useful API on all RNGs, while
|
||||
//! the [`distributions` module] and [`seq` module] provide further
|
||||
//! functionality on top of RNGs.
|
||||
//!
|
||||
//! ```
|
||||
//! use rand::prelude::*;
|
||||
//!
|
||||
//! // thread_rng is often the most convenient source of randomness:
|
||||
//! let mut rng = thread_rng();
|
||||
//!
|
||||
//! if rng.gen() { // random bool
|
||||
//! let x: f64 = rng.gen(); // random number in range [0, 1)
|
||||
//! println!("x is: {}", x);
|
||||
//! let ch = rng.gen::<char>(); // using type annotation
|
||||
//! println!("char is: {}", ch);
|
||||
//! println!("Number from 0 to 9: {}", rng.gen_range(0, 10));
|
||||
//!
|
||||
//! if rand::random() { // generates a boolean
|
||||
//! // Try printing a random unicode code point (probably a bad idea)!
|
||||
//! println!("char: {}", rand::random::<char>());
|
||||
//! }
|
||||
//!
|
||||
//! let mut rng = rand::thread_rng();
|
||||
//! let y: f64 = rng.gen(); // generates a float between 0 and 1
|
||||
//!
|
||||
//! let nums: Vec<i32> = (1..100).collect();
|
||||
//! nums.shuffle(&mut rng);
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! # More functionality
|
||||
//!
|
||||
//! The [`Rng`] trait includes a few more methods not mentioned above:
|
||||
//!
|
||||
//! - [`Rng::sample_iter`] allows iterating over values from a chosen
|
||||
//! distribution.
|
||||
//! - [`Rng::gen_bool`] generates boolean "events" with a given probability.
|
||||
//! - [`Rng::fill`] and [`Rng::try_fill`] are fast alternatives to fill a slice
|
||||
//! of integers.
|
||||
//! - [`Rng::shuffle`] randomly shuffles elements in a slice.
|
||||
//! - [`Rng::choose`] picks one element at random from a slice.
|
||||
//!
|
||||
//! For more slice/sequence related functionality, look in the [`seq` module].
|
||||
//!
|
||||
//!
|
||||
//! # Error handling
|
||||
//!
|
||||
//! Error handling in Rand is a compromise between simplicity and necessity.
|
||||
//! Most RNGs and sampling functions will never produce errors, and making these
|
||||
//! able to handle errors would add significant overhead (to code complexity
|
||||
//! and ergonomics of usage at least, and potentially also performance,
|
||||
//! depending on the approach).
|
||||
//! However, external RNGs can fail, and being able to handle this is important.
|
||||
//!
|
||||
//! It has therefore been decided that *most* methods should not return a
|
||||
//! `Result` type, with as exceptions [`Rng::try_fill`],
|
||||
//! [`RngCore::try_fill_bytes`], and [`SeedableRng::from_rng`].
|
||||
//!
|
||||
//! Note that it is the RNG that panics when it fails but is not used through a
|
||||
//! method that can report errors. Currently Rand contains only three RNGs that
|
||||
//! can return an error (and thus may panic), and documents this property:
|
||||
//! [`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`
|
||||
//!
|
||||
//! The [`rand_core`] crate provides the necessary traits and functionality for
|
||||
//! implementing RNGs; this includes the [`RngCore`] and [`SeedableRng`] traits
|
||||
//! and the [`Error`] type.
|
||||
//! Crates implementing RNGs should depend on [`rand_core`].
|
||||
//!
|
||||
//! Applications and libraries consuming random values are encouraged to use the
|
||||
//! Rand crate, which re-exports the common parts of [`rand_core`].
|
||||
//!
|
||||
//!
|
||||
//! # More examples
|
||||
//!
|
||||
//! For some inspiration, see the examples:
|
||||
//!
|
||||
//! - [Monte Carlo estimation of π](
|
||||
//! https://github.com/rust-random/rand/blob/master/examples/monte-carlo.rs)
|
||||
//! - [Monty Hall Problem](
|
||||
//! https://github.com/rust-random/rand/blob/master/examples/monty-hall.rs)
|
||||
//!
|
||||
//! # The Book
|
||||
//!
|
||||
//! For the user guide and futher documentation, please read
|
||||
//! [The Rust Rand Book](https://rust-random.github.io/book).
|
||||
//!
|
||||
//! [`distributions` module]: distributions/index.html
|
||||
//! [`FromEntropy::from_entropy`]: trait.FromEntropy.html#tymethod.from_entropy
|
||||
//! [`EntropyRng`]: rngs/struct.EntropyRng.html
|
||||
//! [`Error`]: struct.Error.html
|
||||
//! [`gen_range`]: trait.Rng.html#method.gen_range
|
||||
//! [`gen`]: trait.Rng.html#method.gen
|
||||
//! [`OsRng`]: rngs/struct.OsRng.html
|
||||
//! [prelude]: prelude/index.html
|
||||
//! [`rand_core`]: https://crates.io/crates/rand_core
|
||||
//! [`random()`]: fn.random.html
|
||||
//! [`ReadRng`]: rngs/adapter/struct.ReadRng.html
|
||||
//! [`Rng::choose`]: trait.Rng.html#method.choose
|
||||
//! [`Rng::fill`]: trait.Rng.html#method.fill
|
||||
//! [`Rng::gen_bool`]: trait.Rng.html#method.gen_bool
|
||||
//! [`Rng::gen`]: trait.Rng.html#method.gen
|
||||
//! [`Rng::sample_iter`]: trait.Rng.html#method.sample_iter
|
||||
//! [`Rng::shuffle`]: trait.Rng.html#method.shuffle
|
||||
//! [`RngCore`]: trait.RngCore.html
|
||||
//! [`RngCore::try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes
|
||||
//! [`rngs` module]: rngs/index.html
|
||||
//! [`prng` module]: prng/index.html
|
||||
//! [`Rng`]: trait.Rng.html
|
||||
//! [`Rng::try_fill`]: trait.Rng.html#method.try_fill
|
||||
//! [`sample`]: trait.Rng.html#method.sample
|
||||
//! [`SeedableRng`]: trait.SeedableRng.html
|
||||
//! [`SeedableRng::from_rng`]: trait.SeedableRng.html#method.from_rng
|
||||
//! [`seq` module]: seq/index.html
|
||||
//! [`SmallRng`]: rngs/struct.SmallRng.html
|
||||
//! [`StdRng`]: rngs/struct.StdRng.html
|
||||
//! [`thread_rng()`]: fn.thread_rng.html
|
||||
//! [`ThreadRng`]: rngs/struct.ThreadRng.html
|
||||
//! [`Standard`]: distributions/struct.Standard.html
|
||||
//! [`Uniform`]: distributions/struct.Uniform.html
|
||||
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
|
||||
+4
-305
@@ -8,312 +8,11 @@
|
||||
|
||||
//! Pseudo-random number generators.
|
||||
//!
|
||||
//! Pseudo-random number generators are algorithms to produce apparently random
|
||||
//! numbers deterministically, and usually fairly quickly. See the documentation
|
||||
//! of the [`rngs` module] for some introduction to PRNGs.
|
||||
//!
|
||||
//! As mentioned there, PRNGs fall in two broad categories:
|
||||
//!
|
||||
//! - [basic PRNGs], primarily designed for simulations
|
||||
//! - [CSPRNGs], primarily designed for cryptography
|
||||
//!
|
||||
//! In simple terms, the basic PRNGs are often predictable; CSPRNGs should not
|
||||
//! be predictable *when used correctly*.
|
||||
//! This module is deprecated:
|
||||
//!
|
||||
//! Contents of this documentation:
|
||||
//!
|
||||
//! 1. [The generators](#the-generators)
|
||||
//! 1. [Performance and size](#performance)
|
||||
//! 1. [Quality and cycle length](#quality)
|
||||
//! 1. [Security](#security)
|
||||
//! 1. [Extra features](#extra-features)
|
||||
//! 1. [Further reading](#further-reading)
|
||||
//!
|
||||
//!
|
||||
//! # The generators
|
||||
//!
|
||||
//! ## Basic pseudo-random number generators (PRNGs)
|
||||
//!
|
||||
//! 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
|
||||
//! where there is a risk of players predicting the next output value from
|
||||
//! previous values, in which case a CSPRNG should be used).
|
||||
//!
|
||||
//! Currently Rand provides only one PRNG, and not a very good one at that:
|
||||
//!
|
||||
//! | name | full name | performance | memory | quality | period | features |
|
||||
//! |------|-----------|-------------|--------|---------|--------|----------|
|
||||
//! | [`Pcg32`] | PCG XSH RR 64/32 (LCG) | ★★★☆☆ | 16 bytes | ★★★☆☆ | `u32` * 2<sup>64</sup> | — |
|
||||
//! | [`Pcg64Mcg`] | PCG XSL 128/64 (MCG) | ★★★★☆ | 16 bytes | ★★★☆☆ | `u64` * 2<sup>126</sup> | — |
|
||||
//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★★☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2<sup>128</sup> - 1 | — |
|
||||
//!
|
||||
// Quality stars [not rendered in documentation]:
|
||||
// 5. proven cryptographic quality (e.g. ChaCha20)
|
||||
// 4. potentially cryptographic, but low margin or lack of theory (e.g. ChaCha8, ISAAC)
|
||||
// 3. good performance on TestU01 and PractRand, good theory
|
||||
// 2. imperfect performance on tests or other limiting properties, or
|
||||
// insufficient theory, but not terrible
|
||||
// 1. clear deficiencies in test results, cycle length, theory, or other
|
||||
// properties
|
||||
//
|
||||
// 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 basic PRNGs. The primary
|
||||
//! consideration is security. Performance and simplicity are also important,
|
||||
//! 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.
|
||||
//!
|
||||
//! There is a close relationship between CSPRNGs and cryptographic ciphers.
|
||||
//! Any block cipher can be turned into a CSPRNG by encrypting a counter. Stream
|
||||
//! ciphers are basically a CSPRNG and a combining operation, usually XOR. This
|
||||
//! means that we can easily use any stream cipher as a CSPRNG.
|
||||
//!
|
||||
//! This crate currently provides two CSPRNGs. The sub-crate `rand_isaac`
|
||||
//! provides two CSPRNG-like PRNGs:
|
||||
//!
|
||||
//! | name | full name | performance | initialization | memory | predictability | forward secrecy |
|
||||
//! |------|-----------|--------------|--------------|----------|----------------|-------------------------|
|
||||
//! | [`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
|
||||
//! beginning. They have good quality output and no attacks are known, but have
|
||||
//! received little attention from cryptography experts.
|
||||
//!
|
||||
//!
|
||||
//! # Performance
|
||||
//!
|
||||
//! First it has to be said most PRNGs are very fast, and will rarely be a
|
||||
//! performance bottleneck.
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! When choosing a PRNG for performance it is important to benchmark your own
|
||||
//! application due to interactions between PRNGs and surrounding code and
|
||||
//! dependence on the CPU architecture as well as the impact of the size of
|
||||
//! data requested. Because of all this, we do not include performance numbers
|
||||
//! here but merely a qualitative rating.
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! ### Worst-case performance
|
||||
//! Because CSPRNGs usually produce a block of values into a cache, they have
|
||||
//! poor worst case performance (in contrast to basic PRNGs, where the
|
||||
//! performance is usually quite regular).
|
||||
//!
|
||||
//! ## State size
|
||||
//!
|
||||
//! 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 of state.
|
||||
//!
|
||||
//! ## Initialization time
|
||||
//!
|
||||
//! The time required to initialize new generators varies significantly. Many
|
||||
//! simple PRNGs and even some cryptographic ones (including [`ChaChaRng`])
|
||||
//! only need to copy the seed value and some constants into their state, and
|
||||
//! thus can be constructed very quickly. In contrast, CSPRNGs with large state
|
||||
//! require an expensive key-expansion.
|
||||
//!
|
||||
//! # Quality
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! How much do those hidden regularities matter? That is hard to say, and
|
||||
//! depends on how the RNG gets used. If there happen to be correlations between
|
||||
//! the random numbers and the algorithm they are used in, the results can be
|
||||
//! wrong or misleading.
|
||||
//!
|
||||
//! A random number generator can be considered good if it gives the correct
|
||||
//! results in as many applications as possible. The quality of PRNG
|
||||
//! algorithms can be evaluated to some extend analytically, to determine the
|
||||
//! cycle length and to rule out some correlations. Then there are empirical
|
||||
//! test suites designed to test how well a PRNG performs on a wide range of
|
||||
//! possible uses, the latest and most complete of which are [TestU01] and
|
||||
//! [PractRand].
|
||||
//!
|
||||
//! CSPRNGs tend to be more complex, and have an explicit requirement to be
|
||||
//! unpredictable. This implies there must be no obvious correlations between
|
||||
//! output values.
|
||||
//!
|
||||
//! ### Quality stars:
|
||||
//! 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.
|
||||
//!
|
||||
//! ## Period
|
||||
//!
|
||||
//! The *period* or *cycle length* of a PRNG is the number of values that can be
|
||||
//! generated after which it starts repeating the same random number stream.
|
||||
//! Many PRNGs have a fixed-size period, but for some only an expected average
|
||||
//! cycle length can be given, where the exact length depends on the seed.
|
||||
//!
|
||||
//! On today's hardware, even a fast RNG with a cycle length of *only*
|
||||
//! 2<sup>64</sup> can be used for centuries before cycling. Yet we recommend a
|
||||
//! period of 2<sup>128</sup> or more, which most modern PRNGs satisfy.
|
||||
//! Alternatively a PRNG with shorter period but support for multiple streams
|
||||
//! may be chosen. There are two reasons for this, as follows.
|
||||
//!
|
||||
//! If we see the entire period of an RNG as one long random number stream,
|
||||
//! every independently seeded RNG returns a slice of that stream. When multiple
|
||||
//! RNG are seeded randomly, there is an increasingly large chance to end up
|
||||
//! with a partially overlapping slice of the stream.
|
||||
//!
|
||||
//! If the period of the RNG is 2<sup>128</sup>, and an application consumes
|
||||
//! 2<sup>48</sup> values, it then takes about 2<sup>32</sup> random
|
||||
//! initializations to have a chance of 1 in a million to repeat part of an
|
||||
//! already used stream. This seems good enough for common usage of
|
||||
//! non-cryptographic generators, hence the recommendation of at least
|
||||
//! 2<sup>128</sup>. As an estimate, the chance of any overlap in a period of
|
||||
//! size `p` with `n` independent seeds and `u` values used per seed is
|
||||
//! approximately `1 - e^(-u * n^2 / (2 * p))`.
|
||||
//!
|
||||
//! Further, it is not recommended to use the full period of an RNG. Many
|
||||
//! PRNGs have a property called *k-dimensional equidistribution*, meaning that
|
||||
//! for values of some size (potentially larger than the output size), all
|
||||
//! possible values are produced the same number of times over the generator's
|
||||
//! period. This is not a property of true randomness. This is known as the
|
||||
//! generalized birthday problem, see the [PCG paper] for a good explanation.
|
||||
//! This results in a noticable bias on output after generating more values
|
||||
//! than the square root of the period (after 2<sup>64</sup> values for a
|
||||
//! period of 2<sup>128</sup>).
|
||||
//!
|
||||
//!
|
||||
//! # Security
|
||||
//!
|
||||
//! ## Predictability
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! 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 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 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
|
||||
//! analyzing existing designs, and what was once considered good may now turn
|
||||
//! out to be weaker. Generally it is best to use algorithms well-analyzed by
|
||||
//! experts, such as those recommended by NIST or ECRYPT.
|
||||
//!
|
||||
//! ## State and seeding
|
||||
//!
|
||||
//! It is worth noting that a CSPRNG's security relies absolutely on being
|
||||
//! seeded with a secure random key. Should the key be known or guessable, all
|
||||
//! output of the CSPRNG is easy to guess. This implies that the seed should
|
||||
//! come from a trusted source; usually either the OS or another CSPRNG. Our
|
||||
//! seeding helper trait, [`FromEntropy`], and the source it uses
|
||||
//! ([`EntropyRng`]), should be secure. Additionally, [`ThreadRng`] is a CSPRNG,
|
||||
//! thus it is acceptable to seed from this (although for security applications
|
||||
//! fresh/external entropy should be preferred).
|
||||
//!
|
||||
//! Further, it should be obvious that the internal state of a CSPRNG must be
|
||||
//! kept secret. With that in mind, our implementations do not provide direct
|
||||
//! access to most of their internal state, and `Debug` implementations do not
|
||||
//! print any internal state. This does not fully protect CSPRNG state; code
|
||||
//! within the same process may read this memory (and we allow cloning and
|
||||
//! serialisation of CSPRNGs for convenience). Further, a running process may be
|
||||
//! forked by the operating system, which may leave both processes with a copy
|
||||
//! of the same generator.
|
||||
//!
|
||||
//! ## Not a crypto library
|
||||
//!
|
||||
//! It should be emphasised that this is not a cryptography library; although
|
||||
//! Rand does take some measures to provide secure random numbers, it does not
|
||||
//! necessarily take all recommended measures. Further, cryptographic processes
|
||||
//! such as encryption and authentication are complex and must be implemented
|
||||
//! very carefully to avoid flaws and resist known attacks. It is therefore
|
||||
//! recommended to use specialized libraries where possible, for example
|
||||
//! [openssl], [ring] and the [RustCrypto libraries].
|
||||
//!
|
||||
//!
|
||||
//! # Extra features
|
||||
//!
|
||||
//! Some PRNGs may provide extra features, like:
|
||||
//!
|
||||
//! - Support for multiple streams, which can help with parallel tasks.
|
||||
//! - The ability to jump or seek around in the random number stream;
|
||||
//! with large periood this can be used as an alternative to streams.
|
||||
//!
|
||||
//!
|
||||
//! # Further reading
|
||||
//!
|
||||
//! There is quite a lot that can be said about PRNGs. The [PCG paper] is a
|
||||
//! very approachable explaining more concepts.
|
||||
//!
|
||||
//! A good paper about RNG quality is
|
||||
//! ["Good random number generators are (not so) easy to find"](
|
||||
//! http://random.mat.sbg.ac.at/results/peter/A19final.pdf) by P. Hellekalek.
|
||||
//!
|
||||
//!
|
||||
//! [`rngs` module]: ../rngs/index.html
|
||||
//! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs
|
||||
//! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs
|
||||
//! [`Pcg32`]: ../../rand_pcg/type.Pcg32.html
|
||||
//! [`Pcg64Mcg`]: ../../rand_pcg/type.Pcg64Mcg.html
|
||||
//! [`XorShiftRng`]: ../../rand_xorshift/struct.XorShiftRng.html
|
||||
//! [`ChaChaRng`]: ../../rand_chacha/struct.ChaChaRng.html
|
||||
//! [`Hc128Rng`]: ../../rand_hc/struct.Hc128Rng.html
|
||||
//! [`IsaacRng`]: ../../rand_isaac/isaac/struct.IsaacRng.html
|
||||
//! [`Isaac64Rng`]: ../../rand_isaac/isaac64/struct.Isaac64Rng.html
|
||||
//! [`ThreadRng`]: ../rngs/struct.ThreadRng.html
|
||||
//! [`FromEntropy`]: ../trait.FromEntropy.html
|
||||
//! [`EntropyRng`]: ../rngs/struct.EntropyRng.html
|
||||
//! [TestU01]: http://simul.iro.umontreal.ca/testu01/tu01.html
|
||||
//! [PractRand]: http://pracrand.sourceforge.net/
|
||||
//! [PCG paper]: http://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf
|
||||
//! [openssl]: https://crates.io/crates/openssl
|
||||
//! [ring]: https://crates.io/crates/ring
|
||||
//! [RustCrypto libraries]: https://github.com/RustCrypto
|
||||
//! [next-bit test]: https://en.wikipedia.org/wiki/Next-bit_test
|
||||
//! - documentation has moved to
|
||||
//! [The Book](https://rust-random.github.io/book/guide-rngs.html),
|
||||
//! - PRNGs have moved to other `rand_*` crates.
|
||||
|
||||
// Deprecations (to be removed in 0.7)
|
||||
#[doc(hidden)] #[allow(deprecated)]
|
||||
|
||||
Reference in New Issue
Block a user