diff --git a/src/rngs/adaptor/read.rs b/src/rngs/adaptor/read.rs index bf1f23ce2f..1bc5a34e22 100644 --- a/src/rngs/adaptor/read.rs +++ b/src/rngs/adaptor/read.rs @@ -15,10 +15,14 @@ use std::io::Read; use rand_core::{RngCore, Error, ErrorKind, impls}; -/// An RNG that reads random bytes straight from a `Read`. +/// An RNG that reads random bytes straight from any type supporting +/// `std::io::Read`, for example files. /// /// This will work best with an infinite reader, but that is not required. /// +/// This can be used with `/dev/urandom` on Unix but it is recommended to use +/// [`OsRng`] instead. +/// /// # Panics /// /// `ReadRng` uses `std::io::read_exact`, which retries on interrupts. All other @@ -35,6 +39,8 @@ use rand_core::{RngCore, Error, ErrorKind, impls}; /// let mut rng = read::ReadRng::new(&data[..]); /// println!("{:x}", rng.gen::()); /// ``` +/// +/// [`OsRng`]: ../struct.OsRng.html #[derive(Debug)] pub struct ReadRng { reader: R diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index 9d2de78545..ad59864a5a 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -8,101 +8,95 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Various RNGs and adapters. -//! -//! This module provides two standard RNGs exposed by Rand (besides -//! specific PRNG algorithms in the [`prng` module]): [`StdRng`] and -//! [`SmallRng`]. Also there is [`ThreadRng`], an implementation of [`StdRng`] -//! put in thread-local storage. -//! -//! When to prefer [`StdRng`] over [`SmallRng`]? Whenever there might be an -//! adversary who can effect the working of an algorithm by tweaking input. -//! Examples include picking random filenames, hashmap seeding, or QuickSort -//! using Random Pivoting. -//! -//! To get a seed for those PRNGs at runtime, [`EntropyRng`], [`OsRng`] and -//! [`JitterRng`] are sources of external randomness. There might be situations -//! where may want to use one of them directly, but generally they are used to -//! just get a seed. Prefer to use the [`FromEntropy`] trait when seeding a PRNG -//! instead, which takes care of error handling and has a fallback mechanism. +//! Random number generators and adapters for common usage: //! +//! - [`ThreadRng`], a fast, secure, auto-seeded thread-local generator +//! - [`StdRng`] and [`SmallRng`], algorithms to cover typical usage +//! - [`EntropyRng`], [`OsRng`] and [`JitterRng`] as entropy sources +//! - [`mock::StepRng`] as a simple counter for tests +//! - [`adapter::ReadRng`] to read from a file/stream //! //! # Background — Random number generators (RNGs) //! -//! Pulling random numbers out of 'thin air' is very hard for a computer. Not -//! impossible, but hard and slow. Generally the operating systems collects some -//! of them, by measuring different kinds of noice/jitter in the hardware. -//! -//! What is always used instead is a psuedo-random number generator (PRNG). This -//! is a clever algorithm that can produce an infinite stream of psuedo-random -//! numbers from a small seed. There exist algorithms that produce random -//! numbers that appear in no pratical situation to be any less random than -//! pulling values 'out of thin air'. Except that the random number stream can -//! be reproduced if you know the seed. -//! -//! There are two very different groups interested in developing PRNGs: one -//! interested in simulations and statistics, another in cryptography (sometimes -//! PRNGs from the latter are more specifically called a CSPRNG). From both -//! groups Rand picks one good algorithm. They are exposed as: -//! -//! - [`SmallRng`]. Uses little memory, and is very fast. -//! The best way to make sure a PRNG is suitable for many kinds of different -//! uses is by measuring how well it performs on the RNG test suites designed -//! to measure their quality (TestU01 and PractRand). -//! The currently picked algorithm (plain Xorshift) performs very bad on them, -//! and is planned to be replaced in the next major release. -//! - [`StdRng`]. It is a requirement for a CSPRNG that the output is basically -//! indiscernible from true randomness, as otherwise information could be -//! leaked. In addition this PRNG is unpredictable, even if you know the -//! implementation. This is an important property for any situation where -//! there might be an adversary, like cryptography, but certainly not limited -//! to that. This requirement makes it slower and/or use more memory however. -//! -//! One of the problems with PRNGs is that they need a seed (which is what the -//! [`SeedableRng`] trait is for). Where do you get such a seed? Two options: -//! -//! - Just use a constant. This is good when you need reproducible results, for -//! example to procedurally generate a game world). See the -//! [`SeedableRng::from_seed`] documentation. You may want to combine this -//! with a named PRNG from the [`prng` module] or from other crates, because -//! the algorithm of [`StdRng`] and [`SmallRng`] can change per release and/or -//! platform. -//! - Get a random value from somewhere at runtime. The -//! [`FromEntropy::from_entropy`] method helps here. It will usually get the -//! seed from the operating system's PRNG (using [`EntropyRng`]). -//! -//! Another problem is that the internal state of a PRNG must change after every -//! generated number. So an PRNG always has to be mutable. For APIs this means -//! they always need to somehow preserve the state between function calls, and -//! that there can always be only one mutable reference to the PRNG. -//! -//! [`ThreadRng`] abstracts away most of these issues. It uses [`StdRng`], which -//! is always a safe choice. Seeding happens automatically on first use. The -//! PRNG's state is stored in thread local storage, so no need to plumb the -//! state through an API. You can easily get a mutable reference to it with the -//! [`thread_rng`] function. +//! Computers are inherently deterministic, so to get *random* numbers one +//! either has to use a hardware generator or collect small bits of *entropy* +//! from various sources (e.g. event timestamps, or jitter). Generally the +//! operating system will collect entropy, remove bias and provide random +//! values on demand; [`OsRng`] uses this. [`JitterRng`] is a local +//! implementation of an entropy collector using high-resolution timers. Both +//! methods have some overhead (the latter especially). +//! +//! Usually, therefore, random values are generated using a deterministic +//! algorithm seeded with random data; a so-called Pseudo-Random Number +//! Generator (PRNG). The numbers produced are not "true" random numbers but +//! can be statistically of very high quality and can be impossible to predict. +//! (They can also have obvious correlations and be trivial to predict; quality +//! varies.) +//! +//! There are two different types of PRNGs: those developed for simulations +//! and statistics, and those developed for use in cryptography; the latter are +//! called Cryptographically Secure PRNGs (CSPRNG or CPRNG). Both types can +//! have good statistical quality but the latter should also be impossible to +//! predict, even after seeing many previous output values. We choose a good +//! default algorithm for each class: +//! +//! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and +//! good statistical quality. +//! The current algorithm (plain Xorshift) unfortunately performs +//! poorly in statistical quality test suites (TestU01 and PractRand) and will +//! be replaced in the next major release. +//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security +//! (based on reviews, maturity and usage). The current algorithm is HC-128, +//! which is recommended by ECRYPT's eSTREAM project. Amortised performance +//! is (on modern x86_64 CPUs) roughly similar to [`SmallRng`], but memory +//! usage is much higher. +//! +//! The above PRNGs do not cover all use-cases; more algorithms can be found in +//! the [`prng` module], as well as in several other crates. For example, you +//! may wish a CSPRNG with significantly lower memory usage than [`StdRng`] +//! while being less concerned about performance, in which case [`ChaChaRng`] +//! is a good choice. +//! +//! As mentioned above, PRNGs require random seed data in order to produce +//! random output. This is especially important for CSPRNGs, which are still +//! deterministic algorithms, thus can only be secure if their seed value is +//! also secure. To seed a PRNG, use one of: +//! +//! - [`FromEntropy::from_entropy`]; this is the most convenient way to seed +//! with fresh, secure random data +//! - [`SeedableRng::from_rng`]; this allows seeding from another PRNG or +//! from an entropy source such as [`EntropyRng`] +//! - [`SeedableRng::from_seed`]; this is mostly useful if you wish to be able +//! to reproduce the output sequence by using a fixed seed. (Don't use +//! [`StdRng`] or [`SmallRng`] in this case since different algorithms may be +//! used by future versions of Rand; use an algorithm from the [`prng` module].) +//! +//! Finally, if you "just" want a convient, secure, fast random number source, +//! use [`ThreadRng`]. This is a thread-local CSPRNG with automatic seeding on +//! first use and periodic reseeding. Use via the [`thread_rng`] function, which +//! gets a reference to the current thread's local instance. //! //! ## Conclusion //! //! - [`thread_rng`] is what you often want to use. //! - If you want more control, flexibility, or better performance, use -//! [`StdRng`], [`SmallRng`] or choose a specific PRNG algorithm. -//! - If you do not use [`thread_rng`], use [`FromEntropy::from_entropy`] for -//! seeding. +//! [`StdRng`], [`SmallRng`] or an algorithm from the [`prng` module]. +//! - Use [`FromEntropy::from_entropy`] to seed new PRNGs. //! - If you need reproducibility, use [`SeedableRng::from_seed`] combined with //! a named PRNG. //! -//! For more information, and notes on cryptographic security, see the -//! documentation in the [`prng` module]. +//! More information and notes on cryptographic security can be found +//! in the [`prng` module]. //! //! ## Examples //! //! Examples of seeding PRNGs: //! //! ``` -//! # use rand::Error; -//! // StdRng with a seed obtained at runtime: //! use rand::prelude::*; +//! # use rand::Error; +//! +//! // StdRng seeded securely by the OS or local entropy collector: //! let mut rng = StdRng::from_entropy(); //! # let v: u32 = rng.gen(); //! @@ -149,8 +143,12 @@ //! [`RngCore`]: ../trait.RngCore.html //! [`Rng`]: ../trait.Rng.html //! [`SeedableRng`]: ../trait.SeedableRng.html +//! [`SeedableRng::from_rng`]: ../trait.SeedableRng.html#tymethod.from_rng //! [`SeedableRng::from_seed`]: ../trait.SeedableRng.html#tymethod.from_seed //! [`thread_rng`]: ../fn.thread_rng.html +//! [`mock::StepRng`]: mock/struct.StepRng.html +//! [`adapter::ReadRng`]: adaptor/struct.ReadRng.html +//! [`ChaChaRng`]: ../prng/chacha/struct.ChaChaRng.html pub mod adaptor; diff --git a/src/rngs/os.rs b/src/rngs/os.rs index 5d5c8ab7cb..75cee9073d 100644 --- a/src/rngs/os.rs +++ b/src/rngs/os.rs @@ -20,7 +20,7 @@ use rand_core::{CryptoRng, RngCore, Error, impls}; /// Commonly it is used to initialize a user-space RNG, which can then be used /// to generate random values with much less overhead than `OsRng`. /// -/// You may prefer to use [`EntropyRng`] instead of `OsRng`. Is is unlikely, but +/// You may prefer to use [`EntropyRng`] instead of `OsRng`. It is unlikely, but /// not entirely theoretical, for `OsRng` to fail. In such cases [`EntropyRng`] /// falls back on a good alternative entropy source. ///