简体中文

开发者工具 · UUID 生成器

v4 UUID 有多少个随机位? 122,不是 128

· 工作原理

uuid 密码学 浏览器 API

一个 128 位字段,突出显示 6 固定位(版本和变体)并显示 122 随机位,说明了为什么根据 122 位计算冲突概率
原始 ToolAcre 矢量图

随机 UUID 中的 6 个 128 位由标准固定,留下 122 用于随机性。这篇文章展示了如何诚实地估计碰撞几率,以及为什么真正的碰撞来自损坏的发电机,而不是来自数学。

建筑师的问题:我们会得到复制品吗? — 担忧从何而来以及为什么答案取决于生成器

架构师问:如果我们在十年内每天生成 10 万个 UUID,我们还会得到副本吗?诚实的答案是:如果生成器在密码学上是安全的,那么几乎肯定不会;如果发电机坏了,几乎可以肯定是的。 RFC 9562 数学是合理的:具有 122 随机位的 v4 UUID 的冲突概率大约为 n² / 2 的 123 次方,其中 n 是生成的标识符的数量。对于大多数实际系统,这种概率可以忽略不计。问题是这个公式假设每一位都是真正随机的。如果生成器泄漏或重复或可预见地播种,则公式是错误的,并且重复将不可避免。 128 位布局包括四个版本位(0100 对于 v4)和两个变体位(10 对于 RFC 9562),它们是由标准固定和设置的。

表示哪六个位 - 四个版本位和两个变体位,以及为什么它们是设置的而不是随机的

留下 122 位用于随机性。该公式有时被称为 2 到 122 随机位,产生唯一的值。使用生日悖论近似,n 个随机生成的值之间至少发生一次冲突的概率大约为 n² / 2 的 123 次。对于 n = 1 百万,这是 (10^6)² / 2^123 = 10^12 / 9。 3 × 10^36,大约是 10^-25。对于 n = 10 十亿,仍然约为 10^-16。这些并不是“实际上为零”;他们是“你永远不会观察到这一点。”生日近似值给出了计算风险的具体方法:计算你计划生成的 UUID,计算该数字的平方,除以 2 的 123 次方。如果生成器是浏览器的 crypto.getRandomValues,则每一位都由操作系统熵支持。如果是数学的话。

简单来说,生日近似值 — n 个标识符之间至少发生一次冲突的概率大约为 n 平方除以 2 得到 123

对于由不合适或重复状态生成器生成的 UUID,数学模型会崩溃,因为其独立性假设是错误的。固定的测试种子、复制的夹具或过程快照可以重播值,即使文本仍然带有版本 4 半字节。这些是实现缺陷,而不是 122 字段计算错误的证据。另一个常见的来源是将相同的文字标识符复制到多个装置中,然后合并它们的数据。调查重复项时,请保留生成器、种子策略、进程生命周期和导入历史记录。不要从一个重复值跳到声称独立 CSPRNG 输出耗尽了 UUID 空间。

工作示例 - 将规定的发电率和时间跨度插入近似值,显示每个步骤,以便您可以替换自己的数字

没有随机状态重新同步的进程分叉。使用 Math.random 而不是 crypto.getRandomValues 的错误。一个测试夹具,在多行中使用相同的 UUID 手工制作,并在生产中意外使用。旧版本的 UUID 库存在范围限制或状态错误。这些场景都不涉及生日近似数学;它们涉及实施失败或操作错误。诚实地计算系统的碰撞风险:计算 UUID 生成的速率(每秒、每天、每年),将其投影到系统运行的时间内,并将总数代入生日公式。如果您的系统在五年内每天生成 100,000 个 UUID(总计 182 万个),则冲突概率为 (1. 82 × 10^8)² / 2^123 ≈ 3。 3 × 10^-22,可以忽略不计。

重复项的实际来源 — Math.random 种子、克隆虚拟机、具有复制状态的分叉进程以及固定装置中的复制粘贴

如果一年每秒生成 10 百万(总计 315 万亿),则概率为 (3. 15 × 10^14)² / 2^123 ≈ 10^-10,仍然很小。这些估计假设每一位都是独立且随机的。 ToolAcre 生成器使用 crypto.getRandomValues,它为您提供 CSPRNG 支持的随机性;操作是您唯一需要信任的部分。切勿以碰撞概率为借口来跳过适当的授权检查。 UUID 不是密码,不是访问令牌,也不是秘密,即使它是 122 随机位。独特性就是好处;不可预测性是一个单独的(也是更重要的)属性,可以防止猜测。生日数学处理唯一性;它不涉及生命周期(这个 UUID 应该过期吗?)、保密性(在存储之前是否需要对其进行哈希处理?)或授权(拥有这个 UUID 是否能证明有关调用者的任何信息?)。 ToolAcre 生成器为您提供带有 122 随机位的 CSPRNG 支持的 UUID,这意味着数学的唯一性成立并且不可预测性是合理的。其他一切(令牌验证、到期、访问控制)都是您的应用程序的责任。概率公式假定每个生成的 UUID 与前几代是独立的。如果您的系统从单个 CSPRNG 实例生成标识符,并且每次调用都从操作系统中获取新的随机性,则独立性假设成立。如果您的系统使用缓存的 CSPRNG 状态或没有操作系统重新播种的种子生成器,则该假设将不成立。如果熵源耗尽(发生在某些嵌入式系统或负载下的虚拟机上),或者如果进程之间从未重置随机状态(进程分叉而不重新播种 CSPRNG),则冲突风险会急剧增加。

这不包括什么 - v1 和 v7 唯一性,它依赖于时间戳和时钟序列,而不仅仅是随机性

ToolAcre 回退为每个字节数组调用 crypto.getRandomValues,并且不保存应用程序级 PRNG 状态。平台内部仍然由浏览器和操作系统负责。模拟与真实发电机的碰撞显示了理论与实践之间的差异。从相同种子开始使用 Math.random 构建的生成器将产生相同的序列;您将在几百到几千个生成值内看到第一个 UUID 冲突,而不是像生日近似预测的那样在 2^60 值(2^122 的平方根)之后。仅当理论概率变得不可避免时(大约 2^60 UUID),使用来自健全操作系统熵的 crypto.getRandomValues 的生成器才会产生冲突,这个数字太大了,您永远无法达到它。使用弱或重用熵源的生成器(常见于实施不佳的 UUID 库或测试框架)将在两者之间产生冲突。

要点:相信数学,审核生成器 — ToolAcre 生成器使用浏览器的 CSPRNG,这是不能伪造的部分

批量测试可以捕获返回常量或重放明显序列的实现,但通过的样本无法证明未来的唯一性。无论重复的标识符会损坏数据,生产系统仍应强制执行唯一约束。导入值得特别注意,因为两个有效的源系统可能已经包含相同的文字标识符,并且可以跨环境复制装置。 ToolAcre 的测试检查一批 500 是否包含 500 不同值;这是对此实现的回归检查,而不是统计保证。如果出现重复项,请保留证据并检查生成、导入、固定装置和存储路径,然后再找出原因。