Hi,
SecureRandom hangs on the Linux Machine I am using (Linux 2.1 AS)
running Sun JDK 1.4.1_05.
Does anyone know if this is a known issue, how can it be resolved ?
Thanks in Advance,
Asif
Please find the thread dump below:
----------------------------------------------------------------------------
Full thread dump Java HotSpot(TM) Client VM (1.4.1_05-b01 mixed mode):
"Signal Dispatcher" daemon prio=1 tid=0x0x808cd40 nid=0x11c0 waiting
on condition [0..0]
"Finalizer" daemon prio=1 tid=0x0x8086720 nid=0x11bd in Object.wait()
[4c3d2000..4c3d28c0]
at java.lang.Object.wait(Native Method)
- waiting on <0x4426dcc8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
- locked <0x4426dcc8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=1 tid=0x0x8085ad8 nid=0x11bc in
Object.wait() [4c351000..4c3518c0]
at java.lang.Object.wait(Native Method)
- waiting on <0x44260180> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:426)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:113)
- locked <0x44260180> (a java.lang.ref.Reference$Lock)
"main" prio=1 tid=0x0x8051bd8 nid=0x11b9 runnable [bffe9000..bffe99a0]
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:191)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:220)
at java.io.BufferedInputStream.read(BufferedInputStream.java:277)
- locked <0x44240ae0> (a java.io.BufferedInputStream)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:222)
at java.io.BufferedInputStream.read(BufferedInputStream.java:277)
- locked <0x44240900> (a java.io.BufferedInputStream)
at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedByte(SeedGenerator.java:467)
at sun.security.provider.SeedGenerator.getSeedBytes(SeedGenerator.java:137)
at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:132)
at sun.security.provider.SecureRandom.engineGenerateSeed(SecureRandom.java:112)
at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:169)
- locked <0x4423e298> (a sun.security.provider.SecureRandom)
at java.security.SecureRandom.nextBytes(SecureRandom.java:381)
- locked <0x44261f08> (a java.security.SecureRandom)
at java.security.SecureRandom.next(SecureRandom.java:403)
at java.util.Random.nextInt(Random.java:191)
at GenerateId.main(GenerateId.java:17)
"VM Thread" prio=1 tid=0x0x8082898 nid=0x11bb runnable
"VM Periodic Task Thread" prio=1 tid=0x0x808b888 nid=0x11be waiting on
condition
"Suspend Checker Thread" prio=1 tid=0x0x808c2d8 nid=0x11bf runnable
--------------------------------------------------------------------------------
Test Client:
----------------------------------------------------------------------------
import java.security.SecureRandom;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class GenerateId {
public static void main (String[] arguments) throws Exception{
try {
//Initialize SecureRandom
//This is a lengthy operation, to be done only upon
//initialization of the application
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
//<--Code hangs here
//generate a random number
String randomNum = new Integer( prng.nextInt() ).toString();
//get its digest
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte[] result = sha.digest( randomNum.getBytes() );
System.out.println("Random number: " + randomNum);
System.out.println("Message digest: " + hexEncode(result) );
}
catch ( NoSuchAlgorithmException ex ) {
System.err.println(ex);
}
}
/**
* The byte[] returned by MessageDigest does not have a nice
* textual representation, so some form of encoding is usually
performed.
*
* This implementation follows the example of David Flanagan's book
* "Java In A Nutshell", and converts a byte array into a String
* of hex characters.
*
* Another popular alternative is to use a "Base64" encoding.
*/
static private String hexEncode( byte[] aInput){
StringBuffer result = new StringBuffer();
char[] digits = {'0', '1', '2', '3',
'4','5','6','7','8','9','a','b','c','d','e','f'};
for ( int idx = 0; idx < aInput.length; ++idx) {
byte b = aInput[idx];
result.append( digits[ (b&0xf0) >> 4 ] );
result.append( digits[ b&0x0f] );
}
return result.toString();
}
}
----------------------------------------------------------------------------
mbjones - 23 Jul 2004 21:31 GMT
I ran into the same problem with JDK 1.4.1_01 and JDK 1.4.2_05 running on
Redhat Linux using kernel 2.4.9.
After running the issue in the debugger for a while, I found it was always
hanging on a read in a native method while trying to generate a secure
seed in sun.security.provider.SeedGenerator which is called from
sun.security.provider.SecureRandom. I got this error whether I was calling
SecureRandom directly, or whether it was just used by the SSL libraries in
setting up a secure SSL connection with a server. See below for a stack
trace of where it was hanging.
The problem seemed to be that the security provider used /dev/random as an
entropy generator, and it somehow wasn't working. By editing the
$JAVA_HOME/jre/lib/security/java.security file and changing the property:
securerandom.source=file:/dev/random
to:
securerandom.source=file:/dev/urandom
the problem disappeared for me. So there seems to be some issue with the
OS access to /dev/random. Hope this helps with your issue.
Stack trace showing hang:
-------------------------------------
[1] java.io.FileInputStream.readBytes (native method)
[2] java.io.FileInputStream.read (FileInputStream.java:194)
[3] java.io.BufferedInputStream.read1 (BufferedInputStream.java:220)
[4] java.io.BufferedInputStream.read (BufferedInputStream.java:277)
[5] java.io.BufferedInputStream.fill (BufferedInputStream.java:183)
[6] java.io.BufferedInputStream.read1 (BufferedInputStream.java:222)
[7] java.io.BufferedInputStream.read (BufferedInputStream.java:277)
[8] sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedByte
(SeedGenerator.java:467)
[9] sun.security.provider.SeedGenerator.getSeedBytes
(SeedGenerator.java:137)
[10] sun.security.provider.SeedGenerator.generateSeed
(SeedGenerator.java:132)
[11] sun.security.provider.SecureRandom.engineGenerateSeed
(SecureRandom.java:112)
[12] sun.security.provider.SecureRandom.engineNextBytes
(SecureRandom.java:169)
[13] java.security.SecureRandom.nextBytes (SecureRandom.java:381)
[14] java.security.SecureRandom.next (SecureRandom.java:403)
[15] java.util.Random.nextInt (Random.java:191)
[16] GenerateId.main (GenerateId.java:21)
Richard Cook - 16 Nov 2004 23:37 GMT
What mbjones suggested will work, but the root of your problem is that dev/random has no entropy in its pool because it might not be properly configured.
You might want to try and configure dev/random on your linux box to uses additional interrupts to gather random data. If it's not configured to use the best interrupts, then you won't have enough entropy, and it will block until it has enough.
The latest version of FreeBSD (5.3) will probe itself for the best hardware interrupts for entropy, but other systems act differently, so you'll have to find out how to do this.
dev/urandom generates pseudo random numbers if there is not enough random data, which is less secure. So if security is imperative, you might want to fix the /dev/random configuration.
Rich