Article | Talk | Edit | History  

/dev/random

From the World Wide Wiki

"Freedom of speech is the right to yell "Theater" in a crowded Fire" - Abbie Hoffman

<
Jump to: navigation, search

Adding entropy

Please note that the following is not a great idea. Using gzip to remove non-randomness is really not sufficient, you're much better off passing a large amount of alleged entropy into a cryptographic hash function like sha256, and taking the 32 bytes of output as your random data. The lower your confidence in the true randomness of your data, the more of it you should pass into the hash before taking any output. For instance, if you estimate that the data contains about 0.1 Shannons per bit, you would want to pass a minimum of 320 bytes of data in before taking the 32-byte output. If you suspect your data only has 0.01 Shannons per bit, pass in a minimum of 3200 bytes before taking output. Generally speaking, estimating the entropy of arbitrary data is non-trivial and inaccurate, so assume your data has very low entropy and pass a ton into the hash before taking output. Another good idea is using various sized entropy pools as in the Fortuna PRNG. (see Fortuna)

Deprecated

Generically, you may be able to come up with some good sources of entropy that the kernel doesn't know about. I advice you to be extremely careful with this as things that seem random may actually be extremely vulnerable to attacks. Only use entropy sources that are actually random, not just pseudorandom or hard-to-guess. For instance, I have an old clock radio where I replaced the speaker with a stereo cable. I tuned it to static and fed it into my microphone jack (carefully setting the volume so as not to clip or overload the sensitive microphone jack). This should be a pretty good source of genuine randomness.

Anybody can generally write to /dev/random, and put data into the entropy pool. As long as the entropy estimate is not increased, this should not affect security. However, it also does you know good if you don't increase the entropy estimate. To do that, you need to use the RNDADDENTROPY ioctl on the /dev/random device. You could write an easy program to do this yourself, but there's already a nice tool called rngd to do this for you. Basically, I think all this tool does is read from a device, test it for randomness, estimate it's entropy, and then write it to the entropy pool and increment the entropy estimate accordingly. The trick is, getting it to accept your data.

rngd uses a suite of randomness tests called FIPS-140, and throws away any data blocks that fail this test. Unfortunately, most entropy sources you're likely to come up with will fail these tests miserably because they contain some random and some non-random data. For instance, my radio static fails these tests that vast (VAST) majority of the time (much more than 99.9% failure). The key is to extract the randomness from the data, and through away the rest. Then, you'll pass the tests with a good probablity (there are some false negatives in these tests) and rngd can put it in the entropy pool.

Fortunately, every Unix-like system has a tool built in for doing just that: gzip. Yes, simple compression. The whole point of compression is to remove all redundancy, which is to say everything that's not random. Passing your entropy source through gzip or some other good compression utility will do a good job of increasing the randomness of your data and therefore increasing the chances that it'll pass the FIPS tests. Just passing the data into gzip increases my pass rate to something like 66%.

Okay, so start by installed rngd and preferably rngtest. On Fedora (and probably other Redhat based distros), you should be able to install it as a package named rng-utils. Most other places it's called rng-tools. The source is easy to build, and available on Sourceforge. Look for rng-tools on this page (or go straight to the version 2 download here). Once installed, you should have rngd and rngtest available.

To keep your pool pretty much filled to the brim all the time, I did this (has to be as root, otherwise you probably won't be allowed to issue the necessary RNDADDENTROPY ioctl):

cat /dev/dsp | gzip -c | rngtest -p | rngd -f -r /dev/stdin

The first part dumps the contents of /dev/dsp, which is the sound card where I have the radio plugged in (if you're doing this, turn on your speaker (starting nice and low) and play with your volume controls to make sure you're actually getting static in). The second part compresses it and dumps it to stdout. Gzip is a stream compressor so this works fine, no need to cut up the input into blocks or anything. Then I pass it through rngtest with the -p "pipe" option. This option tells rngtest to be quiet (not dump statistics or test results) and to just silently drop any blocks that fail the tests, and forward blocks that pass the tests to stdout. This part isn't technically necessary, but it makes sure all the data going into rngd passes the fips tests, so that rngd doesn't keep dumping "failed fips test" to the console. The last part actually starts rngd (in foreground, as opposed to daemon/background mode, that's the -f option) and the -r option tells is to read from stdin, instead of /dev/hwrandom. Of course, if you have /dev/hwrandom, then just use that.


This article is a stub.