补充第11期作业:Long.fastUUID与UUID.toString之间的关系

一 UUID.toString方法与Long.fastUUID方法的关联

  • UUID类
public final class UUID implements java.io.Serializable, Comparable<UUID> {

	 public static UUID randomUUID() {
        SecureRandom ng = Holder.numberGenerator;

        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes); // 真正生成随机数的地方
        randomBytes[6]  &= 0x0f;  /* clear version        */
        randomBytes[6]  |= 0x40;  /* set to version 4     */
        randomBytes[8]  &= 0x3f;  /* clear variant        */
        randomBytes[8]  |= 0x80;  /* set to IETF variant  */
        return new UUID(randomBytes);
    }

    /*
     * The random number generator used by this class to create random
     * based UUIDs. In a holder class to defer initialization until needed.
     */
    private static class Holder {
        static final SecureRandom numberGenerator = new SecureRandom();
    }
    
    /*
     * The most significant 64 bits of this UUID.
     * @serial
     */
    private final long mostSigBits;

    /*
     * The least significant 64 bits of this UUID.
     * @serial
     */
    private final long leastSigBits;
    
    private UUID(byte[] data) {
        long msb = 0;
        long lsb = 0;
        assert data.length == 16 : "data must be 16 bytes in length";
        // long的64位:    8位    8位 8位 8位 8位 8位 8位 8位   8位
        // 简单说:msb = data[0]     ......      ......       data[7]
        for (int i=0; i<8; i++)
            msb = (msb << 8) | (data[i] & 0xff); 
        // long的64位:    8位    8位 8位 8位 8位 8位 8位 8位   8位
        // 简单说:lsb = data[8]     ......      ......       data[15]
        for (int i=8; i<16; i++)
            lsb = (lsb << 8) | (data[i] & 0xff);
        this.mostSigBits = msb;
        this.leastSigBits = lsb;
    }
    
    // SharedSecrets javaLangAccess变量什么时候设置进去?
    // 答案是System
    private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
    
    public String toString() {
        return jla.fastUUID(leastSigBits, mostSigBits);// 实际调用了Long.fastUUID方法
    }
}

public final class System {
	/**
     * Initialize the system class.  Called after thread initialization.
     */
    private static void initPhase1() {
    	// ...
        setJavaLangAccess();
        // ...
    }
    
    private static void setJavaLangAccess() {
        // Allow privileged classes outside of java.lang
        // 匿名内部类注册
        SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
		    // ......
            public String fastUUID(long lsb, long msb) {
                return Long.fastUUID(lsb, msb);
            }
        });
    }
}

public final class Long extends Number implements Comparable<Long> {
    
    // 其实就是提供UUID的toString方法.......
    static String fastUUID(long lsb, long msb) {
        if (COMPACT_STRINGS) {
            byte[] buf = new byte[36];
            formatUnsignedLong0(lsb,        4, buf, 24, 12);
            formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4);
            formatUnsignedLong0(msb,        4, buf, 14, 4);
            formatUnsignedLong0(msb >>> 16, 4, buf, 9,  4);
            formatUnsignedLong0(msb >>> 32, 4, buf, 0,  8);

            buf[23] = '-';
            buf[18] = '-';
            buf[13] = '-';
            buf[8]  = '-';

            return new String(buf, LATIN1);
        } else {
            byte[] buf = new byte[72];

            formatUnsignedLong0UTF16(lsb,        4, buf, 24, 12);
            formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4);
            formatUnsignedLong0UTF16(msb,        4, buf, 14, 4);
            formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9,  4);
            formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0,  8);

            StringUTF16.putChar(buf, 23, '-');
            StringUTF16.putChar(buf, 18, '-');
            StringUTF16.putChar(buf, 13, '-');
            StringUTF16.putChar(buf,  8, '-');

            return new String(buf, UTF16);
        }
    }
}
  • UUID的组成部分

参考:http://www.ietf.org/rfc/rfc4122.txt

UUID  = time-low "-" time-mid "-" time-high-and-version "-" clock-seq-and-reserved clock-seq-low "-" node
time-low               = 4hexOctet
time-mid               = 2hexOctet
time-high-and-version  = 2hexOctet
clock-seq-and-reserved = hexOctet
clock-seq-low          = hexOctet
node                   = 6hexOctet
hexOctet               = hexDigit hexDigit
hexDigit =
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
"a" / "b" / "c" / "d" / "e" / "f" /
"A" / "B" / "C" / "D" / "E" / "F"

二 Java加密体系结构(JCA)

参考:https://blog.csdn.net/u012741741/article/details/79209984

这篇译文很好,不过本文不是为了讲解加密体系,所以尽量只获取最少的额外知识点来完成UUID.randomUUID的剖析

1 介绍

  • JAVA平台强调安全性,包含内容很多如:语言安全,密码学,公钥基础设施,认证,安全通信和访问控制。
  • JCA是JAVA平台的一部分,提供一个“Provider”体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成管理和安全随机数生成等等。有了这些API,开发人员可以轻松将安全性集成到自己的应用中。
  • JCA设计原则:
    • 实现独立性:应用程序不需要自己实现安全性,它们可以从Java平台请求安全服务。
    • 实现互操作性:Provider不需要绑定到固定的应用中,应用也不需要绑定特定的Provider
    • 算法可拓展性: Java平台包含许多内置的Provider,这些Provider实现了当今广泛使用的一组基本的安全服务 。但也许有些应用希望集成新兴的算法

