Use SecureRandom.generateSeed() to generate ThreadLocalRandom's initialSeedUniquifier

Motivation:

Previously, we used SecureRandom.nextLong() to generate the initialSeedUniquifier.  This required more entrophy than necessary because it has to 1) generate the seed of SecureRandom first and then 2) generate a random long integer.  Instead, we can use generateSeed() to skip the step (2)

Modifications:

Use generateSeed() instead of nextLong()

Result:

ThreadLocalRandom requires less amount of entrphy to start up
This commit is contained in:
Trustin Lee 2014-03-21 13:43:15 +09:00
parent b5c97bcc82
commit 2215ed0a35

View File

@ -82,12 +82,12 @@ public class ThreadLocalRandom extends Random {
if (initialSeedUniquifier == 0) { if (initialSeedUniquifier == 0) {
// Try to generate a real random number from /dev/random. // Try to generate a real random number from /dev/random.
// Get from a different thread to avoid blocking indefinitely on a machine without much entrophy. // Get from a different thread to avoid blocking indefinitely on a machine without much entrophy.
final BlockingQueue<Long> queue = new LinkedBlockingQueue<Long>(); final BlockingQueue<byte[]> queue = new LinkedBlockingQueue<byte[]>();
Thread generatorThread = new Thread("initialSeedUniquifierGenerator") { Thread generatorThread = new Thread("initialSeedUniquifierGenerator") {
@Override @Override
public void run() { public void run() {
SecureRandom random = new SecureRandom(); // Get the real random seed from /dev/random SecureRandom random = new SecureRandom(); // Get the real random seed from /dev/random
queue.add(random.nextLong()); queue.add(random.generateSeed(8));
} }
}; };
generatorThread.start(); generatorThread.start();
@ -99,15 +99,23 @@ public class ThreadLocalRandom extends Random {
long waitTime = deadLine - System.nanoTime(); long waitTime = deadLine - System.nanoTime();
if (waitTime <= 0) { if (waitTime <= 0) {
logger.warn( logger.warn(
"Failed to get the secure random number from SecureRandom within {} seconds. " + "Failed to generate a seed from SecureRandom within {} seconds. " +
"Not enough entrophy?", timeoutSeconds); "Not enough entrophy?", timeoutSeconds);
break; break;
} }
try { try {
Long result = queue.poll(waitTime, TimeUnit.NANOSECONDS); byte[] seed = queue.poll(waitTime, TimeUnit.NANOSECONDS);
if (result != null) { if (seed != null) {
initialSeedUniquifier = result; initialSeedUniquifier =
((long) seed[0] & 0xff) << 56 |
((long) seed[1] & 0xff) << 48 |
((long) seed[2] & 0xff) << 40 |
((long) seed[3] & 0xff) << 32 |
((long) seed[4] & 0xff) << 24 |
((long) seed[5] & 0xff) << 16 |
((long) seed[6] & 0xff) << 8 |
(long) seed[7] & 0xff;
break; break;
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {