UUID 与随机字符串生成器

全球通用工具

这个页面用来生成标识符:version 4 UUID(122 个随机位,不携带任何信息)、version 7 UUID(前面是毫秒时间戳,所以会按创建时间排序),以及从你选择的字母表里抽出的随机字符串。所有值都在浏览器里、由操作系统自带的随机源生成,不会向服务器请求任何东西,也不会留下日志。

version 4 是随机的,不携带信息;version 7 以时间开头,所以值可排序;最后一个模式用来读取已有 UUID。

500 个一批只需几毫秒,正好适合种子文件。

留空则使用 “uuids.txt”;其他模式下分别是 “random-strings.txt” 和 “uuid-report.txt”。

边输入边更新。所有计算都在你的浏览器里完成,数据不会离开本机。

随机 UUID,version 4

5 个值

每个值携带 122 个随机位,不包含关于这台设备、这个浏览器或时间的信息。当标识符不该透露任何东西时,就该用这个版本。

版本
4
随机位
122
字符数
36
大小
16 字节

你的 UUID

b7c6d9b2-976e-467d-9dc9-eb89cd08c9b5
29541230-197c-40a9-9d2e-20296b789970
90fb484d-0623-48b6-b7a5-db1bfedb0f7b
e16580cf-e28f-4f3e-aaeb-9dca5d256fcd
89443157-a30f-489e-b941-59379f8ba7b5

每行一个。可以整批复制,也可以下载成 .txt 文件 —— 无论哪种方式,它们都是在这个标签页里生成的。

这些数字没有说明的事

  • 122 位就是 128 位减去规范用于版本和变体的六位。两个值碰撞的概率,大约和猜中其中一个值差不多:要生成约 2.3 × 10^18 个 UUID,碰撞才会变得有一半可能。
  • version 4 的值不可排序。放进数据库后,它们会随机落在索引各处,规模上来后这是实打实的代价 —— version 7 正是为此而来,这个页面两个版本都能生成,差别可以直接看到。
  • UUID 是好的标识符,却是糟糕的秘密。122 位确实难以猜中,但这些值会自然而然地进入数据库行、请求日志和分析系统,所以任何需要保密的东西,都需要一个有生命周期的密钥,而不是一个标识符。
在当前浏览器标签页里、由操作系统自带的随机源生成。没有向服务器请求任何值,也没有向任何地方发送值。

它也支持反方向。把你已有的 UUID 粘进来——每行一个,各种常见写法都行——每个值都会被读回它本来的信息:版本、变体;对基于时间的版本,还能读出它指向的确切时刻,以及 version 1 会泄露的机器地址指纹。

关于这个工具

这个页面产出的是不该碰撞的标识符:由 122 个随机位构成的 version 4 UUID,前面带毫秒时间戳、因而按创建时间排序的 version 7 UUID,以及从自选字母表生成的普通随机字符串。它也能读回已有 UUID,报告版本、变体与时间。

格式来自 RFC 4122 及其后继 RFC 9562,页面遵循这两份规范,而不是自己发明一种形状。随机性取自浏览器自带的密码学随机源,所以无法从上一个值推测下一个值。生成完全在标签页内完成:不会向服务器索取标识符,也不会记录任何值。

UUID 是一种格式,不是校验和,所以检查模式只报告一个值是什么,而不会声称它是真的。这里不提供 version 1,因为它的 node 字段曾经携带机器的 MAC 地址。要在机器之间无需协调就获得唯一性,这份拒绝本身就是可靠性论证的一部分。

它是怎么工作的

UUID 里到底装了什么

UUID 是 128 位,写成 32 个十六进制数字,形状是 8-4-4-4-12。其中有六位并不自由:四位存放版本号,两位存放变体,后者说明这个值属于哪一族 UUID。RFC 4122 变体是目前所有现代生成器都会写入的,它以比特 `10` 开头,所以第四组的第一个字符总是 8、9、a 或 b。

于是 version 4 UUID 里真正随机的是 122 位,而不是 128 位。这仍然是个巨大的数字:大约要生成 2.3 × 10^18 个值,碰撞概率才会接近一半,和猜中某一个特定值的难度在同一量级。version 4 被普遍采用的实际原因,不是概率完美,而是完全不需要协调:两台从不通信的机器不会撞号。

UUID 是格式,不是校验和。值内部没有任何东西能证明它曾被签发过,所以一个打错的数字只要恰好落在另一个合法值上,读起来就毫无异常。这就是这里的检查模式只报告“它是什么”、而拒绝声称“它是真的”的原因。

version 4 与 version 7,以及数据库里为什么要在意

version 4 是纯随机,连续生成的值彼此无关:放进数据库索引后会落在随机位置,拆开页面,让写入触碰远超必要的索引范围。规模小时没人察觉;到了几亿行,它决定的是插入追加在末尾,还是散落到整棵索引。

RFC 9562(2024)为此加入了 version 7:前 48 位是 Unix 毫秒时间戳,所以值按创建时间排序,插入会追加到索引末尾。代价是信息暴露——拿到值的人都知道这行是什么时候创建的——随机位也从 122 位降到 74 位。这个页面上两个版本只差一次点击,取舍可以直接对比,而不是停留在争论。

version 1 和 6 是更早的时间型组合,这里不生成。它们以 48 位 node 字段结尾,早期实现会填入网卡真实的 MAC 地址:这个值能查到厂商,也曾是机器稳定的指纹。网页没有理由读取 MAC 地址,所以这个页面不读。

随机性、字母表,以及你实际拿到多少位

这里的一切都来自 `crypto.getRandomValues`,它是平台的熵源,由操作系统播种,无法根据之前的输出预测。`Math.random()` 写起来更短,却是错误的工具:它是快速的统计型生成器,输出足够多时内部状态可以被还原;拿来生成颜色没问题,拿来生成 API 密钥不行。

对随机字符串来说,字母表就是全部决定,因为它决定了每个字符值多少位。十六进制每字符 4 位,base64url 每字符 6 位,字母加数字是 5.95 位。长度才是买安全性的东西,而且很便宜:32 个 base64url 字符就是 192 位,已经越过“猜测不再是最便宜攻击方式”的界线。去掉了形近字符的字母表,则用一点强度换取电话里念得清楚。

字符抽取是无偏的。常见捷径是取随机字节对字母表大小取模,只要字母表不能整除 256,靠前的字符就会稍微更容易出现——字母加数字时大约多 1.6%。这里改为丢弃会造成偏斜的字节并重新抽取,代价是每个字符串多消耗几个字节。

示例

示例使用页面自带的默认输入,只改设置;下面的结果与你在页面上看到的完全一致。

一批写给种子文件的 version 4 UUID

要生成什么: version 4 UUID,随机,不携带信息 · 生成数量: 5 个

随机 UUID,version 4

5 个值

每个值携带 122 个随机位,不包含关于这台设备、这个浏览器或时间的信息。当标识符不该透露任何东西时,就该用这个版本。

版本: 4 · 随机位: 122 · 字符数: 36 · 大小: 16 字节

五个随机 UUID,每行一个,可以直接粘进测试夹具或迁移脚本。每个值都携带 122 个随机位,对这个设备不透露任何信息。

version 7 UUID,让插入保持有序

要生成什么: version 7 UUID,以时间开头,因此可排序 · 生成数量: 5 个

按时间排序的 UUID,version 7

5 个值

每个值都以生成时的毫秒开头,所以列表本身已经按时间排好,插入会落在索引末尾,而不是散落到整棵索引。每个值里有 74 位是随机的。

版本: 7 · 随机位: 74 · 时间戳位: 48 · 大小: 16 字节(文本形式 36 个字符)

每个值都以生成时的毫秒时间开头,所以列表本身已经按时间排好。同一毫秒内生成的值按各自的随机位排序,这是该格式诚实的边界。

读取一组已经存在的 UUID

要生成什么: 检查已有的 UUID

已检查 8 行

7/8 是 UUID

1 行不是 UUID:报告会说明每一行哪里有问题。发现的版本:version 4、version 7、version 1、version 5、nil UUID。

读取行数: 8 · UUID: 7 · 非 UUID: 1 · 包含时刻: 2

每一行单独报告:版本、变体,以及时间型值所指向的时刻。version 1 的值还会显示它生成页面时使用的 node 字段;不是 UUID 的行会说明原因。

用 base64url 字母表生成的 32 字符令牌

要生成什么: 随机字符串,可选字母表与长度 · 生成数量: 3 个 · 每个字符串的字符数: 32 个字符 · 字符来源: Base64url(A-Z a-z 0-9 - _),每字符 6 位

来自Base64url的随机字符串

3 个字符串

每个 32 个字符,每个字符串有 192 位随机性:字符从 64 个符号的字母表中抽取,这个数字决定了字符串有多难猜。

长度: 32 个字符 · 字母表: 64 个字符 · 每个字符串的位数: 192 · 整批的位数: 576

