I have read plenty about the distinction between /dev/random and /dev/urandom. I understand that the prevailing advice is to use /dev/urandom. The explanation - that 256 bits of 'proper' randomness is all you need for almost any cryptographic application - makes sense to me.
A couple of helpful sources:
- https://pthree.org/2014/07/21/the-linux-random-number-generator/
- http://www.2uo.de/myths-about-urandom/

The state of a virtual machine (VM) or live CD right after first boot is sometimes identified as an unusual edge case to this guideline, as /dev/urandom may not have been properly seeded.

In context of all the other possible uses of /dev/urandom, I can see that this is an edge case. However, given that you are using a VM for the first time, it seems plausible that one of the first things you might want to do is call on /dev/urandom, e.g. to generate SSH keys.

So, if you assume the worst about your VM (e.g. that it was cloned, or that after a reboot the newly seeded randoms are no good), what could you do to make sure that /dev/urandom is good to go?

The laziest thing to do seems to be to let the VM just sit running for a little while, until random events have re-seeded the input pool. The awkward part is that an idle VM does this quite slowly.

I wanted to test how long it takes for this to happen, and I tried to do so as follows:

This command pulls 32 bytes/256 bits from the pool (and displays in hex)
head -c 32 </dev/random | xxd -p

Once the input pool's entropy count has gone to minimal levels (visible with cat /proc/sys/kernel/random/entropy_avail), the command above will block until new random events enter the input pool. That suggests to me that if we run the above command repeatedly, time it, and write the results to a file called randomtest it will indicate how long it takes to refill the input pool.

I tried writing a one-line command which does so:
for n in {1..10}; do (/usr/bin/time -f "%E Real" sh -c 'printf "%-10s" $(head -c 32 </dev/random | xxd -p)' 2>&1) >> randomtest; done

More readably:

for n in {1..10};
do (/usr/bin/time -f "%E Real" sh -c \
    'printf "%-10s" $(head -c 32 </dev/random | xxd -p)' 2>&1) \
    >> randomtest; 

I know that starting processes (even the cat command above) draws down the input pool, so this will provide a conservative estimate. For what it's worth, I let the above command run on an inactive VM, and the time between fresh 32-byte sequences was a steady 15-20 minutes each.

My questions:

  • Does the output of this command successfully test what I think it does?
  • Is there a much simpler way to test the same thing?
  • Is there a different/better 'lazy' way to refresh the input pool and re-seed /dev/urandom than letting the VM sit idle?

I'm not an expert on the nuances between urandom and random but based on your description it would seem your test is correctly approximating the time to refill the input pool. I'm not aware of any tools that do this kind of testing.

There is a better way to reseed urandom to prevent stale state affecting the quality of the random data though, and that's to write random data in urandom.

This can be done on cloud providers using cloud-init and on VMs at boot time by running some instance metadata through a hash function and writing it to urandom. This could also be part of a configuration management solution using Chef, Ansible, Puppet, etc and pull a random seed from your local machine.

Note that this doesn't increase the overall entropy count, it just sets a fresher seed. From man 4 random

Writing to /dev/random or /dev/urandom will update the entropy pool with the data written, but this will not result in a higher entropy count. This means that it will impact the contents read from both files, but it will not make reads from /dev/random faster.

  • Thanks for the pointer to cloud-init. Could you clarify what you meant by running instance metadata through a hash function and writing to urandom? [I assume this means you need a random input to the hash function, but isn't that the very thing that's lacking?] – SauceCode Mar 27 '16 at 22:31
  • In my view, the enemy is known state. In a low entropy system with known state a hash function's output of known input might be able to be determined. Instance metadata should contain information like an externally generated random instance id, a time stamp, a base image id, etc. Because this data isn't available before boot time and difficult to predict, the theory is that is should provide sufficient hashing fodder to avoid known state. Here's a good write up about using cloud instance metadata to seed urandom: blog.dustinkirkland.com/2012/10/… – Matt Surabian Mar 29 '16 at 0:00

If you do not have a hardware rng you can give vm's entropy by running haveged as a daemon on the host.

I use it in my Alpine Linux install scripts to provide enough entropy to create a luks filesystem on a brand new installation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.