My intuition is that every operation we do (start TCP connections, generate keys, backoff after a failed login, ....) reveals a tiny fraction of a bit about that hidden state, web assembly calling random over and over again probably reveals much much more, over time it builds up.
(anyone want to guess if there's a quantum computer attack here, it kind of looks like the sort of problem where there might be)
So I think that with a sophisticated enough attacker entropy does degrade, the trick is to replace that entropy at a faster rate that the rate at which you guess the worst case attacker might be able to guess.
For most people it probably doesn't matter, you're exposing so little state over time you're likely effectively as safe as the parent poster claims, it kind of depends on whether, in this age when we know that nation state actors are watching every packet that passes thru their hands, watching every thing we're doing online, are you interesting enough for them to spend the time and effort? does the US/5Is think you're not a Trump supporter? are the Chinese interested in your trade secrets? whi knows what the Russians think
As I mentioned above using /dev/urandom doesn't have a mechanism you can use to signal this guess about how much entropy it needs over time to be safe, prior to 4.8 we used to have a mechanism that said "give it some more entropy every N seconds, 60 by default" but that's now broken
(provided here a python applet that periodically drains a little bit of /dev/random entropy if it has plenty available to stir the input pool that /dev/urandom uses for its entropy source)
That's a lot of words because the LRNG is overly complicated. But let's make it clearer: what you're saying about every TCP sequence number "revealing" part of the "hidden state" is exactly equivalent to the argument that every byte of AES-CTR ciphertext is revealing the hidden AES key. If that were the case, AES would be grievously broken.
If you don't believe that AES-CTR and the LRNG are roughly equivalent, try this thought experiment: retain the initialization functionality from the current LRNG --- building a pool of mixed and hashed unpredictable data from kernel events --- and scrap the rest of the LRNG, replacing it with... AES-CTR, using a hash of the entropy pool as its key. Reads from random/urandom (or kernel random reads, as with your sequence numbers) just tap bytes from the AES-CTR keystream. Is every TCP sequence number still revealing a little bit of the RNG state?
The Python script seems entirely silly to me; once the first read from /dev/random succeeds, you're guaranteed to have a fully initialized LRNG, and every subsequent read from urandom will be unpredictable and indistinguishable from random. Nothing is served by updating the LRNG after that point.
What you wrote is magical thinking.
However kernel entropy is real, adding more entropy to the entropy pool is always is always adding more entropy. If the pool had 1000 bits in it and you add 5 bits from the kernel and a fake 1000 bits from a bogus external source it still has 1005 bits of entropy (however /dev/random thinks it will be able to extract 2005 bits)
We actually encourage our customers who are particularly paranoid to lie to the kernel about the quality of the entropy our RNG generates - saying the entropy quality is lower than it really is causes more good quality data to be mixed into the kernel pool (of course the defaults don't do this)
The kernel pools are actually quite small (4k bits) so there's a real practical limit to how much you can play this sort of game
#! /usr/bin/python
#
# OneRNG /dev/urandom tickler
# (C) Copyright Paul Campbell Moonbase Otago 2018
# Released under a GPL 3.0 license
#
import time
with open("/dev/random", 'rb') as r:
while True:
with
open("/proc/sys/kernel/random/entropy_avail", 'r') as e:
iv = e.read()
print(iv)
if iv > 1500:
x= r.read(1000)
e.close()
time.sleep(1)Non-licensed English language version, containing the same information:
Once per second, read /proc/sys/kernel/random/entropy_avail and if the resulting number is more than 1500 perform a read of 1000 bytes from /dev/random.
Not licensing something is, ironically, restrictive. If you want to release to public domain (or equivalent), you have to explicitly mention that. E.g. by licensing under CC0.
Otherwise, default copyright and "all rights reserved" applies.
https://creativecommons.org/share-your-work/public-domain/cc...
(But, IMO, nothing wrong with publicizing use of GPL 3! :) thanks either way to both)
If someone writes the same one-sentence pseudocode as GP in a book or blogpost, nobody could reasonably claim that an implementation would fall under the copyright of that book. And I think you'd be very hard pressed to argue it's copyrightable just because someone typed it out into real code.
#!/usr/bin/env ruby
source = File.open('/dev/random', 'rb')
loop do
source.read(1000) unless File.read('/proc/sys/kernel/random/entropy_avail').to_i < 1500
sleep 1
endThe missing mechanism we're trying to emulate used to essentially read N bytes (whatever user space happened to want at the time) every M seconds our experience has been that that can be way more than 1000 bytes, but reduce it if you like
I think both the diagrams here are simplistic - in reality pre 4.8 there were 3 pools (an input pool and 2 output pools, one of which blocked) and post 4.8 where there are 2 pools, an input pool and a blocking pool (urandom now pulls from the input pool thru a CSPRNG).
One big downside of the new (post 4.8) architecture is that urandom_min_reseed_secs is ignored - pre-4.8 you could ask the kernel to periodically pull a little bit of real entropy from the input to refresh the urandom output (non-blocking) pool, by default that was once every 60 seconds, but in our case with lots of entropy available we'd set it to happen once a second - now post 4.8 it looks like urandom_min_reseed_secs is ignored and the input pool (where /dev/urandom gets its data from) is not regularly updated unless data is also pulled from /dev/random - which may make sense if entropy is rare, but is not so useful when back pressure from /dev/random is left to control the rate at which external entropy flows into the system - I suspect it's time to present a patch that makes urandom_min_reseed_secs work again
Nevertheless the conclusion "use /dev/urandom" is still valid