What's hard is accurately surveying the last 15 years of systems built on top of Linux's needlessly-complicated LRNG and making changes that don't violate the expectations of those systems. Nobody should be running "jitter entropy daemons" in userland (userland RNGs are essentially the source of all practical CSPRNG vulnerabilities in the past 2 decades), but people do, and if those systems exceeded some threshold of security before Donenfeld's patches, you can't merge those patches if they push security below that threshold.
It's a really irritating problem.
... no pun intended, I'm sure.
But Linux must continue to work even on VMs without that, and that is the hard part.
Is your point that CSPRNGs should not be implemented in userland, but instead should just read from /dev/random or do the equivalent on non-linux opperating systems?
[1]: https://sockpuppet.org/blog/2014/02/25/safely-generate-rando...
Why not break their code? Seems justified in this case.
Sounds like they need a compatibility or feature (cmdline) flag.
Add the flag and you can use the new improved system. Establish dates for when the old method will not be the default anymore (but can be used with the flag) and when it will be deprecated for good
I’m not sure if the Linux folks find something wrong with existing, time tested approaches or if there’s some NIH going on, but it doesn’t seem like a multi-decade problem.
uint64_t lemur64(void) {
static uint128_t s =
(uint128_t)426679527491843471ull << 64 | 2131259787901769494ull;
return (s *= 15750249268501108917ull) >> 64;
}
Passes bigcrush and PractRand and it won't ever cause your system to hang on boot.There's some math that goes into picking a good constant, but honestly that's optional. Usually you'd also add a constant each round but this is going for absolute simplicity.
And the line with 'static' is just an awkward way of initializing the state integer.
It isn’t optional. For example, if your constant is even, every iteration adds another zero to the end of your state, and after (in this case) 127 iterations, you’ll start returning zeroes forever.
Also, if your multiplier is smallish, the lower order ones of the current value can be used to (somewhat) predict the higher order ones of the next value.
If you're particularly worried about the top couple digits of the number being undersized you could return fewer bits or use a wider multiplier.
Wholly unsuitable for cryptographic random numbers.
Think of it in terms of VM snapshots. If you boot from a snapshot, there’s no way to get any timestamp guaranteed to be secure.
But “secure” in this context is misleading. I subscribe to the “just use urandom” school of thought. It’s sufficiently secure in practice that no real security threats have emerged (can anyone point to a CVE?) and it seems like a waste of time to focus on this rather than the hundreds of other cases that cause dozens of CVEs.
So it should be fine to add in, but I don't know how many bits you'd want to count that as.
https://factorable.net/weakkeys12.extended.pdf
which is still happening:
https://www.quintessencelabs.com/wp-content/uploads/2020/03/...
https://www.developer.com/guides/how-we-learned-to-cheat-at-...
"The system clock seed gave us an idea that reduced the number of possible shuffles even further. By synchronizing our program with the system clock on the server generating the pseudo-random number, we are able to reduce the number of possible combinations down to a number on the order of 200,000 possibilities. After that move, the system is ours, since searching through this tiny set of shuffles is trivial and can be done on a PC in real time."