FULL PRODUCT VERSION :
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux jb3 2.6.18-6-xen-vserver-amd64 #1 SMP Thu Dec 25 22:49:16 UTC 2008 x86_64 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
A DESCRIPTION OF THE PROBLEM :
I found that even when java.security has specified that the jvm should use /dev/urandom in stead of /dev/random, still any PKCS#12 Keystore store operation blocks on reading data from /dev/random.
[my java.security]
securerandom.source=file:/dev/urandom
This was causing real performance problems on production systems.
Why double/tripple checked java.security many times to rule out the problem of lack of entropy in /dev/random on a server with no keyboard, mouse and most data in memory (low hd activity).
But surprise... no matter what you set in java.security still it uses /dev/random.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
[example]
The following code shows the problem:
while (true)
{
KeyStore ks= KeyStore.getInstance("PKCS12");
ks.load(null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ks.store(out, key); // blocks !!
...
...
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
[expected behaviour]
Whenever java.security specified that /dev/urandom should be used, the jvm should obey that, and don't fallback to /dev/random.
ACTUAL -
The code somtimes blocks for many seconds in ks.store.
[java stacktrace when it blocks]
java.lang.Thread.State: RUNNABLE
[junit] at java.io.FileInputStream.readBytes(Native Method)
[junit] at java.io.FileInputStream.read(FileInputStream.java:199)
[junit] at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:185)
[junit] at sun.security.provider.NativePRNG$RandomIO.implGenerateSeed(NativePRNG.java:202)
[junit] - locked <0x00002aaadf6bdae0> (a java.lang.Object)
[junit] at sun.security.provider.NativePRNG$RandomIO.access$300(NativePRNG.java:108)
[junit] at sun.security.provider.NativePRNG.engineGenerateSeed(NativePRNG.java:102)
[junit] at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
[junit] at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.getSalt(PKCS12KeyStore.java:477)
[junit] at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.getAlgorithmParameters(PKCS12KeyStore.java:490)
[junit] at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.encryptContent(PKCS12KeyStore.java:1131)
[junit] at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.createEncryptedData(PKCS12KeyStore.java:1049)
[junit] at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineStore(PKCS12KeyStore.java:770)
[junit] - locked <0x00002aaadebad138> (a com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore)
[junit] at java.security.KeyStore.store(KeyStore.java:1117)
[junit] at com.vsecure.config.PKCS12Reader.ReadPKCS12file(PKCS12Reader.java:162)
[junit] at com.vsecure.config.PKCS12Reader.run(PKCS12Reader.java:70)
[strace]
stracing shows that ks.store() actually hangs in a read /dev/random
REPRODUCIBILITY :
This bug can be reproduced always.