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

最新文章

  1. Win10 UWP 开发系列:使用SplitView实现汉堡菜单及页面内导航
  2. 【WPF系列】-TextBox常用知识点
  3. utf8转gbk,libcurl中文乱码处理
  4. tree命令的使用
  5. 深入理解javascript中执行环境(作用域)与作用域链
  6. [Json.net]快速入门
  7. ExtJS学习之路第六步:深入讨论组件Panel用法
  8. Android应用程序构成
  9. innerHTML与innerText的PK
  10. 清橙OJ 1082 查找第K小元素 -- 快速排序
  11. WCF学习笔记一(概述)
  12. [Head First Python]2. BIF(内置函数)
  13. [SQLXML]FOR XML语法导出XML的易错之处
  14. 【iOS】swift-获取webView的高度
  15. win10更改无线网卡的MAC地址
  16. JDK 1.8判断集合种的元素是否存在相同
  17. linux系统安全设置策略
  18. css动画特效
  19. WebService 的CXF框架 WS独立服务之HelloWorld
  20. Array数组集合的排序

热门文章

  1. Xshell查看日志
  2. kotlin之map委托
  3. JAVA 基础编程练习题18 【程序 18 乒乓球赛】
  4. nginx重新编译不停服
  5. springmvc+spring+mybatis 项目配置
  6. python进阶--多线程多进程
  7. 以rpm安装包的方式安装MySQL
  8. rabbitmq-BasicReject
  9. npm run build报错 No PostCSS Config found in
  10. 使用tensorflow训练SSD(一):相关环境的配置