-
Notifications
You must be signed in to change notification settings - Fork 430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is CryptoRng
useful?
#543
Comments
Since the rationale of fn do_something_secret<CR: Rng + CryptoRng>(rng: &mut CR) { ... } And it would still allow user-defined types to implement the traits, though of course we recommend only implementing on types which manage seeding internally. For example: pub struct SecureRng(Hc128Rng);
impl SecureRng {
pub fn new() -> Self {
SecureRng(Hc128Rng::from_entropy())
}
}
impl RngCore for SecureRng { /* derive core functions */ }
// Do NOT implement SeedableRng for SecureRng!
impl CryptoRng for SecureRng {} |
I agree that
Changing the definition of In summary, I think generic code involving |
We could do runtime checking by providing a function like
for which that
We should not even implement
|
@burdges I already mentioned runtime checking in the first post. I don't like it, because e.g. |
Is this doable entirely at the type level once the
We could give CSPRNGs a type level parameter like:
but I fear this will become annoying in practice. There are interesting type level work around with wrapper types:
We could also split
We'd simply explain that |
I dislike all these answers myself actually. :) In fact I'll add several concerns that count against Tests or benchmarks in cryptographic crates might employ non-cryptographic PRNGs, like Xorshift, maybe so that benchmarks more accurately represent the crate's actual work, or maybe because the standard is written that way. It's common curve libraries, etc. have functions to build an element with an There are various cryptographic properties one might consider here, including the security level. |
I see @quininer has used All these examples are part of a generic API: allowing some kind of secret to be seeded from a user-provided secure RNG. For these usages I think it makes sense to keep pub trait CryptoRng {
// like SeedableRng's version, but also require CryptoRng
fn from_rng<R: RngCore + CryptoRng>(mut rng: R) -> Result<Self, Error>;
} We could then implement In practice: this means that CSPRNGs would have two "guises": the seedable variant (impls |
Isn't that going to break
But.. I disagree strongly with not implementing There are ways to consider the CSPRNG inputs when doing formal verification, but this requires languages with much stronger dependent types, like F*, and even languages that understand game-hopping proofs, like CryptoVerif/ProtoVerif. There is a tentative project to compile Rust to F* for these purposes, btw. Also, we should not imho go with runtime checking but my initial runtime musings actually did handle
But |
Good argument @burdges. Then I guess we should do nothing here. I brought this up because in #537 @vks keeps saying that |
It's a tradeoff. On the one hand, |
If |
No, because either the type I don't see some halfway-house solution (deliberately breaking |
What's the decision here? Keep the status quo? |
Yes. @burdges is right that we can't really just make Runtime checking would be a partial fix, but then really we'd want to modify fn from_seed(seed: Self::Seed, is_crypto: bool) -> Self; (or wrap the boolean with a struct / enum, but same effect) The status quo is poor but |
Yes, I think a |
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):
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:
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:
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:
CryptoRng
from PRNG algorithms and keep only onOsRng
,JitterRng
,EntropyRng
andThreadRng
(which all manage their own seeding or directly get entropy from external sources)CryptoRng
trait altogetherThe text was updated successfully, but these errors were encountered: