|
16 | 16 | //!
|
17 | 17 | //! As mentioned there, PRNGs fall in two broad categories:
|
18 | 18 | //!
|
19 |
| -//! - [normal PRNGs], primarily designed for simulations |
| 19 | +//! - [basic PRNGs], primarily designed for simulations |
20 | 20 | //! - [CSPRNGs], primarily designed for cryptography
|
21 | 21 | //!
|
22 |
| -//! In simple terms, the normal PRNGs are often predictable; CSPRNGs should not |
| 22 | +//! In simple terms, the basic PRNGs are often predictable; CSPRNGs should not |
23 | 23 | //! be predictable *when used correctly*.
|
24 | 24 | //!
|
25 | 25 | //! Contents of this documentation:
|
|
34 | 34 | //!
|
35 | 35 | //! # The generators
|
36 | 36 | //!
|
37 |
| -//! ## Normal pseudo-random number generators (PRNGs) |
| 37 | +//! ## Basic pseudo-random number generators (PRNGs) |
38 | 38 | //!
|
39 |
| -//! The goal of normal, non-cryptographic PRNGs is usually to find a good |
| 39 | +//! The goal of regular, non-cryptographic PRNGs is usually to find a good |
40 | 40 | //! balance between simplicity, quality, memory usage and performance. These
|
41 | 41 | //! algorithms are very important to Monte Carlo simulations, and also suitable
|
42 | 42 | //! for several other problems such as randomized algorithms and games (except
|
|
47 | 47 | //!
|
48 | 48 | //! | name | full name | performance | memory | quality | period | features |
|
49 | 49 | //! |------|-----------|-------------|--------|---------|--------|----------|
|
50 |
| -//! | [`XorShiftRng`] | Xorshift 32/128 | ⭐⭐⭐ | 16 bytes | ⭐ | `u32` * 2<sup>128</sup> - 1 | — | |
| 50 | +//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★☆☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2<sup>128</sup> - 1 | — | |
51 | 51 | //!
|
| 52 | +// Quality stars [not rendered in documentation]: |
| 53 | +// 5. reserved for crypto-level (e.g. ChaCha8, ISAAC) |
| 54 | +// 4. good performance on TestU01 and PractRand, good theory |
| 55 | +// (e.g. PCG, truncated Xorshift*) |
| 56 | +// 3. good performance on TestU01 and PractRand, but "falling through the |
| 57 | +// cracks" or insufficient theory (e.g. SFC, Xoshiro) |
| 58 | +// 2. imperfect performance on tests or other limiting properties, but not |
| 59 | +// terrible (e.g. Xoroshiro128+) |
| 60 | +// 1. clear deficiencies in test results, cycle length, theory, or other |
| 61 | +// properties (e.g. Xorshift) |
| 62 | +// |
| 63 | +// Performance stars [not rendered in documentation]: |
| 64 | +// Meant to give an indication of relative performance. Roughly follows a log |
| 65 | +// scale, based on the performance of `next_u64` on a current i5/i7: |
| 66 | +// - 5. 8000 MB/s+ |
| 67 | +// - 4. 4000 MB/s+ |
| 68 | +// - 3. 2000 MB/s+ |
| 69 | +// - 2. 1000 MB/s+ |
| 70 | +// - 1. < 1000 MB/s |
| 71 | +// |
52 | 72 | //! ## Cryptographically secure pseudo-random number generators (CSPRNGs)
|
53 | 73 | //!
|
54 |
| -//! CSPRNGs have much higher requirements than normal PRNGs. The primary |
| 74 | +//! CSPRNGs have much higher requirements than basic PRNGs. The primary |
55 | 75 | //! consideration is security. Performance and simplicity are also important,
|
56 |
| -//! but in general CSPRNGs are more complex and slower than normal PRNGs. |
| 76 | +//! but in general CSPRNGs are more complex and slower than regular PRNGs. |
57 | 77 | //! Quality is no longer a concern, as it is a requirement for a
|
58 | 78 | //! CSPRNG that the output is basically indistinguishable from true randomness
|
59 | 79 | //! since any bias or correlation makes the output more predictable.
|
|
65 | 85 | //!
|
66 | 86 | //! Rand currently provides two trustworthy CSPRNGs and two CSPRNG-like PRNGs:
|
67 | 87 | //!
|
68 |
| -//! | name | full name | performance | initialization | memory | predictability | backtracking resistance | |
| 88 | +//! | name | full name | performance | initialization | memory | predictability | forward secrecy | |
69 | 89 | //! |------|-----------|--------------|--------------|----------|----------------|-------------------------|
|
70 |
| -//! | [`ChaChaRng`] | ChaCha20 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 136 bytes | secure | no | |
71 |
| -//! | [`Hc128Rng`] | HC-128 | ⭐⭐⭐⭐⭐ | ⭐ | 4176 bytes | secure | no | |
72 |
| -//! | [`IsaacRng`] | ISAAC | ⭐⭐⭐⭐ | ⭐ | 2072 bytes | unknown | unknown | |
73 |
| -//! | [`Isaac64Rng`] | ISAAC-64 | ⭐⭐⭐⭐⭐ | ⭐ | 4136 bytes| unknown | unknown | |
| 90 | +//! | [`ChaChaRng`] | ChaCha20 | ★☆☆☆☆ | fast | 136 bytes | secure | no | |
| 91 | +//! | [`Hc128Rng`] | HC-128 | ★★☆☆☆ | slow | 4176 bytes | secure | no | |
| 92 | +//! | [`IsaacRng`] | ISAAC | ★★☆☆☆ | slow | 2072 bytes | unknown | unknown | |
| 93 | +//! | [`Isaac64Rng`] | ISAAC-64 | ★★☆☆☆ | slow | 4136 bytes| unknown | unknown | |
74 | 94 | //!
|
75 | 95 | //! It should be noted that the ISAAC generators are only included for
|
76 | 96 | //! historical reasons, they have been with the Rust language since the very
|
|
83 | 103 | //! First it has to be said most PRNGs are very fast, and will rarely be a
|
84 | 104 | //! performance bottleneck.
|
85 | 105 | //!
|
86 |
| -//! Performance of normal PRNGs is a bit of a subtle thing. It depends a lot on |
| 106 | +//! Performance of basic PRNGs is a bit of a subtle thing. It depends a lot on |
87 | 107 | //! the CPU architecture (32 vs. 64 bits), inlining, and also on the number of
|
88 | 108 | //! available registers. This often causes the performance to be affected by
|
89 | 109 | //! surrounding code due to inlining and other usage of registers.
|
|
98 | 118 | //! CSPRNGs are a little different in that they typically generate a block of
|
99 | 119 | //! output in a cache, and pull outputs from the cache. This allows them to have
|
100 | 120 | //! good amortised performance, and reduces or completely removes the influence
|
101 |
| -//! of surrounding code on the CSPRNG performance. It does however cause *poor |
102 |
| -//! worst case performance*. |
| 121 | +//! of surrounding code on the CSPRNG performance. |
103 | 122 | //!
|
104 |
| -//! ## State size |
| 123 | +//! ### Worst-case performance |
| 124 | +//! Because CSPRNGs usually produce a block of values into a cache, they have |
| 125 | +//! poor worst case performance (in contrast to regular PRNGs). |
105 | 126 | //!
|
106 |
| -//! Normal PRNGs often use very little memory, commonly only a few words, where |
107 |
| -//! a *word* is usually either `u32` or `u64`. This is not universal however, |
108 |
| -//! for example the historically popular Mersenne Twister MT19937 algorithm |
109 |
| -//! requires 2.5 kB of state. |
| 127 | +//! Simple PRNGs often use very little memory, commonly only a few words, where |
| 128 | +//! a *word* is usually either `u32` or `u64`. This is not true for all |
| 129 | +//! non-cryptographic PRNGs however, for example the historically popular |
| 130 | +//! Mersenne Twister MT19937 algorithm requires 2.5 kB of state. |
110 | 131 | //!
|
111 | 132 | //! CSPRNGs typically require more memory; since the seed size is recommended
|
112 | 133 | //! to be at least 192 bits and some more may be required for the algorithm,
|
|
124 | 145 | //!
|
125 | 146 | //! # Quality
|
126 | 147 | //!
|
127 |
| -//! Many normal PRNGs are not much more than a couple of bitwise and arithmetic |
| 148 | +//! Many basic PRNGs are not much more than a couple of bitwise and arithmetic |
128 | 149 | //! operations. Their simplicity gives good performance, but also means there
|
129 | 150 | //! are small regularities hidden in the generated random number stream.
|
130 | 151 | //!
|
|
146 | 167 | //! output values.
|
147 | 168 | //!
|
148 | 169 | //! ### Quality stars:
|
149 |
| -// 5. reserved for crypto-level (e.g. ChaCha8, ISAAC) |
150 |
| -// 4. good performance on TestU01 and PractRand, good theory |
151 |
| -// (e.g. PCG, truncated Xorshift*) |
152 |
| -// 3. good performance on TestU01 and PractRand, but "falling through the |
153 |
| -// cracks" or insufficient theory (e.g. SFC, Xoshiro) |
154 |
| -// 2. imperfect performance on tests or other limiting properties, but not |
155 |
| -// terrible (e.g. Xoroshiro128+) |
156 |
| -// 1. clear deficiencies in test results, cycle length, theory, or other |
157 |
| -// properties (e.g. Xorshift) |
158 |
| -//! |
159 | 170 | //! PRNGs with 3 stars or more should be good enough for any purpose.
|
160 | 171 | //! 1 or 2 stars may be good enough for typical apps and games, but do not work
|
161 | 172 | //! well with all algorithms.
|
|
204 | 215 | //!
|
205 | 216 | //! From the context of any PRNG, one can ask the question *given some previous
|
206 | 217 | //! output from the PRNG, is it possible to predict the next output value?*
|
| 218 | +//! This is an important property in any situation where there might be an |
| 219 | +//! adversary. |
207 | 220 | //!
|
208 |
| -//! Normal PRNGs tend to fall into one of two categories here; *yes* and |
209 |
| -//! *with effort*. In some cases prediction is trivial; e.g. plain Xorshift |
210 |
| -//! outputs part of its state without mutation, and prediction is as simple as |
211 |
| -//! seeding a new Xorshift generator from four `u32` outputs. The widely-used |
212 |
| -//! Mersenne Twister algorithms are also easy to predict, though more samples |
213 |
| -//! are required (624 `u32` samples, in the case of MT19937). Other generators, |
214 |
| -//! like [PCG](http://www.pcg-random.org/predictability.html) and truncated |
215 |
| -//! Xorshift* are harder to predict, but not outside the realm of common |
216 |
| -//! mathematics and a desktop PC. |
| 221 | +//! Regular PRNGs tend to be predictable, although with varying difficulty. In |
| 222 | +//! some cases prediction is trivial, for example plain Xorshift outputs part of |
| 223 | +//! its state without mutation, and prediction is as simple as seeding a new |
| 224 | +//! Xorshift generator from four `u32` outputs. Other generators, like |
| 225 | +//! [PCG](http://www.pcg-random.org/predictability.html) and truncated Xorshift* |
| 226 | +//! are harder to predict, but not outside the realm of common mathematics and a |
| 227 | +//! desktop PC. |
217 | 228 | //!
|
218 | 229 | //! The basic security that CSPRNGs must provide is the infeasibility to predict
|
219 | 230 | //! output. This requirement is formalized as the [next-bit test]; this is
|
220 | 231 | //! roughly stated as: given the first *k* bits of a random sequence, the
|
221 | 232 | //! sequence satisfies the next-bit test if there is no algorithm able to
|
222 | 233 | //! predict the next bit using reasonable computing power.
|
223 | 234 | //!
|
224 |
| -//! A further security that *some* CSPRNGs provide is backtracking resistance: |
| 235 | +//! A further security that *some* CSPRNGs provide is forward secrecy: |
225 | 236 | //! in the event that the CSPRNGs state is revealed at some point, it must be
|
226 | 237 | //! infeasible to reconstruct previous states or output. Note that many CSPRNGs
|
227 |
| -//! *do not* have backtracking resistance in their usual formulations. |
| 238 | +//! *do not* have forward secrecy in their usual formulations. |
228 | 239 | //!
|
229 | 240 | //! As an outsider it is hard to get a good idea about the security of an
|
230 | 241 | //! algorithm. People in the field of cryptography spend a lot of effort
|
|
283 | 294 | //!
|
284 | 295 | //!
|
285 | 296 | //! [`rngs` module]: ../rngs/index.html
|
286 |
| -//! [normal PRNGs]: #normal-pseudo-random-number-generators-prngs |
| 297 | +//! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs |
287 | 298 | //! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs
|
288 | 299 | //! [`XorShiftRng`]: struct.XorShiftRng.html
|
289 | 300 | //! [`ChaChaRng`]: chacha/struct.ChaChaRng.html
|
|
0 commit comments