On 09/16/2013 02:11 PM, Guy Steele wrote:

Okay, as long as we're obsessing: the code defends against the hardware
address being longer than 8 bytes.

This was to protect ourselves from the impact of this code being used in some
alternative universe in which hardware addresses are not always 48bits.
But you are right that we could do a little better.

So how about this code?
...
                           h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];

On first glance the sign extension of byte to long conversion
makes this suspicious, but I see that it cannot hurt.
So, sure; thanks.

Here's the full current version, including another minor tweak.
(Paul: I'm committing to our CVS.)

    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()));
    }

Reply via email to