# HG changeset patch # User psandoz # Date 1379700426 25200 # Node ID 564bad4af0a8559ccdd9210bf41d1ab97e9702f6 # Parent e360435c2d8ede8a0c4a20de319dde59982e6c45 8024253: ThreadLocal random can use SecureRandom for the initial seed Reviewed-by: psandoz, chegar, alanb Contributed-by: Doug Lea , Peter Levart , Guy Steele diff -r e360435c2d8e -r 564bad4af0a8 jdk/src/share/classes/java/util/SplittableRandom.java --- a/jdk/src/share/classes/java/util/SplittableRandom.java Fri Sep 20 16:40:32 2013 +0200 +++ b/jdk/src/share/classes/java/util/SplittableRandom.java Fri Sep 20 11:07:06 2013 -0700 @@ -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 @@ s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); return s; } - int hh = 0; // hashed host address + long h = 0L; try { - hh = InetAddress.getLocalHost().hashCode(); + Enumeration 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())); } diff -r e360435c2d8e -r 564bad4af0a8 jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java --- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Sep 20 16:40:32 2013 +0200 +++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Sep 20 11:07:06 2013 -0700 @@ -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 @@ * *

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 @@ /** * 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 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 diff -r e360435c2d8e -r 564bad4af0a8 jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java --- a/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java Fri Sep 20 16:40:32 2013 +0200 +++ b/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java Fri Sep 20 11:07:06 2013 -0700 @@ -33,7 +33,9 @@ /** * @test + * @bug 8024253 * @run testng ThreadLocalRandomTest + * @run testng/othervm -Djava.util.secureRandomSeed=true ThreadLocalRandomTest * @summary test methods on ThreadLocalRandom */ @Test