• 补充第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);
            }
        }
    }
    
  • 相关阅读:
    Vue
    Vue
    Vue
    Vue
    Vue
    kubernetes
    kubernetes
    kubernetes
    django源码bug解决方案
    UNI-APP 桌面LOGO角标设置(ios)
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/9575447.html
Copyright © 2020-2023  润新知