2 UUID中涉及JCA的类

  • SecureRandom:它是一个随机数生成器(RNG),同时是JCA中的其中一个引擎类。引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法或提供者。
  • SecureRandomSpi:该类定义了SecureRandom的服务提供者接口(SPI),意味着为SecureRandom提供具体实现的生成器需要实现该类的所有方法。
  • DRBG:它实现了"SecureRandom.DRBG"算法,是SecureRandom的其中一个随机数生成器实现。
  • Provider:该类表示Java安全API的“提供者”,其中某个具体提供者需要实现Java安全的部分或全部部分。
  • Sun:Sun的安全提供者,Provider的子类。
  • Provider.Service:Provider的内部类,封装SPI的具体实现类,通过Service能够找到具体的实现类

3 SecureRandom的具体实现类追寻

(1)找出Jdk中有许多Providers,许多官方的,或者第三方添加。如:Sun、SunJCE、JdkLDAP、XMLLDSig等

(2)顺序遍历Providers并解析Providers中提供的算法为Services,如:

  • SecureRandom.DRBG -> sun.security.provider.DRBG
  • MessageDigest.SHA -> sun.security.provider.SHA
  • Alg.Alias.KeyPairGenerator.1.2.8400.10040.4.1 -> DSA
  • Alg.Alias.CertificateFactory.X509 -> X.509
  • Provider.id info -> SUN(DSA key/parameter generation; DSA signing; SHA-1 , MD5...)
  • .....

(3)发现DRBG是SecureRandom的具体提供者

(4)根据DRBG的全类名创建对象并返回使用

4 通过代码跟踪看看

public class SecureRandom extends java.util.Random {
    
    public SecureRandom() {
        super(0);
        getDefaultPRNG(false, null);
        this.threadSafe = getThreadSafe();
   }
    
   private void getDefaultPRNG(boolean setSeed, byte[] seed) {
        String prng = getPrngAlgorithm(); // 返回"DRBG"
        if (prng == null) {
            prng = "SHA1PRNG";
            this.secureRandomSpi = new sun.security.provider.SecureRandom();
            this.provider = Providers.getSunProvider();
            if (setSeed) this.secureRandomSpi.engineSetSeed(seed);
        } else { 
            try {
                SecureRandom random = SecureRandom.getInstance(prng);
                this.secureRandomSpi = random.getSecureRandomSpi();
                this.provider = random.getProvider();
                if (setSeed) {
                    this.secureRandomSpi.engineSetSeed(seed);
                }
            } catch (NoSuchAlgorithmException nsae) {
                throw new RuntimeException(nsae);
            }
        }
        if (getClass() == SecureRandom.class) {
            this.algorithm = prng;
        }
    }
    
    private static String getPrngAlgorithm() {
        for (Provider p : Providers.getProviderList().providers()) {
            for (Service s : p.getServices()) {
                if (s.getType().equals("SecureRandom"))  return s.getAlgorithm();
            }
        }
        return null;
    }
    
   public static SecureRandom getInstance(String algorithm) throws NoSuchAlgorithmException {
        Instance instance = GetInstance.getInstance("SecureRandom",
                                                    SecureRandomSpi.class,
                                                    algorithm);
        return new SecureRandom((SecureRandomSpi)instance.impl,
                                instance.provider, algorithm);
    }
}

public class GetInstance {
	public static Instance getInstance(String type, Class<?> clazz,
            String algorithm) throws NoSuchAlgorithmException {
        ProviderList list = Providers.getProviderList();
        Service firstService = list.getService(type, algorithm);
        return getInstance(firstService, clazz);
    }
    
     public static Instance getInstance(Service s, Class<?> clazz)
            throws NoSuchAlgorithmException {
        Object instance = s.newInstance(null);
        return new Instance(s.getProvider(), instance);
    }
}

public class Provider{
    
    public class Service{
        public Object newInstance(Object constructorParameter)
                throws NoSuchAlgorithmException {
            Class<?> ctrParamClz;
            EngineDescription cap = knownEngines.get(type);
            if (cap == null) {
                ctrParamClz = constructorParameter == null?
                    null : constructorParameter.getClass();
            } else {
                ctrParamClz = cap.constructorParameterClassName == null?
                    null : Class.forName(cap.constructorParameterClassName);
            }
            return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
        }
        
        // 返回class sun.security.provider.DRBG
        // return the implementation Class object for this service
        private Class<?> getImplClass() throws NoSuchAlgorithmException {
            Reference<Class<?>> ref = classRef;
            Class<?> clazz = (ref == null) ? null : ref.get();
            ClassLoader cl = provider.getClass().getClassLoader();
            if (cl == null) {
                clazz = Class.forName(className);//className为sun.security.provider.DRBG
            } else {
                clazz = cl.loadClass(className);
            }
            classRef = new WeakReference<>(clazz);
            return clazz;
        }
    }
    
     private static Object newInstanceUtil(final Class<?> clazz,
        final Class<?> ctrParamClz, final Object ctorParamObj)
        throws Exception {
        if (ctrParamClz == null) {
            Constructor<?> con = clazz.getConstructor();
            // 最后就是构造器的newInstance
            return con.newInstance();
        } else {
            Constructor<?> con = clazz.getConstructor(ctrParamClz);
            return con.newInstance(ctorParamObj);
        }
    }
}
posted @ 2018-09-02 21:34  月下小魔王  阅读(1510)  评论(0编辑  收藏  举报