README: rand is not a crypto library (#1514)
Closes #1358 by documenting what Rand is not. Co-authored-by: Dan <dan.middleton@intel.com>
This commit is contained in:
parent
0c36c6ca59
commit
24b9cc38ea
40
README.md
40
README.md
@ -6,20 +6,20 @@
|
|||||||
[](https://rust-random.github.io/rand/rand)
|
[](https://rust-random.github.io/rand/rand)
|
||||||
[](https://docs.rs/rand)
|
[](https://docs.rs/rand)
|
||||||
|
|
||||||
Rand is a Rust library supporting random generators:
|
Rand is a set of crates supporting (pseudo-)random generators:
|
||||||
|
|
||||||
- A standard RNG trait: [`rand_core::RngCore`](https://docs.rs/rand_core/latest/rand_core/trait.RngCore.html)
|
- Built over a standard RNG trait: [`rand_core::RngCore`](https://docs.rs/rand_core/latest/rand_core/trait.RngCore.html)
|
||||||
- Fast implementations of the best-in-class [cryptographic](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and
|
- With fast implementations of both [strong](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and
|
||||||
[non-cryptographic](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators: [`rand::rngs`](https://docs.rs/rand/latest/rand/rngs/index.html), and more RNGs: [`rand_chacha`](https://docs.rs/rand_chacha), [`rand_xoshiro`](https://docs.rs/rand_xoshiro/), [`rand_pcg`](https://docs.rs/rand_pcg/), [rngs repo](https://github.com/rust-random/rngs/)
|
[small](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators: [`rand::rngs`](https://docs.rs/rand/latest/rand/rngs/index.html), and more RNGs: [`rand_chacha`](https://docs.rs/rand_chacha), [`rand_xoshiro`](https://docs.rs/rand_xoshiro/), [`rand_pcg`](https://docs.rs/rand_pcg/), [rngs repo](https://github.com/rust-random/rngs/)
|
||||||
- [`rand::rng`](https://docs.rs/rand/latest/rand/fn.rng.html) is an asymtotically-fast, reasonably secure generator available on all `std` targets
|
- [`rand::rng`](https://docs.rs/rand/latest/rand/fn.rng.html) is an asymptotically-fast, automatically-seeded and reasonably strong generator available on all `std` targets
|
||||||
- Secure seeding via the [`getrandom` crate](https://crates.io/crates/getrandom)
|
- Direct support for seeding generators from the [`getrandom` crate](https://crates.io/crates/getrandom)
|
||||||
|
|
||||||
Supporting random value generation and random processes:
|
With broad support for random value generation and random processes:
|
||||||
|
|
||||||
- [`Standard`](https://docs.rs/rand/latest/rand/distributions/struct.Standard.html) random value generation
|
- [`Standard`](https://docs.rs/rand/latest/rand/distributions/struct.Standard.html) random value sampling,
|
||||||
- Ranged [`Uniform`](https://docs.rs/rand/latest/rand/distributions/struct.Uniform.html) number generation for many types
|
[`Uniform`](https://docs.rs/rand/latest/rand/distributions/struct.Uniform.html)-ranged value sampling
|
||||||
- A flexible [`distributions`](https://docs.rs/rand/*/rand/distr/index.html) module
|
and [more](https://docs.rs/rand/latest/rand/distr/index.html)
|
||||||
- Samplers for a large number of random number distributions via our own
|
- Samplers for a large number of non-uniform random number distributions via our own
|
||||||
[`rand_distr`](https://docs.rs/rand_distr) and via
|
[`rand_distr`](https://docs.rs/rand_distr) and via
|
||||||
the [`statrs`](https://docs.rs/statrs/0.13.0/statrs/)
|
the [`statrs`](https://docs.rs/statrs/0.13.0/statrs/)
|
||||||
- Random processes (mostly choose and shuffle) via [`rand::seq`](https://docs.rs/rand/latest/rand/seq/index.html) traits
|
- Random processes (mostly choose and shuffle) via [`rand::seq`](https://docs.rs/rand/latest/rand/seq/index.html) traits
|
||||||
@ -28,19 +28,23 @@ All with:
|
|||||||
|
|
||||||
- [Portably reproducible output](https://rust-random.github.io/book/portability.html)
|
- [Portably reproducible output](https://rust-random.github.io/book/portability.html)
|
||||||
- `#[no_std]` compatibility (partial)
|
- `#[no_std]` compatibility (partial)
|
||||||
- *Many* performance optimisations
|
- *Many* performance optimisations thanks to contributions from the wide
|
||||||
|
user-base
|
||||||
|
|
||||||
It's also worth pointing out what Rand *is not*:
|
Rand **is not**:
|
||||||
|
|
||||||
- Small. Most low-level crates are small, but the higher-level `rand` and
|
- Small (LOC). Most low-level crates are small, but the higher-level `rand`
|
||||||
`rand_distr` each contain a lot of functionality.
|
and `rand_distr` each contain a lot of functionality.
|
||||||
- Simple (implementation). We have a strong focus on correctness, speed and flexibility, but
|
- Simple (implementation). We have a strong focus on correctness, speed and flexibility, but
|
||||||
not simplicity. If you prefer a small-and-simple library, there are
|
not simplicity. If you prefer a small-and-simple library, there are
|
||||||
alternatives including [fastrand](https://crates.io/crates/fastrand)
|
alternatives including [fastrand](https://crates.io/crates/fastrand)
|
||||||
and [oorandom](https://crates.io/crates/oorandom).
|
and [oorandom](https://crates.io/crates/oorandom).
|
||||||
- Slow. We take performance seriously, with considerations also for set-up
|
- A cryptography library. Rand provides functionality for generating
|
||||||
time of new distributions, commonly-used parameters, and parameters of the
|
unpredictable random data (potentially applicable depending on requirements)
|
||||||
current sampler.
|
but does not provide high-level cryptography functionality.
|
||||||
|
|
||||||
|
Rand is a community project and cannot provide legally-binding guarantees of
|
||||||
|
security.
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
|
|
||||||
|
43
SECURITY.md
43
SECURITY.md
@ -1,31 +1,46 @@
|
|||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
## No guarantees
|
## Disclaimer
|
||||||
|
|
||||||
Support is provided on a best-effort bases only.
|
Rand is a community project and cannot provide legally-binding guarantees of
|
||||||
No binding guarantees can be provided.
|
security.
|
||||||
|
|
||||||
## Security premises
|
## Security premises
|
||||||
|
|
||||||
Rand provides the trait `rand_core::CryptoRng` aka `rand::CryptoRng` as a marker
|
### Marker traits
|
||||||
trait. Generators implementing `RngCore` *and* `CryptoRng`, and given the
|
|
||||||
additional constraints that:
|
Rand provides the marker traits `CryptoRng`, `TryCryptoRng` and
|
||||||
|
`CryptoBlockRng`. Generators implementing one of these traits and used in a way
|
||||||
|
which meets the following additional constraints:
|
||||||
|
|
||||||
- Instances of seedable RNGs (those implementing `SeedableRng`) are
|
- Instances of seedable RNGs (those implementing `SeedableRng`) are
|
||||||
constructed with cryptographically secure seed values
|
constructed with cryptographically secure seed values
|
||||||
- The state (memory) of the RNG and its seed value are not be exposed
|
- The state (memory) of the RNG and its seed value are not exposed
|
||||||
|
|
||||||
are expected to provide the following:
|
are expected to provide the following:
|
||||||
|
|
||||||
- An attacker can gain no advantage over chance (50% for each bit) in
|
- An attacker cannot predict the output with more accuracy than what would be
|
||||||
predicting the RNG output, even with full knowledge of all prior outputs.
|
expected through pure chance since each possible output value of any method
|
||||||
|
under the above traits which generates output bytes (including
|
||||||
|
`RngCore::next_u32`, `RngCore::next_u64`, `RngCore::fill_bytes`,
|
||||||
|
`TryRngCore::try_next_u32`, `TryRngCore::try_next_u64`,
|
||||||
|
`TryRngCore::try_fill_bytes` and `BlockRngCore::generate`) should be equally
|
||||||
|
likely
|
||||||
|
- Knowledge of prior outputs from the generator does not aid an attacker in
|
||||||
|
predicting future outputs
|
||||||
|
|
||||||
For some RNGs, notably `OsRng`, `ThreadRng` and those wrapped by `ReseedingRng`,
|
### Specific generators
|
||||||
we provide limited mitigations against side-channel attacks:
|
|
||||||
|
|
||||||
- After the state (memory) of an RNG is leaked, there is an upper-bound on the
|
`OsRng` is a stateless "generator" implemented via [getrandom]. As such, it has
|
||||||
number of bits of output by the RNG before prediction of output by an
|
no possible state to leak and cannot be improperly seeded.
|
||||||
observer again becomes computationally-infeasible
|
|
||||||
|
`ThreadRng` will periodically reseed itself, thus placing an upper bound on the
|
||||||
|
number of bits of output from an instance before any advantage an attacker may
|
||||||
|
have gained through state-compromising side-channel attacks is lost.
|
||||||
|
|
||||||
|
[getrandom]: https://crates.io/crates/getrandom
|
||||||
|
|
||||||
|
### Distributions
|
||||||
|
|
||||||
Additionally, derivations from such an RNG (including the `Rng` trait,
|
Additionally, derivations from such an RNG (including the `Rng` trait,
|
||||||
implementations of the `Distribution` trait, and `seq` algorithms) should not
|
implementations of the `Distribution` trait, and `seq` algorithms) should not
|
||||||
|
@ -11,10 +11,9 @@
|
|||||||
use crate::{TryCryptoRng, TryRngCore};
|
use crate::{TryCryptoRng, TryRngCore};
|
||||||
use getrandom::getrandom;
|
use getrandom::getrandom;
|
||||||
|
|
||||||
/// A random number generator that retrieves randomness from the
|
/// An interface over the operating-system's random data source
|
||||||
/// operating system.
|
|
||||||
///
|
///
|
||||||
/// This is a zero-sized struct. It can be freely constructed with `OsRng`.
|
/// This is a zero-sized struct. It can be freely constructed with just `OsRng`.
|
||||||
///
|
///
|
||||||
/// The implementation is provided by the [getrandom] crate. Refer to
|
/// The implementation is provided by the [getrandom] crate. Refer to
|
||||||
/// [getrandom] documentation for details.
|
/// [getrandom] documentation for details.
|
||||||
@ -32,7 +31,8 @@ use getrandom::getrandom;
|
|||||||
///
|
///
|
||||||
/// After the first successful call, it is highly unlikely that failures or
|
/// After the first successful call, it is highly unlikely that failures or
|
||||||
/// significant delays will occur (although performance should be expected to
|
/// significant delays will occur (although performance should be expected to
|
||||||
/// be much slower than a user-space PRNG).
|
/// be much slower than a user-space
|
||||||
|
/// [PRNG](https://rust-random.github.io/book/guide-gen.html#pseudo-random-number-generators)).
|
||||||
///
|
///
|
||||||
/// # Usage example
|
/// # Usage example
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -11,17 +11,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [`Uniform`] is the standard distribution to sample uniformly from a range;
|
//! [`Uniform`] is the standard distribution to sample uniformly from a range;
|
||||||
//! e.g. `Uniform::new_inclusive(1, 6).unwrap()` can sample integers from 1 to 6, like a
|
//! e.g. `Uniform::new_inclusive(1, 6).unwrap()` can sample integers from 1 to 6, like a
|
||||||
//! standard die. [`Rng::random_range`] supports any type supported by [`Uniform`].
|
//! standard die. [`Rng::random_range`] is implemented over [`Uniform`].
|
||||||
//!
|
|
||||||
//! This distribution is provided with support for several primitive types
|
|
||||||
//! (all integer and floating-point types) as well as [`std::time::Duration`],
|
|
||||||
//! and supports extension to user-defined types via a type-specific *back-end*
|
|
||||||
//! implementation.
|
|
||||||
//!
|
|
||||||
//! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the
|
|
||||||
//! back-ends supporting sampling from primitive integer and floating-point
|
|
||||||
//! ranges as well as from [`std::time::Duration`]; these types do not normally
|
|
||||||
//! need to be used directly (unless implementing a derived back-end).
|
|
||||||
//!
|
//!
|
||||||
//! # Example usage
|
//! # Example usage
|
||||||
//!
|
//!
|
||||||
@ -151,26 +141,38 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
/// Sample values uniformly between two bounds.
|
/// Sample values uniformly between two bounds.
|
||||||
///
|
///
|
||||||
|
/// # Construction
|
||||||
|
///
|
||||||
/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
|
/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
|
||||||
/// distribution sampling from the given range; these functions may do extra
|
/// distribution sampling from the given `low` and `high` limits. `Uniform` may
|
||||||
/// work up front to make sampling of multiple values faster. If only one sample
|
/// also be constructed via [`TryFrom`] as in `Uniform::try_from(1..=6).unwrap()`.
|
||||||
/// from the range is required, [`Rng::random_range`] can be more efficient.
|
///
|
||||||
|
/// Constructors may do extra work up front to allow faster sampling of multiple
|
||||||
|
/// values. Where only a single sample is required it is suggested to use
|
||||||
|
/// [`Rng::random_range`] or one of the `sample_single` methods instead.
|
||||||
///
|
///
|
||||||
/// When sampling from a constant range, many calculations can happen at
|
/// When sampling from a constant range, many calculations can happen at
|
||||||
/// compile-time and all methods should be fast; for floating-point ranges and
|
/// compile-time and all methods should be fast; for floating-point ranges and
|
||||||
/// the full range of integer types, this should have comparable performance to
|
/// the full range of integer types, this should have comparable performance to
|
||||||
/// the `Standard` distribution.
|
/// the `Standard` distribution.
|
||||||
///
|
///
|
||||||
/// Steps are taken to avoid bias, which might be present in naive
|
/// # Provided implementations
|
||||||
/// implementations; for example `rng.gen::<u8>() % 170` samples from the range
|
|
||||||
/// `[0, 169]` but is twice as likely to select numbers less than 85 than other
|
|
||||||
/// values. Further, the implementations here give more weight to the high-bits
|
|
||||||
/// generated by the RNG than the low bits, since with some RNGs the low-bits
|
|
||||||
/// are of lower quality than the high bits.
|
|
||||||
///
|
///
|
||||||
/// Implementations must sample in `[low, high)` range for
|
/// - `char` ([`UniformChar`]): samples a range over the implementation for `u32`
|
||||||
/// `Uniform::new(low, high)`, i.e., excluding `high`. In particular, care must
|
/// - `f32`, `f64` ([`UniformFloat`]): samples approximately uniformly within a
|
||||||
/// be taken to ensure that rounding never results values `< low` or `>= high`.
|
/// range; bias may be present in the least-significant bit of the significand
|
||||||
|
/// and the limits of the input range may be sampled even when an open
|
||||||
|
/// (exclusive) range is used
|
||||||
|
/// - Integer types ([`UniformInt`]) may show a small bias relative to the
|
||||||
|
/// expected uniform distribution of output. In the worst case, bias affects
|
||||||
|
/// 1 in `2^n` samples where n is 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96
|
||||||
|
/// (`i32` and `u32`), 64 (`i64` and `u64`), 128 (`i128` and `u128`).
|
||||||
|
/// The `unbiased` feature flag fixes this bias.
|
||||||
|
/// - `usize` ([`UniformUsize`]) is handled specially, using the `u32`
|
||||||
|
/// implementation where possible to enable portable results across 32-bit and
|
||||||
|
/// 64-bit CPU architectures.
|
||||||
|
/// - `Duration` ([`UniformDuration`]): samples a range over the implementation
|
||||||
|
/// for `u32` or `u64`
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -29,14 +29,17 @@ use serde::{Deserialize, Serialize};
|
|||||||
///
|
///
|
||||||
/// # Implementation notes
|
/// # Implementation notes
|
||||||
///
|
///
|
||||||
/// Instead of generating a float in the `[0, 1)` range using [`Standard`], the
|
/// `UniformFloat` implementations convert RNG output to a float in the range
|
||||||
/// `UniformFloat` implementation converts the output of an PRNG itself. This
|
/// `[1, 2)` via transmutation, map this to `[0, 1)`, then scale and translate
|
||||||
/// way one or two steps can be optimized out.
|
/// to the desired range. Values produced this way have what equals 23 bits of
|
||||||
|
/// random digits for an `f32` and 52 for an `f64`.
|
||||||
///
|
///
|
||||||
/// The floats are first converted to a value in the `[1, 2)` interval using a
|
/// # Bias and range errors
|
||||||
/// transmute-based method, and then mapped to the expected range with a
|
///
|
||||||
/// multiply and addition. Values produced this way have what equals 23 bits of
|
/// Bias may be expected within the least-significant bit of the significand.
|
||||||
/// random digits for an `f32`, and 52 for an `f64`.
|
/// It is not guaranteed that exclusive limits of a range are respected; i.e.
|
||||||
|
/// when sampling the range `[a, b)` it is not guaranteed that `b` is never
|
||||||
|
/// sampled.
|
||||||
///
|
///
|
||||||
/// [`new`]: UniformSampler::new
|
/// [`new`]: UniformSampler::new
|
||||||
/// [`new_inclusive`]: UniformSampler::new_inclusive
|
/// [`new_inclusive`]: UniformSampler::new_inclusive
|
||||||
|
@ -58,6 +58,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// multiply by `range`, the result is in the high word. Then comparing the low
|
/// multiply by `range`, the result is in the high word. Then comparing the low
|
||||||
/// word against `zone` makes sure our distribution is uniform.
|
/// word against `zone` makes sure our distribution is uniform.
|
||||||
///
|
///
|
||||||
|
/// # Bias
|
||||||
|
///
|
||||||
|
/// Unless the `unbiased` feature flag is used, outputs may have a small bias.
|
||||||
|
/// In the worst case, bias affects 1 in `2^n` samples where n is
|
||||||
|
/// 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96 (`i32` and `u32`), 64 (`i64`
|
||||||
|
/// and `u64`), 128 (`i128` and `u128`).
|
||||||
|
///
|
||||||
/// [`Uniform`]: super::Uniform
|
/// [`Uniform`]: super::Uniform
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
@ -41,16 +41,36 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
|
|||||||
/// A reference to the thread-local generator
|
/// A reference to the thread-local generator
|
||||||
///
|
///
|
||||||
/// This type is a reference to a lazily-initialized thread-local generator.
|
/// This type is a reference to a lazily-initialized thread-local generator.
|
||||||
/// An instance can be obtained via [`rand::rng()`][crate::rng())] or via
|
/// An instance can be obtained via [`rand::rng()`][crate::rng()] or via
|
||||||
/// `ThreadRng::default()`.
|
/// [`ThreadRng::default()`].
|
||||||
/// The handle cannot be passed between threads (is not `Send` or `Sync`).
|
/// The handle cannot be passed between threads (is not `Send` or `Sync`).
|
||||||
///
|
///
|
||||||
/// `ThreadRng` uses the same CSPRNG as [`StdRng`], ChaCha12. As with
|
/// # Security
|
||||||
/// [`StdRng`], the algorithm may be changed, subject to reasonable expectations
|
|
||||||
/// of security and performance.
|
|
||||||
///
|
///
|
||||||
/// `ThreadRng` is automatically seeded from [`OsRng`] with periodic reseeding
|
/// Security must be considered relative to a threat model and validation
|
||||||
/// (every 64 kiB — see [`ReseedingRng`] documentation for details).
|
/// requirements. The Rand project can provide no guarantee of fitness for
|
||||||
|
/// purpose. The design criteria for `ThreadRng` are as follows:
|
||||||
|
///
|
||||||
|
/// - Automatic seeding via [`OsRng`] and periodically thereafter (see
|
||||||
|
/// ([`ReseedingRng`] documentation). Limitation: there is no automatic
|
||||||
|
/// reseeding on process fork (see [below](#fork)).
|
||||||
|
/// - A rigorusly analyzed, unpredictable (cryptographic) pseudo-random generator
|
||||||
|
/// (see [the book on security](https://rust-random.github.io/book/guide-rngs.html#security)).
|
||||||
|
/// The currently selected algorithm is ChaCha (12-rounds).
|
||||||
|
/// See also [`StdRng`] documentation.
|
||||||
|
/// - Not to leak internal state through [`Debug`] or serialization
|
||||||
|
/// implementations.
|
||||||
|
/// - No further protections exist to in-memory state. In particular, the
|
||||||
|
/// implementation is not required to zero memory on exit (of the process or
|
||||||
|
/// thread). (This may change in the future.)
|
||||||
|
/// - Be fast enough for general-purpose usage. Note in particular that
|
||||||
|
/// `ThreadRng` is designed to be a "fast, reasonably secure generator"
|
||||||
|
/// (where "reasonably secure" implies the above criteria).
|
||||||
|
///
|
||||||
|
/// We leave it to the user to determine whether this generator meets their
|
||||||
|
/// security requirements. For an alternative, see [`OsRng`].
|
||||||
|
///
|
||||||
|
/// # Fork
|
||||||
///
|
///
|
||||||
/// `ThreadRng` is not automatically reseeded on fork. It is recommended to
|
/// `ThreadRng` is not automatically reseeded on fork. It is recommended to
|
||||||
/// explicitly call [`ThreadRng::reseed`] immediately after a fork, for example:
|
/// explicitly call [`ThreadRng::reseed`] immediately after a fork, for example:
|
||||||
@ -68,13 +88,6 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
|
|||||||
/// from an interrupt (e.g. a fork handler) unless it can be guaranteed that no
|
/// from an interrupt (e.g. a fork handler) unless it can be guaranteed that no
|
||||||
/// other method on the same `ThreadRng` is currently executing.
|
/// other method on the same `ThreadRng` is currently executing.
|
||||||
///
|
///
|
||||||
/// Security must be considered relative to a threat model and validation
|
|
||||||
/// requirements. `ThreadRng` attempts to meet basic security considerations
|
|
||||||
/// for producing unpredictable random numbers: use a CSPRNG, use a
|
|
||||||
/// recommended platform-specific seed ([`OsRng`]), and avoid
|
|
||||||
/// leaking internal secrets e.g. via [`Debug`] implementation or serialization.
|
|
||||||
/// Memory is not zeroized on drop.
|
|
||||||
///
|
|
||||||
/// [`ReseedingRng`]: crate::rngs::ReseedingRng
|
/// [`ReseedingRng`]: crate::rngs::ReseedingRng
|
||||||
/// [`StdRng`]: crate::rngs::StdRng
|
/// [`StdRng`]: crate::rngs::StdRng
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -115,9 +128,9 @@ thread_local!(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Access a local, pre-initialized generator
|
/// Access a fast, pre-initialized generator
|
||||||
///
|
///
|
||||||
/// This is a reasonably fast unpredictable thread-local instance of [`ThreadRng`].
|
/// This is a handle to the local [`ThreadRng`].
|
||||||
///
|
///
|
||||||
/// See also [`crate::rngs`] for alternatives.
|
/// See also [`crate::rngs`] for alternatives.
|
||||||
///
|
///
|
||||||
@ -139,6 +152,10 @@ thread_local!(
|
|||||||
/// println!("A simulated die roll: {}", rng.random_range(1..=6));
|
/// println!("A simulated die roll: {}", rng.random_range(1..=6));
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Security
|
||||||
|
///
|
||||||
|
/// Refer to [`ThreadRng#Security`].
|
||||||
pub fn rng() -> ThreadRng {
|
pub fn rng() -> ThreadRng {
|
||||||
let rng = THREAD_RNG_KEY.with(|t| t.clone());
|
let rng = THREAD_RNG_KEY.with(|t| t.clone());
|
||||||
ThreadRng { rng }
|
ThreadRng { rng }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user