How to deal with a slow SecureRandom generator?
If you want a cryptographically strong random numbers in Java, you use SecureRandom
. Unfortunately, SecureRandom
can be very slow. If it uses /dev/random
on Linux, it can block waiting for sufficient entropy to build up. How do you avoid the performance penalty?
Has anyone used Uncommon Maths as a solution to this problem?
Can anybody confirm that this performance problem has been solved in JDK 6?
Solution 1:
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 /./
)
Solution 2:
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.