Entropy in the Cloud

Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin.

-John Von Neumann

Good sources of random bits are hard to come by, particularly in the cloud. Pseudo-random generators (PRG), particularly cryptographically secure ones are something of a dark art. All of them depend upon the quality (or entropy) of the random input. We spend most of our time trying to make computers behave deterministically, only to ask them for “truly random” bits! The typical pseudo-random generator implementation “harvests” random bits from peripheral devices, interrupts, hardware clocks, and even special purpose devices. RFC 4086 provides a good practical starting point on the subject.

Under Linux, the kernel maintains an “entropy pool” that is the source of random bits for the kernel and user applications. The kernel keeps an estimate of the number of random bits in the entropy pool. The kernel’s estimate can be read with:

cat /proc/sys/kernel/random/entropy_avail

If an application reads from /dev/random, it will only be able to read as many bits as the kernel estimates are available. If, on the other hand, it reads from /dev/urandom, it will be given pseudo-random bits generated by a PRG. On a workstation, one can run a packages such as randomsound to collect random bits from external events and add entropy to the pool. In the absence of appropriate hardware, as is often the case on headless servers and usually the case for virtual machines, collecting “truly random” bits is harder.

The trouble is that in a virtualized environment, many of the common sources used by pseudo-random number generators are unavailable or ineffective. Virtualized hardware events in one VM are correlated with those in other VMs on the same machine and network traffic may be manipulated by an adversary. Practical cryptographically secure PRGs for the cloud are an open and challenging problem.

Many applications use /dev/random by default and therefore deplete the already small entropy pool. For security sensitive (i.e. cryptographic) applications, this may be necessary. For many others, it is not and /dev/urandom would be perfectly sufficient. A common example are internally-facing services running in a JVM. In general, the JVM must use /dev/random since a Java program may need cryptographic services. If the entropy pool is low, the JVM may take several tens of seconds to boot while it tries to seed its internal PRG. Particularly during development and testing it is perfectly acceptable to use /dev/urandom. The magical incantation to boot the JVM with /dev/urandom is:

java '-Djava.security.egd=file:/dev/./urandom'

Note the spelling of /dev/urandom: it is necessary in Java 5 and later (really!).

Post a Comment