Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with a slow SecureRandom generator?

People also ask

Is SecureRandom truly random?

The basic and important difference between both is SecureRandom generate more non predictable random numbers as it implements Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) as compare to Random class which uses Linear Congruential Generator (LCG).

How does SecureRandom work?

A cryptographically secure number random generator, as you might use for generating encryption keys, works by gathering entropy - that is, unpredictable input - from a source which other people can't observe.

What is seed in SecureRandom?

The setSeed(long seed) method of java. security. SecureRandom class is used to reseeds this random object, using the eight bytes contained in the given long seed. The given seed supplements, rather than replaces, the existing seed.

What is Java security SecureRandom?

security. SecureRandom class: This class provides a cryptographically strong random number generator (RNG). A cryptographically strong random number minimally complies with the statistical random number generator tests specified in FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.


You should be able to select the faster-but-slightly-less-secure /dev/urandom on Linux using:

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

However, this doesn't work with Java 5 and later (Java Bug 6202721). The suggested work-around is to use:

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

(note the extra /./)


If you want true random data, then unfortunately you have to wait for it. This includes the seed for a SecureRandom PRNG. Uncommon Maths can't gather true random data any faster than SecureRandom, although it can connect to the internet to download seed data from a particular website. My guess is that this is unlikely to be faster than /dev/random where that's available.

If you want a PRNG, do something like this:

SecureRandom.getInstance("SHA1PRNG");

What strings are supported depends on the SecureRandom SPI provider, but you can enumerate them using Security.getProviders() and Provider.getService().

Sun is fond of SHA1PRNG, so it's widely available. It isn't especially fast as PRNGs go, but PRNGs will just be crunching numbers, not blocking for physical measurement of entropy.

The exception is that if you don't call setSeed() before getting data, then the PRNG will seed itself once the first time you call next() or nextBytes(). It will usually do this using a fairly small amount of true random data from the system. This call may block, but will make your source of random numbers far more secure than any variant of "hash the current time together with the PID, add 27, and hope for the best". If all you need is random numbers for a game, though, or if you want the stream to be repeatable in future using the same seed for testing purposes, an insecure seed is still useful.


On Linux, the default implementation for SecureRandom is NativePRNG (source code here), which tends to be very slow. On Windows, the default is SHA1PRNG, which as others pointed out you can also use on Linux if you specify it explicitly.

NativePRNG differs from SHA1PRNG and Uncommons Maths' AESCounterRNG in that it continuously receives entropy from the operating system (by reading from /dev/urandom). The other PRNGs do not acquire any additional entropy after seeding.

AESCounterRNG is about 10x faster than SHA1PRNG, which IIRC is itself two or three times faster than NativePRNG.

If you need a faster PRNG that acquires entropy after initialization, see if you can find a Java implementation of Fortuna. The core PRNG of a Fortuna implementation is identical to that used by AESCounterRNG, but there is also a sophisticated system of entropy pooling and automatic reseeding.


Many Linux distros (mostly Debian-based) configure OpenJDK to use /dev/random for entropy.

/dev/random is by definition slow (and can even block).

From here you have two options on how to unblock it:

  1. Improve entropy, or
  2. Reduce randomness requirements.

Option 1, Improve entropy

To get more entropy into /dev/random, try the haveged daemon. It's a daemon that continuously collects HAVEGE entropy, and works also in a virtualized environment because it doesn't require any special hardware, only the CPU itself and a clock.

On Ubuntu/Debian:

apt-get install haveged
update-rc.d haveged defaults
service haveged start

On RHEL/CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Option 2. Reduce randomness requirements

If for some reason the solution above doesn't help or you don't care about cryptographically strong randomness, you can switch to /dev/urandom instead, which is guaranteed not to block.

To do it globally, edit the file jre/lib/security/java.security in your default Java installation to use /dev/urandom (due to another bug it needs to be specified as /dev/./urandom).

Like this:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

Then you won't ever have to specify it on the command line.


Note: If you do cryptography, you need good entropy. Case in point - android PRNG issue reduced the security of Bitcoin wallets.