@@ -20,7 +20,7 @@ use {Rng, SeedableRng, Error, ErrorKind};
20
20
/// limited number of bytes they can output, or at least not a limit reachable
21
21
/// in any practical way. There is no such thing as 'running out of entropy'.
22
22
///
23
- /// Some small non-cryptographic PRNG's can have very small periods of for
23
+ /// Some small non-cryptographic PRNGs can have very small periods, for
24
24
/// example less than 2<sup>64</sup>. Would reseeding help to ensure that you do
25
25
/// not wrap around at the end of the period? A period of 2<sup>64</sup> still
26
26
/// takes several centuries of CPU-years on current hardware. Reseeding will
@@ -31,30 +31,29 @@ use {Rng, SeedableRng, Error, ErrorKind};
31
31
/// # When should you use `ReseedingRng`?
32
32
///
33
33
/// - Reseeding can be seen as some form of 'security in depth'. Even if in the
34
- /// future there is found a cryptographic weakness in the used CSPRNG,
34
+ /// future a cryptographic weakness is found in the CSPRNG being used ,
35
35
/// occasionally reseeding should make exploiting it much more difficult or
36
36
/// even impossible.
37
37
/// - It can be used as a poor man's cryptography (not recommended, just use a
38
38
/// good CSPRNG). Previous implementations of `thread_rng` for example used
39
- /// `ReseedingRng` with the ISAAC RNG. That algorithm, although seemingly
40
- /// strong, does not come with a security proof and does not meet the current
41
- /// standards for a cryptographically secure PRNG. By reseeding it very
42
- /// frequently (every 32 MiB) it seems safe to assume there is no attack that
43
- /// can operate on the tiny window between reseeds.
39
+ /// `ReseedingRng` with the ISAAC RNG. That algorithm, although apparently
40
+ /// strong and with no known attack , does not come with any proof of security
41
+ /// and does not meet the current standards for a cryptographically secure
42
+ /// PRNG. By reseeding it frequently (every 32 MiB) it seems safe to assume
43
+ /// there is no attack that can operate on the tiny window between reseeds.
44
44
///
45
45
/// # Error handling
46
46
///
47
47
/// If reseeding fails, `try_fill_bytes` is the only `Rng` method to report it.
48
- /// For all other methods `ReseedingRng` wil not panic, but try to handle the
49
- /// error intelligently. And if nothing helps, continue without reseeding.
48
+ /// For all other `Rng` methods, `ReseedingRng` will not panic but try to
49
+ /// handle the error intelligently; if handling the source error fails these
50
+ /// methods will continue generating data from the wrapped PRNG without
51
+ /// reseeding.
50
52
///
51
53
/// It is usually best to use the infallible methods `next_u32`, `next_u64` and
52
- /// `fill_bytes` because they can make use of this error handeling strategy.
53
- ///
54
- /// Use `try_fill_bytes` and possible `try_reseed` if you want to handle
55
- /// reseeding errors explicitly. All reseeding errors will either be
56
- /// `ErrorKind::Transient` or `ErrorKind::NotReady`, and contain the original
57
- /// error as cause.
54
+ /// `fill_bytes` because they can make use of this error handling strategy.
55
+ /// Use `try_fill_bytes` and possibly `try_reseed` if you want to handle
56
+ /// reseeding errors explicitly.
58
57
#[ derive( Debug ) ]
59
58
pub struct ReseedingRng < R , Rsdr > {
60
59
rng : R ,
@@ -81,19 +80,19 @@ impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
81
80
}
82
81
}
83
82
84
- /// Reseed the internal RNG.
85
- ///
86
- /// On error, this will try to intelligently handle reseeding. If the error
87
- /// kind indicates retrying might help, it will immidiately retry a couple
88
- /// of times. If the error kind indicates the seeding RNG is not ready, it
89
- /// will retry after a while, after `threshold / 256` generated bytes.
83
+ /// Reseed the internal PRNG.
90
84
///
91
- /// If the seeding RNG has an other error or a permanently failure, it will
92
- /// completely skip reseeding. Only after generating `threshold` bytes it
93
- /// will retry again.
85
+ /// This will try to work around errors in the RNG used for reseeding
86
+ /// intelligently. If the error kind indicates retrying might help, it will
87
+ /// immediately retry a couple of times. If the error kind indicates the
88
+ /// seeding RNG is not ready, it will retry later, after `threshold / 256`
89
+ /// generated bytes. On other errors in the source RNG, this will skip
90
+ /// reseeding and continue using the internal PRNG, until another
91
+ /// `threshold` bytes have been generated (at which point it will try
92
+ /// reseeding again).
94
93
#[ inline( never) ]
95
94
pub fn reseed ( & mut self ) {
96
- trace ! ( "Reseeding RNG after {} generated bytes" ,
95
+ trace ! ( "Reseeding RNG after generating {} bytes" ,
97
96
self . threshold - self . bytes_until_reseed) ;
98
97
self . bytes_until_reseed = self . threshold ;
99
98
let mut err_count = 0 ;
@@ -103,14 +102,14 @@ impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
103
102
let kind = e. kind ( ) ;
104
103
if kind. should_wait ( ) {
105
104
self . bytes_until_reseed = self . threshold >> 8 ;
106
- info ! ( "Reseeding delayed, retrying after {} generated bytes" ,
105
+ warn ! ( "Reseeding RNG delayed for {} bytes" ,
107
106
self . bytes_until_reseed) ;
108
107
} else if kind. should_retry ( ) {
109
108
err_count += 1 ;
110
109
// Retry immediately for 5 times (arbitrary limit)
111
110
if err_count <= 5 { continue ; }
112
111
}
113
- info ! ( "Reseeding failed, RNG remains unchanged . Error: {}" , e) ;
112
+ warn ! ( "Reseeding RNG failed; continuing without reseeding . Error: {:? }" , e) ;
114
113
}
115
114
break ; // Successfully reseeded, delayed, or given up.
116
115
}
@@ -121,7 +120,8 @@ impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
121
120
///
122
121
/// If reseeding fails, return an error with the original cause. Note that
123
122
/// if the cause has a permanent failure, we report a transient error and
124
- /// skip reseeding.
123
+ /// skip reseeding; this means that only two error kinds can be reported
124
+ /// from this method: `ErrorKind::Transient` and `ErrorKind::NotReady`.
125
125
#[ inline( never) ]
126
126
pub fn try_reseed ( & mut self ) -> Result < ( ) , Error > {
127
127
trace ! ( "Reseeding RNG after {} generated bytes" ,
0 commit comments