Skip to content
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

Auto-seeded randomness: thread_rng, weak_rng, random() #23

Closed
4 tasks
dhardy opened this issue Oct 27, 2017 · 13 comments
Closed
4 tasks

Auto-seeded randomness: thread_rng, weak_rng, random() #23

dhardy opened this issue Oct 27, 2017 · 13 comments

Comments

@dhardy
Copy link
Owner

dhardy commented Oct 27, 2017

The rand crate currently has:

  • weak_rng() — seeds a new XorShiftRng from OsRng on each call
  • thread_rng() — initialises a per-thread ISAAC generator from OsRng on first call and returns a reference
  • random() — convenience wrapper around thread_rng()
  • OsRng::new() — unlike other generators, can be created directly since it uses external entropy

But what do we want to provide? In terms of entropy:

  1. Strong entropy for direct usage or seeding crypto generators: OsRng
  2. "Good" entropy via OsRng or a fallback for cases where entropy is still important but not critical (stuff like HashMap which might possibly be open to a DoS attack or randomised algorithms)
  3. Weak entropy? For things which want some entropy (e.g. randomised algorithms and games) but aren't vulnerable to attacks or where it really doesn't matter. (It may be that the previous category covers this one too sufficiently anyway.)
  4. Deterministic (seeded) generators: no entropy

In terms of convenient random numbers it gets more complicated, because we potentially have a matrix of entropy vs speed and memory requirements, via a thread-local generator or a fresh generator. But most importantly:

  1. Direct access to strong entropy (OsRng)
  2. Direct access to reliable entropy (OsRng or fallback)
  3. (Possibly) direct access to fast entropy (ClockRng or some such)
  4. A generator which provides a good trade-off between strength and performance without necessarily having true cryptographic strength: thread_rng
  5. Some recommended PRNGs providing various trade-offs between performance, memory usage and quality, which can be easily seeded from either fresh entropy or a fixed seed

The existing weak_rng() really satisfies only one variant of the last case, and personally I see little justification for keeping it over something like SmallFastRng::from_rng(reliable_entropy()). On the other hand, one shouldn't use SmallFastRng directly for deterministic generation (since the underlying generator may change), so SmallFastRng::from_rng(reliable_entropy()) appears to be the only use-case.

The existing StdRng is in a similar position: it shouldn't be used for reproducibility, hence its only real use is the current thread_rng().

To do:

  • Implement a good fallback generator
  • Do we also want a fast, weak clock-based generator?
  • Is weak_rng + thread_rng + direct access to entropy generators sufficient?
  • Is usage sufficiently clear (e.g. that thread_rng is not for cryptography)?
@dhardy dhardy added this to the Entropy and convenience generators RFC milestone Oct 27, 2017
@pitdicker
Copy link

pitdicker commented Oct 27, 2017

Good overview.

But what do we want to provide? In terms of entropy:
3. Weak entropy?

What would the use be? I can only see performance as a reason. It seems to me there are better options than going down that route. If / when we get support for PCG streams and jumping could be good solutions to get a separate rng quickly from an existing one. An other is to initialize a cryptographic rng once, and use that to initialize others.

If someone really has a need for this, it could also be part of an external crate. That seems better to me, as anything rand provides has a good chance to be misused.


I would not mind removing weak_rng(). It seems to me its only reason for existing is that it makes a fast and weak RNGs easily discoverable. That can also be solved with good documentation and an example.

StdRng also feels like a documentation issue to me. Its use is basically to help users to quickly choose an rng. Would TreadRng than not always be the better and more ergonomic choice?

Is usage sufficiently clear (e.g. that thread_rng is not for cryptography)?

There has been some discussion that maybe it should be. Would ChaCha with fewer rounds be a possible replacement?


Do we also want a fast, weak clock-based generator?

If we end up with something that works well, it could potentially be useful for no_std. If the function that gets the current time can be supplied by the user, it can be used as a randomness source on embedded (?).

As a note about fallback generators: RDRAND could be useful here too.

@dhardy
Copy link
Owner Author

dhardy commented Oct 27, 2017

What would the use [of weak entropy] be?

Then you and I are both surprised by @alexcrichton merging rust-random#181.

@alexcrichton
Copy link

@dhardy oh sorry I thought you were already ok with it! If you're worried about that I'm ok reverting

@dhardy
Copy link
Owner Author

dhardy commented Oct 29, 2017

The question really is are people using thread_rng where strong entropy matters, on systems where OsRng might not work? It's an edge case which shouldn't cause security issues, but you never know. I'd be happier replacing that generator with the StrongClockRng from this PR. If @pitdicker agrees I'll make a new PR against rand master (as an interim solution).

@pitdicker
Copy link

I would be happy with something stronger too. As discussed in #21 (comment) something based on jitterentropy-library may be even better. I now have a rust implementation of that mostly ready. The C code is translated, assembly looks sufficiently non-optimized, and PractRand is happy with the results. It still needs some better comments and documentation, a few statistical test (from older versions of jitterentropy), and a bit more detailed errors.

If there is not a great hurry, maybe that is a better option.

@alexcrichton
Copy link

@dhardy oh I was basing it off https://docs.rs/rand/0.3.17/rand/#cryptographic-security which states:

An application that requires an entropy source for cryptographic purposes must use OsRng

@dhardy
Copy link
Owner Author

dhardy commented Oct 30, 2017

That's the intended way of obtaining secure entropy @alexcrichton; that doesn't mean people always read the instructions. That plus potential DoS attacks on HashMap is why there's still some value in making thread_rng reasonably secure (i.e. no known attacks).

@alexcrichton
Copy link

True! I'm not sure how else it's possible to fix rust-random#180 though?

@dhardy
Copy link
Owner Author

dhardy commented Oct 30, 2017

Leave it as is for now @alexcrichton; we'll open a new PR when we have a stronger candidate. I don't think there's any other strategy available (other than don't fix).

@dhardy
Copy link
Owner Author

dhardy commented Nov 22, 2017

@pitdicker now that JitterRng has been merged into my branch, do you think we should make a PR against upstream to improve on rust-random#181? Since it's your code I guess you should get the credit ;)

@pitdicker
Copy link

Yes, we promised to try and improve upon that. I suppose that we can't just merge this whole branch in rand as-is yet. It would be a breaking change, but there are still some things left to do...

I will be careful with credit for others, but don't mind it much for myself. This is just for fun. And it seems you did about as much work around this code as I did ;-).

If you want to make a pr feel free, otherwise I will prepare one this weekend.

@dhardy
Copy link
Owner Author

dhardy commented Nov 22, 2017

Ok, I'll probably look at that tomorrow.

No, I don't think we can just merge the whole branch. There's still some work to finish the rand-core proposal and then some more to present the other changes (distribution, thread_rng, PRNGs). But I think it's worth getting JitterRng merged sooner rather than later and it's mostly independent of other stuff.

@dhardy
Copy link
Owner Author

dhardy commented Mar 11, 2018

I don't think this is useful any more; we have JitterRng, still have #22 for discussion of fallbacks; rust-random#289 discusses these functions.

@dhardy dhardy closed this as completed Mar 11, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants