PHP中生成标准UUID(GUID)的方法
全局唯一标识 UUID (Universally unique identifier)
格式
格式为:00000000-0000-0000-0000-000000000000
总长度 36,由 32 个 16 进制字符和 4 个连字符组成。连字符仅用于增加可读性,实际的精度为一个 16 进制字符为 2^4=4bit
,32 个则为 32*4bit=128bit
版本区别
Version 1
- 48bit 主机的 Mac 地址
- 60bit 时间戳 (13-14bit 作为时间序列)
每个节点每秒钟可生成 1630 亿个,也就是说每毫秒 163 个
Version 2
- 48bit 主机的 Mac 地址
- 40bit 域名/ID
- 28bit 时间戳(6bit 作为时间序列)
允许一个节点存在 1 万亿个 域名/ID 对象,每个对象每 7 秒产生一个 UUID
Version 3 和 Version 5
将值与指定的命名空间拼接后,做 hash 运算,再做一些额外的固定变换得到最终的 UUID
V5 区别于 V3 是使用了更不容易碰撞的 hash 算法,前者 sha1,后者 md5。
注意值不变的情况下生成的 UUID 相同
Version 4
- 6bit 标记版本
- 122bit 随机数
每秒生成 10 亿个,大约需要 85 年才有重复的可能,所以在正常应用情形下这种碰撞概率可以忽略
版本选择
- V4 - 首选
- V1 - 如果需要反向解析主机 Mac 地址
- V5 - 如果需要根据特定的值生成,而且在值不变的情况下生成的 UUID 不变。
可用于加密用户密码,比如我的密码是 123456,sha1 固定为7c4a8d09ca3762af61e59520943dc26494f8941b
,所以一旦数据库数据泄露,很容易枚举出简单的密码原文。但使用 v5 算法后加入了特定的 namespace,会得到完全不同,切不具备普遍性的 UUID 串,这样就很难破解出密码原文了。 - V3 - 不推荐,用 V5 替代
- V2 - 一般不会用到
生成v4的代码
Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B.
function guid()
{
if (function_exists('com_create_guid') === true)
{
return trim(com_create_guid(), '{}');
}
return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}
or
public static function UUIDv4() {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
// 16 bits for "time_mid"
mt_rand(0, 0xffff),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand(0, 0x0fff) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand(0, 0x3fff) | 0x8000,
// 48 bits for "node"
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
参考代码: https://www.php.net/manual/en/function.uniqid.php#94959
本文最后更新时间:2020年9月8日