UUID v2生成器
Generate DCE Security UUID v2 with local domain and ID
什么是 UUID v2?
UUID v2 是 DCE 安全 UUID 版本,作为分布式计算环境(DCE)规范的一部分标准化,并在 RFC 4122 中引用。它通过将 POSIX 用户或组标识符(UID/GID)嵌入时间戳字段来扩展 UUID v1。
结构类似于 UUID v1,但 32 位 time_low 字段被替换为 32 位本地标识符(例如 POSIX UID),1 字节的 local_domain 字段标识它是哪种本地 ID。因此时间戳被截断,降低了其精度和唯一性保证。
UUID v2 在现代软件中极为罕见。大多数开发人员永远不需要生成一个。本页记录了该格式,以便完整性和帮助解码遗留系统中遇到的 UUID v2 值。
UUID v2 结构
UUID v2 与其他 UUID 版本具有相同的 128 位连字符格式。字段与 UUID v1 的区别如下:
| 字段 | 位数 | 用途 |
|---|---|---|
| local_id | 32 | <code>local_id</code>——32 位本地域标识符(例如来自 <code>/etc/passwd</code> 的 POSIX UID),替换 UUID v1 的 time_low 字段 |
| time_mid | 16 | <code>time_mid</code>——截断的 UUID v1 时间戳的中间 16 位 |
| time_hi+version | 16 | <code>time_hi_and_version</code>——最高 12 位时间戳,版本半字节设为 <code>2</code> |
| variant+clock_hi | 8 | <code>clock_seq_hi_and_reserved</code>——变体位加上时钟序列的高位部分 |
| local_domain | 8 | <code>local_domain</code>——域标识符:<code>0</code> = POSIX 用户(UID),<code>1</code> = POSIX 组(GID),<code>2</code> = 组织 |
| node | 48 | <code>node</code>——生成主机的 48 位 MAC 地址 |
示例:000003e8-92e0-21ef-8000-325096b39f47——local_id 0x000003e8 = UID 1000,local_domain 0x00 = POSIX 用户
本地域值
local_domain 字节指定 UUID 中嵌入的本地标识符类型:
域值由 DCE 规范定义。值 3–255 保留。实际上,只有域 0(人员/UID)在实际 UUID v2 值中常见。
为什么 UUID v2 很少使用
三个特性使 UUID v2 对于大多数现代应用程序来说不切实际:
粗糙的时间戳分辨率
时间戳被截断为 28 位(大约 7.2 分钟粒度)。在该窗口内,同一主机上具有相同 local_id 和域的 UUID 不是唯一的——规范依赖 clock_seq 字段来区分它们,将唯一性限制为每 7 分钟窗口 64 个值。
没有标准库支持
与 UUID v1 和 v4 不同,大多数 UUID 库不支持 UUID v2。uuid npm 包、Python 的 uuid 模块和 Java 的 java.util.UUID 都省略了 v2。需要自定义实现。
POSIX 特有的语义
本地域概念(UID/GID)本质上是 POSIX 特有的,在 Windows、嵌入式系统或 POSIX 用户 ID 概念不存在的云环境中没有实际意义。
历史背景
UUID v2 是在 1990 年代初期作为开放软件基金会的分布式计算环境(DCE/RPC)的一部分定义的。目标是创建可以携带授权上下文的 UUID——具体来说,是让 RPC 服务器在没有单独身份验证步骤的情况下识别调用用户。
DCE 安全模型假设了一个同质 POSIX 环境,其中每个节点都参与共享的 UID/GID 命名空间。嵌入的 UID 将让服务器快速检查访问控制列表,而无需往返目录服务。
- 互联网从同质 POSIX 环境转向异质云架构
- 现代身份验证使用令牌(JWT、OAuth)而非标识符中嵌入的 UID
- UUID v4(完全随机)和 UUID v7(按时间排序)涵盖了唯一标识符的实际用例
- DCE/RPC 本身已不再广泛使用
RFC 4122(2005 年)通过引用 DCE 规范包含了 UUID v2,但故意省略了详细的生成算法——注意它是由 DCE 而非 IETF 定义的。
RFC 9562(2024 年),更新了 UUID 标准,为了历史完整性保留了 UUID v2,但继续指出其 POSIX 特有性质和 IETF 标准中缺少完整生成算法的问题。
UUID v2 vs UUID v1
UUID v2 源自 UUID v1。以下是它们的对比:
| 方面 | UUID v1 | UUID v2 |
|---|---|---|
| 时间戳位数 | 60 位(约 100 纳秒精度) | 28 位(约 7.2 分钟精度) |
| 本地标识符 | 无 | 32 位 POSIX UID/GID |
| 本地域 | 不存在 | 0=UID,1=GID,2=组织 |
| 节点字段 | MAC 地址 | MAC 地址 |
| 库支持 | 广泛支持 | 很少支持 |
| 标准 | RFC 4122 / RFC 9562 | DCE 规范(RFC 4122 引用) |
| 实际用途 | 遗留时间戳排序 ID(Cassandra) | 仅 DCE 安全上下文 |
UUID v2 对通用用途比 UUID v1 没有任何优势,在大多数方面严格更差。没有理由在新开发中选择 UUID v2。
代码示例
UUID v2 在标准库中没有原生支持。以下示例展示如何处理 UUID v2 值:
Python——手动实现
import uuid, struct, time
def uuid_v2(local_id: int, local_domain: int = 0) -> str:
"""
Generate a DCE Security UUID (v2).
local_domain: 0 = POSIX UID, 1 = POSIX GID, 2 = Org
local_id: 32-bit unsigned integer (e.g. os.getuid())
"""
# Get a v1 UUID for the time and node fields
v1 = uuid.uuid1()
fields = list(v1.fields) # [time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node]
# Replace time_low with local_id
fields[0] = local_id & 0xFFFFFFFF
# Replace version nibble: clear lower 12 bits of time_hi, set version 2
fields[2] = (fields[2] & 0x0FFF) | 0x2000
# Replace clock_seq_low with local_domain
fields[4] = local_domain & 0xFF
return str(uuid.UUID(fields=tuple(fields)))
import os
print(uuid_v2(os.getuid(), local_domain=0)) # POSIX UID
print(uuid_v2(os.getgid(), local_domain=1)) # POSIX GID
Go——注意
// The standard "github.com/google/uuid" package does NOT support v2. // You would need to implement it manually, similar to the Python example above. // Most Go developers use v4 or v7 for new projects. import "github.com/google/uuid" v4 := uuid.New() // v4 — recommended for most use cases v7, _ := uuid.NewV7() // v7 — time-ordered, ideal for database primary keys
JavaScript——提取字段
要从现有 UUID v2 字符串中提取 local_id 和域:
// Extracting fields from a UUID v2 string
const uuidStr = '000003e8-1234-2abc-8200-a1b2c3d4e5f6'
// ^^^^^^^^ ^^^^ ^ ^^
// local_id ver variant+clockSeqHi
// ^^ = local_domain (00 = POSIX UID)
const parts = uuidStr.split('-')
const localId = parseInt(parts[0], 16) // → 1000 (0x3e8)
const version = parseInt(parts[2][0], 16) // → 2
const localDomain = parseInt(parts[3].slice(2), 16) // low byte of octet pair
const DOMAIN_NAMES = ['POSIX UID', 'POSIX GID', 'Org']
console.log(`Local ID: ${localId}`) // Local ID: 1000
console.log(`Version: ${version}`) // Version: 2
console.log(`Domain: ${DOMAIN_NAMES[localDomain]}`) // Domain: POSIX UID
google/uuid Go 包通过 uuid.NewDCEGroup() 和 uuid.NewDCEPerson() 支持 UUID v2 生成——是少数支持的主流库之一。