"/dev/random" hangs in java program when server is inactive

Solution Verified - Updated

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 urandom instead:

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

    Note that you must not specify file:/dev/urandom but file:/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/urandom are sufficient. Applications should be written to use /dev/urandom for 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/urandom in preference. Sun/Orcale's JVM and OpenJDK can be modified by the property securerandom.source in $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 the securerandom.strongAlgorithms security property instead of the base java.security.egd file. In that case, the securerandom.strongAlgorithms property needs to be adjusted for such code as exemplified in JSF application start up hangs on EAP 7.4.15+

Root Cause

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"); 
            } 
          }
    
Components
Category

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.