21

Typically reading from /dev/random produces 100-500 bytes and blocks, waiting for an entropy to be collected.

Why doesn't writing information to /dev/random by other processes speed up reading? Shouldn't it provide the required entropy?

It can be useful for unblocking gpg or similar software without restarting it and re-entering everything, for generating non-super-top-secret keys, etc.

  • 2
    Just read from /dev/urandom instead. /dev/urandom is as secure as /dev/random for cryptographic use, the behavior of /dev/random is bad design. – Gilles Jul 7 '14 at 22:23
  • How to switch gpg --gen-key from /dev/random to /dev/urandom without restarting? – Vi. Jul 7 '14 at 22:33
  • IIRC gpg has /dev/random hard-coded. You can change your udev configuration to make /dev/random the same device as /dev/urandom, among other possibilities. – Gilles Jul 7 '14 at 22:39
  • @Gilles, it still requires restarting gpg --gen-key, therefore re-endering data it interactively asks (or using more clever methods like specifying more command line parameters). Also CPU time generating the prime whould be lost (gpg can work a minute, print some +es and then request additional random data). And it gives "let's go back and go other route" feeling instead of "let's take a hammer and force it forward"... – Vi. Jul 7 '14 at 22:41
19

You can write to /dev/random because it is part of the way to provide extra random bytes to /dev/random, but it is not sufficient, you also have to notify the system that there is additional entropy via an ioctl() call.

I needed the same functionality for testing my smartcard setup program, as I did not want to wait for my mouse/keyboard to generate enough for the several calls to gpg that were made for each test run. What I did is to run the Python program, which follows, in parallel to my tests. It of course should not be used at all for real gpg key generation, as the random string is not random at all (system generated random info will still be interleaved). If you have an external source to set the string for random, then you should be able to have high entropy. You can check the entropy with:

cat /proc/sys/kernel/random/entropy_avail

The program:

#!/usr/bin/env python
# For testing purposes only 
# DO NOT USE THIS, THIS DOES NOT PROVIDE ENTROPY TO /dev/random, JUST BYTES

import fcntl
import time
import struct

RNDADDENTROPY=0x40085203

while True:
    random = "3420348024823049823-984230942049832423l4j2l42j"
    t = struct.pack("ii32s", 8, 32, random)
    with open("/dev/random", mode='wb') as fp:
        # as fp has a method fileno(), you can pass it to ioctl
        res = fcntl.ioctl(fp, RNDADDENTROPY, t)
    time.sleep(0.001)

(Don't forget to kill the program after you are done.)

  • 1
    Much simpler solution would be to use rngd. It's available as a package in most (all?) distros. – Patrick Jul 7 '14 at 21:07
  • 4
    random = "3420348024823049823-984230942049832423l4j2l42j" see xkcd.com/221 – immibis Jul 8 '14 at 0:21
  • @Patrick I tried at least 3 potential solutions for adding randomness, IIRC rngd was one of them. But they would not work out of the box (it could be the Ubuntu 12.04 setup at the time), and for me this solution, with 10 lines of code, was simpler. – Anthon Jul 8 '14 at 2:22
  • @Anthon: as a sidenote, I haven't seem xs4all.nl since mitnik used it to store some things, decades ago... :) – woliveirajr Jul 8 '14 at 16:26
  • @woliveirajr, I had my account from hacktic.nl transferred there somewhere in 1992, I have been there a while although I haven't lived in the Netherlands for over 20 years now. – Anthon Jul 8 '14 at 16:40
14

Typically, it's designed by kernel developers and documented in 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.
1

Anthony already explained that writing to /dev/random does not increase the entropy count and showed how the RNDADDENTROPY ioctl (see random(4)) can be used to credit for entropy. It is obviously not really secure, so here is an alternative when a hardware random number generator is available.

The following implementations take 512 bytes (4096 bits) of randomness from /dev/hwrng and forward it to the entropy pool (crediting 4 bits of entropy per byte, this is an arbitrary choice from me). After that it will invoke the select(2) syscall to block when the entropy pool is full (documented in the random(4) manpage).

A Python version:

import fcntl, select, struct
with open('/dev/hwrng', 'rb') as hw, open('/dev/random') as rnd:
    while True:
        d = hw.read(512)
        fcntl.ioctl(rnd, 0x40085203, struct.pack('ii', 4 * len(d), len(d)) + d)
        select.select([], [rnd], [])

Since the Arch Linux iso did not have Python installed, here is a Perl version too:

open my $hw, "</dev/hwrng" and open my $rnd, "</dev/random" or die;
for (;;) {
    my $l = read $hw, my $d, 512;
    ioctl $rnd, 0x40085203, pack("ii", 4 * $l, $l) . $d or die;
    vec(my $w, fileno $rnd, 1) = 1;
    select undef, $w, undef, undef
}

This is probably what the rngd program (part of rng-tools) does (unverified), except that it uses tools (Python or Perl) that are already commonly available.

  • If you have no hardware random number generator, you could use /dev/urandom instead of /dev/hwrng if you absolutely do not care about insecure random values. – Lekensteyn Aug 9 '16 at 16:10
  • Hmm, I discovered that hwrng devices automatically generate entropy when needed, no additional rngd or script is needed. There is a bug though when the getrandom() syscall is used with hwrng on kernels older than 4.8-rc1 that results in blocking behavior. A workaround is to read() twice from /dev/random, see github.com/Lekensteyn/archdir/commit/… – Lekensteyn Aug 10 '16 at 22:15

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.