Hi Brad

Is this the same as your Non-blocking SecureRandom? They have a webrev at

   http://cr.openjdk.java.net/~plevart/jdk9-dev/SystemRandom/webrev.01/

Thanks
Max


> Begin forwarded message:
> 
> Date: December 3, 2014 at 00:42:41 GMT+8
> From: Peter Levart <peter.lev...@gmail.com>
> To: Paul Sandoz <paul.san...@oracle.com>, core-libs-dev Libs 
> <core-libs-...@openjdk.java.net>
> Subject: Re: RFR 8066397 Remove network-related seed initialization code in 
> ThreadLocal/SplittableRandom
> 
> On 12/02/2014 11:02 AM, Paul Sandoz wrote:
>> Hi,
>> 
>> Please find below a patch to remove the networking code computing a seed in 
>> ThreadLocal/SplittableRandom.
>> 
>> We thought it a good idea at the time :-) but subsequently on certain 
>> platforms this results in very high initalization costs that can propagate 
>> to other classes such as ConcurrentSkipList*.
>> 
>> The short-term solution is to remove this code and fallback just using 
>> current system time. This needs to be back-ported to 8u40.
>> 
>> A longer term solution is to provide a simple public API to get access to 
>> some seed bytes that is optimal for the underlying platform, for example, 
>> based on Peter's investigations. For linux /dev/urandom is sufficient as a 
>> source of bytes. The main problem seems to be Windows. It would also be nice 
>> to back-port to say 8u60 using a private API and update TLR/SR.
> 
> Hi,
> 
> Here's a proof of concept for an API that just delegates to system-provided 
> "cryptographically secure" (as declared by the system(s)) pseudo random 
> number generator:
> 
> http://cr.openjdk.java.net/~plevart/jdk9-dev/SystemRandom/webrev.01/
> 
> On UNIX-es this uses /dev/urandom (which is non-blocking and uses system 
> entropy at least for it's seed):
> 
> http://en.wikipedia.org/?title=/dev/random
> 
> On Windows it uses MS Crypto API's function CryptGenRandom (the JNI code is 
> ripped from the sun.security.provider.NativeSeedGenerator), which also seeds 
> from various system sources of entropy:
> 
> http://en.wikipedia.org/wiki/CryptGenRandom
> 
> http://msdn.microsoft.com/en-us/library/windows/desktop/aa379942%28v=vs.85%29.aspx
> 
> The initialization overhead is low on UNIX (the enclosed test run on 64 bit 
> Fedora 20, i7 PC):
> 
> SystemRandomTest... (8 bytes / invocation)
> 1st invocation: 112315 ns, result: [25, 61, -12, -106, 75, -7, -73, -55]
> Following 1000000 invocations: 0.636644474 s, (636 ns/invocation)
> 
> The same test run on 32 bit Windows 7 (as VirtualBox guest on the same 
> machine):
> 
> SystemRandomTest... (8 bytes / invocation)
> 1st invocation: 4880788 ns, result: [-32, 53, -31, 62, 51, 83, 9, -5]
> Following 1000000 invocations: 1.761087512 s, (1761 ns/invocation)
> 
> I think the initialization on Windows has an initial latency of approx 5ms 
> because it has to initialize the whole MS Crypto API with it's providers. But 
> CryptGenRandom, which is part of this API, actually delegates it's work to 
> RtlGenRandom function:
> 
> http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694%28v=vs.85%29.aspx
> 
> ...which might have lower initialization costs. Unfortunately, the wording in 
> the Microsoft document states that it might be removed in the future. Perhaps 
> we could try to use it and fallback to CryptGenRandom if it is not 
> available...
> 
> 
> Regards, Peter
> 
> 
>> 
>> Paul.
>> 
>> [1] https://bugs.openjdk.java.net/browse/JDK-8060435
>> 
>> diff -r 1b599b4755bd 
>> src/java.base/share/classes/java/util/SplittableRandom.java
>> --- a/src/java.base/share/classes/java/util/SplittableRandom.java    Mon Dec 
>> 01 17:59:39 2014 -0800
>> +++ b/src/java.base/share/classes/java/util/SplittableRandom.java    Tue Dec 
>> 02 10:53:47 2014 +0100
>> @@ -237,34 +237,7 @@
>>                  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()) ^
>> +        return (mix64(System.currentTimeMillis()) ^
>>                  mix64(System.nanoTime()));
>>      }
>>  diff -r 1b599b4755bd 
>> src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
>> --- 
>> a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java    
>>     Mon Dec 01 17:59:39 2014 -0800
>> +++ 
>> b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java    
>>     Tue Dec 02 10:53:47 2014 +0100
>> @@ -147,34 +147,7 @@
>>                  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()) ^
>> +        return (mix64(System.currentTimeMillis()) ^
>>                  mix64(System.nanoTime()));
>>      }

Reply via email to