-
-
Notifications
You must be signed in to change notification settings - Fork 490
Description
Perhaps this can stay open for a while as a discussion item. I'd especially like feedback from lib users who have looked at this trait.
This trait has requirements on the PRNG algorithm, but not the seeding method (as comes up in #537):
/// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`]
/// implementation is supposed to be cryptographically secure.
///
/// *Cryptographically secure generators*, also known as *CSPRNGs*, should
/// satisfy an additional properties over other generators: given the first
/// *k* bits of an algorithm's output
/// sequence, it should not be possible using polynomial-time algorithms to
/// predict the next bit with probability significantly greater than 50%.
///
/// Some generators may satisfy an additional property, however this is not
/// required by this trait: if the CSPRNG's state is revealed, it should not be
/// computationally-feasible to reconstruct output prior to this. Some other
/// generators allow backwards-computation and are consided *reversible*.
///
/// Note that this trait is provided for guidance only and cannot guarantee
/// suitability for cryptographic applications. In general it should only be
/// implemented for well-reviewed code implementing well-regarded algorithms.
///
/// Note also that use of a `CryptoRng` does not protect against other
/// weaknesses such as seeding from a weak entropy source or leaking state.
///
/// [`RngCore`]: trait.RngCore.html
/// [`BlockRngCore`]: ../rand_core/block/trait.BlockRngCore.html
pub trait CryptoRng {}The trait can guarantee absolutely nothing about the quality of the seed used on the PRNG. For example, it would be quite easy to write:
let key = [0u8; 32];
// TODO: randomise the key
let rng = ChaChaRng::from_seed(key);and forget to actually add any entropy to the system.
Or, in some ways worse (because it is harder to spot), the key could be written using a non-crypto RNG (stretching an insecure key).
There is no easy way to guard against insecure seeding (and even if there were, there are other ways to go wrong in cryptography). Even if we added a function like this it wouldn't really help:
pub trait CryptoRng {
/// Implementations must estimate the number of bits of entropy in their seed
fn estimate_entropy(&self) -> u32;
}It would be simple enough to detect seeds with too many 0s or 1s, but still extra complexity to implement. Detecting that the seed was set by a weak PRNG however would be much much harder (computationally very expensive and very complex) — this is not viable.
Summary: security is a property of the complete implementation, not just the type.
So my conclusion: CryptoRng appears to be making a promise it cannot guarantee when implemented on PRNG algorithms.
Options:
- Keep the status quo; rely on documentation
- Remove implementation of
CryptoRngfrom PRNG algorithms and keep only onOsRng,JitterRng,EntropyRngandThreadRng(which all manage their own seeding or directly get entropy from external sources) - Remove the
CryptoRngtrait altogether