"/dev/random" hangs in java program when server is inactive
Environment
- Red Hat Enterprise Linux 5 - All architectures
- Red Hat Enterprise Linux 6 - All architectures
- Java application
- JBoss Enterprise Application Platform (EAP)
- Tomcat
Issue
-
Reading "
/dev/random" hangs in java program -
entropy is too low to generate enough random numbers
-
Java program hangs as it's waiting on a thread that's continuously in this state trying to generate random numbers:
"main" prio=10 tid=0x00002aab580e2000 nid=0x6c98 runnable [0x000000004044f000] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:199) at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:185) at sun.security.provider.NativePRNG$RandomIO.implGenerateSeed(NativePRNG.java:202) - locked <0x00002aaad23739a0> (a java.lang.Object) at sun.security.provider.NativePRNG$RandomIO.access$300(NativePRNG.java:108) at sun.security.provider.NativePRNG.engineGenerateSeed(NativePRNG.java:102) at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
Resolution
One can use a hardware random number generator or rngd to gather more system entropy, as described on How to increase the entropy pool without using a keyboard or mouse?
The default "/dev/random" generates random numbers based on noise or entropy on the system; the higher the noise the faster the output. If there is no noise this tool won't return any data. We have two device files that we use for random number generation: "/dev/random" (blocking read) and "/dev/urandom" (unblocking read). The difference of these devices are "/dev/random" device will only return bytes within the estimated number of bits of noise in the entropy pool but /dev/urandom device will return as many bytes as are requested immediately. "/dev/random" is used when there is a high quality randomness is required. So if the application wants to generate random bits when the system is idle then suggest to use "/dev/urandom" instead of "/dev/random".
-
Launch the java application with the following option to run with
urandominstead:-Djava.security.egd=file:/dev/./urandomNote that you must not specify
file:/dev/urandombutfile:/dev/./urandom. Please refer to this article for details. -
For additional details refer to the man page
man 4 random -
The highest quality random numbers do need to be used for long-term (months to years) keys but, if a session key for JDBC is the primary use of the entropy data, it does not need to be used for session keys which are relatively short-lived. For these, the numbers produced by
/dev/urandomare sufficient. Applications should be written to use/dev/urandomfor session keys in preference to/dev/random. -
If the application uses a Java Virtual Machine (JVM) facility which passes requests for random numbers direct to the operating system, the JVM configuration may be changed to use
/dev/urandomin preference. Sun/Orcale's JVM and OpenJDK can be modified by the propertysecurerandom.sourcein$JAVA_HOME/jre/lib/security/java.security. Other JVMs may differ. Note that this should not be done if long-term keys are generated from the resulting data.Also, the Java Virtual Machine (JVM) seeds some of its internal generators (typically,
SecureRandom) from/dev/random, which is excessive for most purposes. Fortunately these should not be used frequently in general. However it may be an issue if the java application are being started with high frequency, or the application destroys their initial configuration as part of the setup/teardown.The configuration change above will modify the behavior.
-
Note that application code may fetch its random instance with
SecureRandom.getInstanceStrong(), which forces the selection of the random source to follow thesecurerandom.strongAlgorithmssecurity property instead of the basejava.security.egdfile. In that case, thesecurerandom.strongAlgorithmsproperty needs to be adjusted for such code as exemplified in JSF application start up hangs on EAP 7.4.15+
Root Cause
-
Java program was hung as it was waiting on "
/dev/random" and there was not enough entropy for "/dev/random" to generate output as the system was in idle state. -
Sun (now oracle) have documented this issue in their Content from bugs.sun.com is not included.issue tracker
Diagnostic Steps
-
Sample java program that can be used to test this:
import java.security.SecureRandom; class JRand { public static void main(String args[]) throws Exception { System.out.println("Begin Test #1 with SecureRandom"); System.out.println(" Result#1: " + SecureRandom.getInstance("SHA1PRNG").nextLong()); System.out.println("End Test 1"); System.out.println("Exiting Program"); } }
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.