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

Improve documentation for Random::Secure #8484

Merged

Conversation

straight-shoota
Copy link
Member

Adds documentation based on @ysbaddaden's comment in #6340 (comment)

# For generating *high quality* random numbers, a pseudorandom number generator
# (PRNG) such as `Random::PCG32` should be used instead, or preferably one with
# more state (e.g. `xoshiro256**`). These number generators are much faster
# than `Random::Secure`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be nuanced: using a non cryptography quality PRNG and exposing the numbers can lead to reversing the seed of the RNG, leading an attacker to know the following generated numbers in advance. There are scenarios where this can be acceptable (e.g. generating an UUID for database IDs) and scenarios where this can be exploited (e.g. online game).

@@ -17,15 +19,19 @@ require "crystal/system/random"
# For generating *high quality* random numbers, a pseudorandom number generator
# (PRNG) such as `Random::PCG32` should be used instead, or preferably one with
# more state (e.g. `xoshiro256**`). These number generators are much faster
# than `Random::Secure`.
# than `Random::Secure` and suitable for many use cases with lower
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without instead of lower.

For a slightly lower security (because of user-space instead of kernel), an user-space CSPRNG such as ISAAC or ChaCha20 can be used.

Yes, RNG and security is complex and full of devils in tiny details. I barely grasp them 😭

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish someone with good knowledge of RNG and such details would write such documentation.

@ysbaddaden
Copy link
Contributor

I thought about this for the past few days, and I vote to close.

Nobody here has enough knowledge on cryptography or generating random numbers in general to be capable to say which [CS]PRNG should be used. Expect maybe @oprypin or @konovod? Certainly not me.

Selecting a [CS]PRNG is very complex and depends on lots of deciding factors:

  • what's the purpose? physics simulations? online gaming? cryptography?
  • will numbers be exposed publicly? most PRNG can be reversed with just a few numbers, leading to know incoming numbers;
  • do numbers need to be reproducible (important for physics simulations and more)? a regularly reseeded RNG like the system CSRNG won't fit;
  • what numbers must be generated? i8, i16, i32, i64, f32, f64, bytes, UUID?
  • is generation speed a factor?
  • ...

It's also impossbile to find third-party peer reviews of popular PRNG. For example PCG and XoShiRo are only criticised by their respective authors, then Daniel Lemire ran a few tests, and that's about it 😭

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Nov 23, 2019

Or we should just say:

Generates random numbers from a secure source provided by the system.

Random::Secure is a Cryptographically Secure Random Number Generator (CSPRNG) and should always be used for secure usages (Cryptography, generating secret keys, ...), when values may be exposed (e.g. UUID) or to seed another PRNG (secure or not).

Choosing another [CS]PRNG should always be the result of a thorought investigation of all the deciding factors (security, reproducibility, reversibility, the type of numbers to generate, generation speed, state and period sizes, ability to jump ahead, ...) and whether numbers are exposed (use a CSPRNG) or not, in which case you may decide to use a non cryptographically secure PRNG.

When in doubt: use Random::Secure. It uses the best known source, both in terms of security and performance, of the current system.

@oprypin
Copy link
Member

oprypin commented Nov 23, 2019

Now that one I definitely disagree with. That's definitely not the common advice. And relying on commonness is the only thing we can do, I'm afraid.
As a side note related to that, I still have no idea how PCG came to be the default 😂

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Nov 23, 2019

Aparte (unrelated to Random::Secure):

The default PRNG used to be Mersenne Twister which is neither good, fast, or memory efficient. PCG32 was a good all rounder to replace it.

The generic rand() doesn't need to be secure or to return 64-bit numbers —we only need an i32 to shuffle an array for example. We settled on PCG32 that was better than XorShift (that fails some BigCrush tests), and had an overall better performance on different targets (with and without --release). Not having to be secure, we skipped the slower ISAAC and ChaCha20.

We didn't evaluate Java's Splittable Random at the time (then made available in crystal-random) or the SplitMix64 variant (pending PR). We didn't evaluate XoShiRo (or XoRoShiRo). I'm not sure they were released at the time (or very recently).

If Int becomes platform-specific (see another RFC) we'll probably revise this, since PCG64 requires Int128 support (or two PCG32 generators) to generate 64-bit numbers. Random::Splittable could be a good choice, since it can generate both u32 and u64, and it's ability to split, so we could have related, yet independent, RNGs for each scheduler thread. XoShiRo256 could be another good choice thanks to its 256-bit of state.

# on Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom),
# and falls back to reading from `/dev/urandom` on UNIX systems.
#
# For generating *high quality* random numbers, a pseudorandom number generator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather remove this whole paragraph. "high quality" is pretty confusing and undefined.

@ysbaddaden
Copy link
Contributor

Closing. I said 💩. Always ask and listen to security people, not me!

@ysbaddaden ysbaddaden closed this Nov 29, 2019
@RX14
Copy link
Member

RX14 commented Nov 29, 2019

This whole pull request does not have to be closed, only the security advice removed.

@straight-shoota straight-shoota merged commit 12a1053 into crystal-lang:master Jan 7, 2020
@straight-shoota straight-shoota deleted the feature/random-doc branch January 7, 2020 17:51
@straight-shoota straight-shoota added this to the 0.33.0 milestone Jan 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants