UUID v3生成器

Generate deterministic name-based UUID v3 using MD5

命名空间

6ba7b810-9dad-11d1-80b4-00c04fd430c8

名称

已生成的 UUID v3

输入名称并点击"生成"
相同的命名空间 + 名称始终生成相同的 UUID
Note:UUID v3 是使用 MD5 哈希的遗留格式。对于需要确定性 UUID 的新开发,优先选择 UUID v5(SHA-1)。对于通用唯一 ID,请使用 UUID v4

什么是 UUID v3?

UUID v3 是在 RFC 4122 中定义的基于名称的 UUID 版本。它不使用随机数据或时间戳,而是从两个输入中确定性地派生 UUID:一个命名空间 UUID 和一个名称字符串。命名空间 + 名称对使用 MD5 进行哈希,结果哈希被格式化为 UUID。

UUID v3 的关键属性是确定性:相同的命名空间和名称将始终在任何机器、任何时间产生相同的 UUID。这使它适合内容寻址——为由有意义名称标识的资源生成稳定标识符。

UUID v3 使用 MD5 作为其哈希函数。MD5 在安全目的上被认为是加密破解的,这就是为什么通常对新开发优先选择 UUID v5(使用 SHA-1)的原因。v3 和 v5 都不提供任何随机性——它们纯粹是确定性的。

标准命名空间

RFC 4122 定义了四个预分配的命名空间 UUID。使用标准命名空间确保互操作性——两个独立的实现将在同一命名空间内为同一名称生成相同的 UUID v3:

命名空间UUID用于
DNS6ba7b810-9dad-11d1-80b4-00c04fd430c8完全限定域名(例如 'example.com')
URL6ba7b811-9dad-11d1-80b4-00c04fd430c8URL 和 URI(例如 'https://example.com/resource')
OID6ba7b812-9dad-11d1-80b4-00c04fd430c8ISO 对象标识符(例如 '1.2.840.113556')
X.5006ba7b814-9dad-11d1-80b4-00c04fd430c8X.500 可分辨名称(例如 'cn=John,dc=example,dc=com')

你也可以使用任意 UUID 作为自定义命名空间——例如,你生成一次并作为常量嵌入应用程序的 UUID v4。这让你可以为自己的名称到 UUID 映射创建私有命名空间。

UUID v3 vs UUID v5

UUID v3 和 UUID v5 在结构上完全相同——两者都是确定性的、基于名称的 UUID。唯一的区别是哈希函数:

UUID v3
  • 使用 MD5 哈希
  • 128 位输出(UUID 大小)
  • 在 RFC 4122 中定义
  • MD5 在加密上已破解
  • 所有 UUID 库都支持
UUID v5
  • 使用 SHA-1 哈希
  • 160 位哈希截断为 128 位
  • 在 RFC 4122 中定义
  • SHA-1 在安全使用上已弃用,但比 MD5 更强
  • 所有 UUID 库都支持

对于所有新开发,优先选择 UUID v5 而非 UUID v3。SHA-1 哈希比 MD5 更强,性能差异可忽略不计。仅当你需要从已使用它的系统复现 UUID 时才使用 UUID v3。

何时使用 UUID v3

UUID v3(和 v5)适用于需要从有意义名称派生稳定、可复现标识符的场景——而非需要存储和查找的随机 ID:

URL 规范化
为任何 URL 生成确定性 UUID,用作数据库或缓存中的紧凑、固定长度键——无需存储映射表。
基于 DNS 的标识符
为主机名或域名分配稳定的 UUID,在部署和数据库之间保持一致。
内容寻址
为由规范名称标识的内容项创建可复现 ID——文章、产品或配置键。
幂等资源创建
为相同资源名称生成相同的 UUID,使重复创建尝试自然成为幂等的,无需查找。
测试夹具
在测试数据中生成稳定、可预测的 UUID,这样在测试重新运行时不需要更新测试断言。
跨系统去重
两个独立系统可以为相同名称派生相同的 UUID,而无需通信,从而在没有共享 ID 注册表的情况下实现去重。

理解确定性

UUID v3 的确定性既是其最大优势,也是其最重要的约束。给定任何命名空间 UUID 和任何名称字符串,输出 UUID 是完全固定的——不涉及随机性。这意味着:

示例(DNS 命名空间,名称 = 'example.com'):9073926b-929f-31c2-abc9-fad77ae3e8eb

始终产生:9073926b-929f-31c2-abc9-fad77ae3e8eb

如果攻击者知道命名空间并能猜测名称,他们可以提前计算 UUID。UUID v3 值不应用作不可预测的令牌、会话 ID 或机密。对于任何安全敏感的标识符,请使用 UUID v4。

代码示例

UUID v3 需要命名空间 UUID名称字符串。使用标准 uuid 包:

JavaScript / Node.js
// Browser / Node.js — UUID v3 without dependencies
function uuidV3(namespace, name) {
  // namespace must be a UUID string like '6ba7b810-9dad-11d1-80b4-00c04fd430c8'
  const nsBytes = namespace.replace(/-/g, '').match(/../g).map(h => parseInt(h, 16))
  const nameBytes = [...new TextEncoder().encode(name)]
  const combined = new Uint8Array([...nsBytes, ...nameBytes])

  // md5(combined) — use your preferred MD5 library or the inline implementation
  const hash = md5(combined) // returns Uint8Array(16)
  hash[6] = (hash[6] & 0x0f) | 0x30 // version 3
  hash[8] = (hash[8] & 0x3f) | 0x80 // variant

  const h = [...hash].map(b => b.toString(16).padStart(2, '0')).join('')
  return `${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20)}`
}

// Using the 'uuid' npm package
import { v3 as uuidv3 } from 'uuid'
const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'
console.log(uuidv3('example.com', uuidv3.DNS))
// → '9073926b-929f-31c2-abc9-fad77ae3e8eb' (always the same)
Python
import uuid

# Using the standard library
dns_uuid = uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
print(dns_uuid)
# → 9073926b-929f-31c2-abc9-fad77ae3e8eb

url_uuid = uuid.uuid3(uuid.NAMESPACE_URL, 'https://example.com/page')
print(url_uuid)

# Custom namespace
MY_NS = uuid.UUID('a1b2c3d4-e5f6-7890-abcd-ef1234567890')
custom = uuid.uuid3(MY_NS, 'my-entity-name')
print(custom)
Go
package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    // Standard DNS namespace
    ns := uuid.MustParse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
    id := uuid.NewMD5(ns, []byte("example.com"))
    fmt.Println(id)
    // → 9073926b-929f-31c2-abc9-fad77ae3e8eb

    // URL namespace
    urlNS := uuid.MustParse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
    idURL := uuid.NewMD5(urlNS, []byte("https://example.com/page"))
    fmt.Println(idURL)
}

常见问题

UUID v3 和 UUID v5 可以互换吗?
不可以——它们对相同输入产生不同输出,因为它们使用不同的哈希函数(MD5 vs SHA-1)。从相同命名空间 + 名称生成的 UUID v3 和 UUID v5 将是不同的 UUID。它们不可互换,但在结构和用例上功能等效。
UUID v3 具有抗碰撞性吗?
在给定命名空间内,只要 MD5 不对这些特定输入产生碰撞,两个不同的名称将产生不同的 UUID v3 值。MD5 碰撞攻击存在,但它们需要精心设计的输入——实际上,自然出现的名称(URL、域名、产品 ID)不会碰撞。对于更高的保证,请使用 UUID v5。
我可以使用 UUID v3 作为数据库主键吗?
可以,如果你理解其折衷。UUID v3 是确定性的,所以相同的键将为相同的名称生成——这提供了自然的幂等性。但是,UUID v3 不能按生成顺序排序,索引碎片化与 UUID v4 一样适用。对于按时间排序的可排序主键,请使用 UUID v7。
名称输入应该使用什么编码?
RFC 4122 规定名称应使用命名空间的规范形式转换为字节。对于 DNS 命名空间,使用不带尾随点的 UTF-8 字符串域名。对于 URL 命名空间,使用完整 URL 的 UTF-8 字符串。始终一致使用相同的编码——同一逻辑名称的不同编码将产生不同的 UUID。
UUID v3 隐藏了原始名称吗?
MD5 是单向函数——你不能从 UUID v3 反向恢复原始名称。但是,如果攻击者知道命名空间并怀疑一小组可能的名称,他们可以为每个候选预计算 UUID v3 值并进行比较。对于来自小型或可预测空间的名称,UUID v3 不提供保密性。如果你需要不透明、不可猜测的标识符,请使用 UUID v4。