If you, as a developer who doesn't know much about random numbers or cryptography, think you need a random value, and you don't know if it needs to be cryptographically secure or not, you may as well just use a cryptographic RNG interface (unless you're using so much that performance or entropy becomes an issue.)
I think in most cases, it's pretty benign if you use cryptographic randomness even when it's not necessary. But, if you use math/rand when you wanted cryptographic randomness, to generate IDs or some such, that would be a much worse outcome.
Maybe it's bad for someone to use an RNG without understanding this well enough, though, and they should instead use a higher level abstraction if at all possible. But I can get behind the general idea.
> If you, as a developer who doesn't know much about random numbers or cryptography, think you need a random value, and you don't know if it needs to be cryptographically secure or not, you may as well just use a cryptographic RNG interface (unless you're using so much that performance or entropy becomes an issue.) I think in most cases, it's pretty benign if you use cryptographic randomness even when it's not necessary. But, if you use math/rand when you wanted cryptographic randomness, to generate IDs or some such, that would be a much worse outcome.
This is more or less what I was getting at. The main two downsides to using crypto/rand are:
- ergonomics (crypto/rand is a less user-friendly interface than math/rand)
- concurrent performance
The first one can be easily solved with a wrapper[0]. The second is particularly relevant here, because the main distinguishing feature of the global RNG in math/rand is that it is safe for concurrent use, whereas user-instantiated RNGs in math/rand are not. The big downside to this is that it's very easy to end up with performance issues due to mutex contention when multiple packages all use the global RNG (which is common in practice).
I actually submitted a CL (patch) to fix the mutex contention issue in the global RNG about five years ago, but it was rejected on the grounds that callers might depend on the specific sequence of numbers with the default seed, which would arguably break the compatibility promise. That apparently is no longer a concern (this change breaks the same thing, and the notes in the CL justify it), so I might resubmit it now.
crypto/rand is a little less performant in the single-threaded case, but not much - I think it'd be rare for that to be the bottleneck in real-life workloads at scale. The mutex, on the other hand, is a common bottleneck - I've run into this multiple times in multiple different codebases, one of which is what motivated the aforementioned CL.
So I generally advise people to use crypto/rand unless they are certain they need reproducibility, because the potential downside of accidentally using a non-secure RNG when you actually need one is quite high[1], but the downside of using a threadsafe cryptographically-secure one when you needed a threadsafe non-secure one is quite low: you're already taking much of the performance hit because of the mandated mutex, so the number of use cases that actually require the global RNG is quite small.
[1] there are a number of places where RNGs end up being used that don't obviously result in exploits but nevertheless result in exploits in practice. For the average developer, it's easiest just to avoid that quagmire altogether, rather than try to reason about the potential adversaries (and potentially get that wrong).
If you, as a developer who doesn't know much about random numbers or cryptography, think you need a random value, and you don't know if it needs to be cryptographically secure or not, you may as well just use a cryptographic RNG interface (unless you're using so much that performance or entropy becomes an issue.)
I think in most cases, it's pretty benign if you use cryptographic randomness even when it's not necessary. But, if you use math/rand when you wanted cryptographic randomness, to generate IDs or some such, that would be a much worse outcome.
Maybe it's bad for someone to use an RNG without understanding this well enough, though, and they should instead use a higher level abstraction if at all possible. But I can get behind the general idea.