8024253: ThreadLocal random can use SecureRandom for the initial seed
Co-authored-by: Peter Levart <peter.levart@gmail.com> Co-authored-by: Guy Steele <guy.steele@oracle.com> Reviewed-by: psandoz, chegar, alanb
This commit is contained in:
parent
fdef74ade2
commit
851fd0447e
@ -25,8 +25,7 @@
|
||||
|
||||
package java.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
@ -242,12 +241,34 @@ public final class SplittableRandom {
|
||||
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
|
||||
return s;
|
||||
}
|
||||
int hh = 0; // hashed host address
|
||||
long h = 0L;
|
||||
try {
|
||||
hh = InetAddress.getLocalHost().hashCode();
|
||||
Enumeration<NetworkInterface> ifcs =
|
||||
NetworkInterface.getNetworkInterfaces();
|
||||
boolean retry = false; // retry once if getHardwareAddress is null
|
||||
while (ifcs.hasMoreElements()) {
|
||||
NetworkInterface ifc = ifcs.nextElement();
|
||||
if (!ifc.isVirtual()) { // skip fake addresses
|
||||
byte[] bs = ifc.getHardwareAddress();
|
||||
if (bs != null) {
|
||||
int n = bs.length;
|
||||
int m = Math.min(n >>> 1, 4);
|
||||
for (int i = 0; i < m; ++i)
|
||||
h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
|
||||
if (m < 4)
|
||||
h = (h << 8) ^ bs[n-1-m];
|
||||
h = mix64(h);
|
||||
break;
|
||||
}
|
||||
else if (!retry)
|
||||
retry = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return (mix64((((long)hh) << 32) ^ System.currentTimeMillis()) ^
|
||||
return (h ^ mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.io.ObjectStreamField;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Random;
|
||||
import java.util.Spliterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -71,7 +73,10 @@ import java.util.stream.StreamSupport;
|
||||
*
|
||||
* <p>Instances of {@code ThreadLocalRandom} are not cryptographically
|
||||
* secure. Consider instead using {@link java.security.SecureRandom}
|
||||
* in security-sensitive applications.
|
||||
* in security-sensitive applications. Additionally,
|
||||
* default-constructed instances do not use a cryptographically random
|
||||
* seed unless the {@linkplain System#getProperty system property}
|
||||
* {@code java.util.secureRandomSeed} is set to {@code true}.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
@ -129,9 +134,49 @@ public class ThreadLocalRandom extends Random {
|
||||
/**
|
||||
* The next seed for default constructors.
|
||||
*/
|
||||
private static final AtomicLong seeder =
|
||||
new AtomicLong(mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
private static final AtomicLong seeder = new AtomicLong(initialSeed());
|
||||
|
||||
private static long initialSeed() {
|
||||
String pp = java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction(
|
||||
"java.util.secureRandomSeed"));
|
||||
if (pp != null && pp.equalsIgnoreCase("true")) {
|
||||
byte[] seedBytes = java.security.SecureRandom.getSeed(8);
|
||||
long s = (long)(seedBytes[0]) & 0xffL;
|
||||
for (int i = 1; i < 8; ++i)
|
||||
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
|
||||
return s;
|
||||
}
|
||||
long h = 0L;
|
||||
try {
|
||||
Enumeration<NetworkInterface> ifcs =
|
||||
NetworkInterface.getNetworkInterfaces();
|
||||
boolean retry = false; // retry once if getHardwareAddress is null
|
||||
while (ifcs.hasMoreElements()) {
|
||||
NetworkInterface ifc = ifcs.nextElement();
|
||||
if (!ifc.isVirtual()) { // skip fake addresses
|
||||
byte[] bs = ifc.getHardwareAddress();
|
||||
if (bs != null) {
|
||||
int n = bs.length;
|
||||
int m = Math.min(n >>> 1, 4);
|
||||
for (int i = 0; i < m; ++i)
|
||||
h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
|
||||
if (m < 4)
|
||||
h = (h << 8) ^ bs[n-1-m];
|
||||
h = mix64(h);
|
||||
break;
|
||||
}
|
||||
else if (!retry)
|
||||
retry = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return (h ^ mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The seed increment
|
||||
|
@ -33,7 +33,9 @@ import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024253
|
||||
* @run testng ThreadLocalRandomTest
|
||||
* @run testng/othervm -Djava.util.secureRandomSeed=true ThreadLocalRandomTest
|
||||
* @summary test methods on ThreadLocalRandom
|
||||
*/
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user