RFR 8024253: ThreadLocal random can use SecureRandom for the initial seed

Peter Levart peter.levart at gmail.com
Mon Sep 16 14:27:42 UTC 2013


On 09/16/2013 03:54 PM, Doug Lea wrote:
> On 09/16/2013 08:46 AM, Peter Levart wrote:
>
>> What worries me is that InetAddress.getLocalHost() involves name
>> service look-up. It depends on configuration, but on my computer, it 
>> takes about
>> 5s to evaluate the hostname -> IP mapping the first time the program 
>> is run.
>>
>> NetworkInterface also has one method called getHardwareAddress(). 
>> This might me
>> interesting too...
>
> Using NetworkInterface.getHardwareAddress() is a good idea; thanks!
> Using only one of them should suffice. And just giving up on
> SecurityException seems fine.
>
> Could you check that this performs reasonably on your
> unusually-configured machine?

I checked and it performs fast. It doesn't involve name service look-up.

>
>  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();
>             if (ifcs.hasMoreElements()) {
>                 byte[] bs = ifcs.nextElement().getHardwareAddress();
>                 if (bs != null) {
>                     for (int i = 0; i < 8 && i < bs.length; ++i)
>                         h = (h << 8) ^ bs[i];
>                 }
>             }
>         } catch (Exception ignore) {
>         }
>         return (mix64(h ^ System.currentTimeMillis()) ^
>                 mix64(System.nanoTime()));
>
>
>

But not every interface has hardware address (loopback interface for 
example) and the order of returned interfaces is not defined. Also with 
security manager installed (System.setSecurityManager(new 
RMISecurityManager()) and no extra policy, the above code always 
evaluates 'h' to 0. The following is more robust (I included only the 
2nd part after SecureRandom and added some prints to see what gets 
evaluated):

     public static long initialSeed() {
         long h = 0L;
         try {
             h = AccessController.doPrivileged(new 
PrivilegedExceptionAction<Long>() {
                 @Override
                 public Long run() throws Exception {
                     long h = 0L;
                     Enumeration<NetworkInterface> ifcs =
NetworkInterface.getNetworkInterfaces();
                     while (ifcs.hasMoreElements()) {
                         NetworkInterface ifc = ifcs.nextElement();
                         System.out.println(ifc);
                         byte[] bs = ifc.getHardwareAddress();
System.out.println(Arrays.toString(bs));
                         if (bs != null) {
                             for (int i = 0; i < 8 && i < bs.length; ++i)
                                 h = (h << 8) ^ bs[i];
                             break;
                         }
                     }
                     return h;
                 }
             });
         } catch (Exception ignore) {
         }
         return (
             mix64(h ^ System.currentTimeMillis()) ^
             mix64(System.nanoTime())
         );
     }


Regards, Peter




More information about the core-libs-dev mailing list