每个字符串 192 位:字符从 64 个符号的字母表里抽取,每个正好值 6 位。多数会话令牌和 API 密钥都是这种形状。

常见问题

UUID 是随机的吗?

完全取决于版本,而版本就是第三组的第四个字符。version 4 是 122 个随机位;version 7 是毫秒时间戳加 74 个随机位;version 1 和 6 是时间戳、计数器加机器字段,完全没有随机性;version 3 和 5 是名称的哈希,知道名称的人可以完全预测。不看版本就信任一个标识符,正是许多人误以为它“天生随机”的原因。

两个 UUID 会碰撞吗?

version 4 的碰撞概率符合 122 个独立位的预期:每一对大约 2.3 × 10^18 分之一;按生日界估算,大约要生成 2^61 个值,碰撞才变得可能。这远远超出任何单一系统的生成量,所以没人需要协调 UUID:两台从不通信的机器不会产生同一个值。现实中的失败模式不是数学碰撞,而是随机源坏掉,那是另一个问题——也是这个页面从操作系统取值、而不用 `Math.random()` 的原因。

可以把 UUID 当作密码重置令牌或 API 密钥吗?

从技术上说,122 个随机位足够难以猜测,这不是弱点。问题在于 UUID 是标识符,所以会被记录:数据库行、请求日志、分析系统、错误报告和共享截图都会自然地带着它。出现在日志文件里的令牌,就是已经泄露的凭证。应该使用长度足够的随机字符串(这个页面也能生成),配上过期时间、单次使用和服务端记录,并让它远离会被记录进日志的 URL。

主键该用 version 4 还是 version 7?

如果规模上来后插入必须快,选 version 7:时间戳位于最高有效位,值按创建时间排序,新行会追加到索引末尾,而不是散落各处。如果不希望公开一行的创建时间,选 version 4。version 7 的代价有限,但值得说清楚:每个值有 48 位是时钟读数,拿到它的人都能换算回一个时刻。对多数表来说这不是秘密,对某些表则是。两个选项在这里只差一次点击。

为什么这个页面不生成 version 1 或 version 6 UUID?

因为 version 1 和 6 以 48 位 node 字段结尾,最初的实现会填入网卡的 MAC 地址:这个值能识别厂商,并且在很长时间里是单台机器的稳定指纹。浏览器页面没有理由读取 MAC 地址,而往这个字段里写随机值,只会得到一个“看起来像真的、实际却不是”的 UUID。version 7 用另一种方式解决了同一个问题——按时间排序,又不必借用硬件地址。

怎样生成 version 5 UUID?

取命名空间 UUID 的字节(RFC 9562 列出了 DNS、URL、OID 和 X.500 名称的标准命名空间),接上名称的字节,用 SHA-1 哈希,保留前 16 字节,然后把版本半字节设为 5,并设置变体位。这里不生成它,因为它并不随机——它的全部意义在于 `example.com` 永远得到同一个 UUID,这适合可重复的导入,却不适合任何需要保密的东西。算法很短,可以照规范实现;这个页面会很乐意把你算出的结果读回来,并告诉你它是 version 5。

这里生成的值会到你们的服务器吗?

不会。所有值都由你浏览器标签页里的 `crypto.getRandomValues` 生成,下载文件在本地构建,页面背后没有任何能够接收值的接口。静态 HTML 里的那批 UUID 是站点发布时生成一次的——那是在任何 JavaScript 运行之前你看到的内容,是真实示例而不是占位符。按下“重新生成”,页面上的每个值都会在你的设备上产生。

nil 和 max UUID 是什么?

RFC 9562 定义了两个特殊值:nil UUID 全为零,max UUID 全为一。两者都不是标识符。它们在查询和范围判断里有用:nil 表示“这里什么都没有”,max 表示范围上界,这样写 `between` 查询时不必知道表里的最大值。这里的检查模式能识别两者并明确说明,因为用全零做行键通常意味着缺陷,而不是有意为之。

资料来源与统计口径

  • 标识符遵循 RFC 9562:version 4 带 122 个随机位,version 7 把毫秒时间戳放在最前面,所以一批值自然按时间排序。
  • 随机数来自浏览器的加密随机源,而不是可预测的伪随机数;每个字符的抽取都没有偏差。
  • 值在你的设备上生成,不会上传;页面也不会读取设备指纹。

最近复核于 2026-09-16.

本页在您的浏览器本地运行,请保留原文件备份;不涉及财务建议。 阅读完整免责声明。