简体中文

开发者工具 · UUID 生成器

GUID 与 UUID:Microsoft 的大括号、字节顺序和变体解释

· 背景

uuid 密码学 浏览器 API

以 RFC 顺序和 GUID 结构顺序呈现的相同 16 字节,显示哪些字节交换
原始 ToolAcre 矢量图

GUID 是 Microsoft 对 UUID 的名称,但大括号、大写字母和字节顺序可能会使相同的标识符在不同平台上看起来有所不同。这篇文章解释了每个差异以及如何安全地进行比较。

无法跨系统匹配的相同 ID — .NET 服务和 Java 服务在一条记录上不一致

.NET 服务生成一个 GUID 并将其发送到 Java 服务,该服务尝试将该值与来自 PostgreSQL 的 UUID 进行匹配。字符串比较失败,系统报告标识符不匹配,即使所有三个服务都使用相同的底层 16 字节。这些差异看似表面上的(大括号、大小写、字节顺序),但它们会导致字符串比较失败,并混淆未在边界标准化的积分点。 GUID 是 Microsoft 术语,RFC 9562 称为 UUID:具有相同位布局的 128 位标识符。这两个名称指的是相同的基本结构,但表示方式的不同让开发人员感到惊讶。了解混乱的根源可以防止集成错误。

GUID 是 UUID — 共享 128 位格式以及命名差异的来源

GUID 代表全局唯一标识符和全局唯一标识符,是 Microsoft 用于 RFC 标准称为 UUID 的名称。 128 位布局和版本 /variant 系统相同。 RFC 4122 和 RFC 9562 指定 UUID 格式和含义; Microsoft 实现了它们并使用术语 GUID。命名差异是历史性的:在 IETF 对 UUID 进行标准化之前,Microsoft 使用了 GUID,并且 Microsoft 术语一直停留在 .NET 生态系统中。在位级别,GUID 和 UUID 是完全可以互换的。在格式级别上,它们的表示方式有所不同:.NET 代码通常使用大括号和大写字母编写 GUID,而 RFC 规范 UUID 使用小写且不使用大括号。

大括号和大写字母 - 注册表样式的 {XXXXXXXX-...} 形式以及如何对其进行规范化

规范 RFC 形式的 UUID 写作八个、四个、四个、四个和十二个小写十六进制字符,并用连字符分隔:550e8400-e29b-41d4-a716-446655440000。 .NET GUID 通常用大括号和大写字母显示:{550E8400-E29B-41D4-A716-446655440000}。大括号来自 Windows 注册表格式;大写是一种显示约定。两种形式都表示相同的 128 位。要将 .NET 中的 GUID 与 PostgreSQL 中的 UUID 进行匹配,请去掉大括号并标准化大小写,然后比较字符串。 ToolAcre 格式良好的检查接受规范形式并自动删除大括号。规范化是一种保留所有含义的小型文本转换。

混合端字节顺序 — 前三个字段如何以小端方式存储在 GUID 结构中,以及为什么 Guid.ToByteArray 与 RFC 字节顺序不同

GUID 和 UUID 之间的危险区别在于字节顺序。 RFC 9562 指定前三个字段(8、4 和 4 十六进制组)以大端(网络)字节顺序存储。 .NET Guid 结构以小端存储前三个字段:在写入存储之前字节会反转。当由 .NET Guid.ToByteArray() 写入并由符合 RFC 的代码解释时,相同的 16 字节会产生完全不同的文本表示形式。 RFC 字节顺序中的 UUID 550e8400-e29b-41d4-a716-446655440000 存储为字节 55 0e 84 00 e2 9b 41 d4 a7 16 44 66 55 44 00 00。

旧版 Microsoft 变体 — 第四组第一个字符中的 c 或 d 的含义

除了字节顺序之外,旧版 Microsoft 标识符有时还使用非标准变体字段。其中 RFC 9562 指定第四组的第一个字符必须是 8、9、a 或 b,旧版 Microsoft GUID 可能使用 c、d、e 或 f。这些仍然是有效的 UUID,但它们符合 RFC 标准化之前的遗留变体。如果您在第四组第一个字符中遇到带有 c 或 d 的 GUID,则您有一个不符合 RFC 变体位的有效 128 位值。现代 .NET 生成符合 RFC 的 GUID,因此新标识符不应出现此问题。遗留变体位很少见,但识别起来很重要。

工作示例 — 以 RFC 顺序和 GUID 结构顺序呈现的相同 16 字节,准确显示哪些字符交换

获取 UUID 550e8400-e29b-41d4-a716-446655440000 并使用小端约定将其转换为 .NET GUID 字节数组形式。按照 RFC 顺序,字节为:第一个字段 (550e8400) 等于 55 0e 84 00,第二个字段 (e29b) 等于 e2 9b,第三个字段 (41d4) 等于 41 d4,第四个和第五个等于 a7 16 44 66 55 44 00 00。在 .NET 小端字节序中:第一个字段变为 00 84 0e 55,第二个字段变为 9b e2,第三个字段变为 d4 41,其余字段保持大端字节序。完整字节数组为 00 84 0e 55 9b e2 d4 41 a7 16 44 66 55 44 00 00。如果 Java 系统读取这些字节时需要 RFC 顺序,则会将它们解释为 00840e55-9be2-d441-a716-446655440000。

这不包括什么 - SQL Server 的 NEWSEQUENTIALID 和排序,它们是它们自己的存储主题

SQL Server NEWSEQUENTIALID 函数行为及其特定标识符排序属性是存储层和数据库特定的主题。这篇文章重点讨论应用程序和序列化级别的格式和字节顺序差异。深层特定于数据库的 UUID 处理和字节顺序问题最好在特定于该数据库平台的文档中解决。不同的数据库系统对 UUID 存储、索引、排序和本机支持有不同的方式和途径。一些数据库自动检测版本和变体位,而其他数据库则需要在系统和存储之间的边界进行显式类型声明和字节顺序处理。

要点:在边界处标准化 — ToolAcre 检查接受规范形式,这是交换 ID 时要标准化的形状

当标识符跨越 .NET/non-.NET 系统边界时,在边界处进行标准化。去掉大括号,一致地标准化大小写,如果字节来自 .NET Guid.ToByteArray(),则字节交换前三个字段。规范的 RFC 形式是参考标准:八个、四个、四个、四个和十二个小写十六进制字符,带连字符,无大括号,大端字节顺序。与 .NET 系统交换时,应商定规范化形式并在集成代码中显式应用转换。记录字节顺序处理并彻底测试转换。 GUID 和 UUID 之间的核心基本相似之处意味着大多数 128 位是相同的。