日本語

開発者ツール · UUID ジェネレーター

GUID 対 UUID: Microsoft の中括弧、バイト オーダー、およびバリアントの説明

· 背景

uuid 暗号化 ブラウザ API

同じ 16 バイトが RFC 順序および GUID 構造順序でレンダリングされ、どのバイトがスワップされるかを示します
オリジナル ToolAcre ベクトル イラスト

GUID は Microsoft による UUID の名前ですが、中括弧、大文字、バイト順序により、同じ識別子がプラットフォーム間で異なって見える場合があります。この記事では、それぞれの違いと安全に比較する方法について説明します。

システム間で一致しない同じ ID - 1 つのレコードに関して一致しない .NET サービスと Java サービス

.NET サービスは GUID を生成し、それを Java サービスに送信します。Java サービスは、その値を PostgreSQL の UUID と照合しようとします。 3 つのサービスがすべて同じ基礎となる 16 バイトで動作する場合でも、文字列の比較は失敗し、システムは識別子が一致しないと報告します。これらの違いは、中かっこ、大文字と小文字、バイト順序など表面的なものに見えますが、文字列の比較が失敗し、境界で正規化されない統合点が混乱する原因となります。 GUID は、RFC 9562 で UUID と呼ばれるものを表す Microsoft の用語です。つまり、同じビット レイアウトを持つ 128 ビットの識別子です。 2 つの名前は同じ基本構造を指しますが、その表現は開発者を驚かせる点で異なります。混乱がどこから発生しているのかを理解することで、統合のバグを防ぐことができます。

GUID は UUID — 共有の 128 ビット形式であり、名前の違いはどこから来たのか

GUID は Globally Unique Identifier および Globally Unique Identifier の略で、RFC 標準で UUID と呼ばれるものに対して Microsoft が使用する名前です。 128 ビット レイアウトとバージョン/variant システムは同一です。 RFC 4122 および RFC 9562 は、UUID の形式と意味を指定します。 Microsoft はこれらを実装し、GUID という用語を使用します。命名の違いは歴史的なものです。Microsoft は UUID が IETF によって標準化される前に GUID を使用しており、Microsoft の用語は .NET エコシステム内に定着しています。ビット レベルでは、GUID と UUID は完全に交換可能です。書式設定レベルでは、表現が異なります。.NET コードでは GUID を中括弧と大文字で記述することがよくありますが、RFC 正規 UUID は小文字を使用し、中括弧は使用しません。

中括弧と大文字 — レジストリ スタイルの {XXXXXXXX-...} 形式とそれを正規化する方法

正規 RFC 形式の UUID は、550e8400-e29b-41d4-a716-446655440000 のように、ハイフンで区切られた 8、4、4、4、12 個の小文字 16 進文字として記述されます。 .NET GUID は通常、中括弧と大文字で表示されます: {550E8400-E29B-41D4-A716-446655440000}。中かっこは Windows レジストリ形式から来ています。大文字は表示規則です。どちらの形式も、同一の 128 ビットを表します。 .NET の GUID を PostgreSQL の UUID と照合するには、中かっこを削除して大文字と小文字を正規化し、文字列を比較します。 ToolAcre の整形式チェックは正規形式を受け入れ、中括弧を自動的に削除します。正規化は、すべての意味を保持する小規模なテキスト変換です。

混合エンディアンのバイトオーダー — 最初の 3 つのフィールドが GUID 構造にリトルエンディアンで格納される方法、および Guid.ToByteArray が RFC バイトオーダーと異なる理由

GUID と UUID の危険な違いはバイトオーダーです。 RFC 9562 は、最初の 3 つのフィールド (8、4、および 4 の 16 進数グループ) がビッグ エンディアン (ネットワーク) バイト オーダーで格納されることを指定します。 .NET Guid 構造は、最初の 3 つのフィールドをリトル エンディアンで保存します。バイトはストレージに書き込む前に反転されます。同じ 16 バイトが、.NET Guid.ToByteArray() によって書き込まれ、RFC 準拠のコードによって解釈されると、まったく異なるテキスト表現が生成されます。 RFC バイトオーダーの UUID 550e8400-e29b-41d4-a716-446655440000 は、バイト 55 0e 84 00 e2 9b 41 d4 a7 として格納されます。 16 44 66 55 44 00 00。

従来の Microsoft バリアント — 4 番目のグループの最初の文字の c または d の意味

バイト オーダーに加えて、従来の Microsoft 識別子は非標準のバリアント フィールドを使用することがあります。 RFC 9562 では、4 番目のグループの最初の文字が 8、9、a、または b である必要があると指定されていますが、従来の Microsoft GUID では c、d、e、または f が使用される場合があります。これらは依然として有効な UUID ですが、RFC 標準化より前のレガシー バリアントに準拠しています。 4 番目のグループの最初の文字に c または d が含まれる GUID が見つかった場合は、RFC バリアント ビットに準拠していない有効な 128 ビット値を持っています。最新の .NET は RFC 準拠の GUID を生成するため、新しい識別子ではこの問題は発生しません。レガシーバリアントビットはまれですが、認識することが重要です。

動作した例 — 同じ 16 バイトが RFC 順序および GUID 構造順序でレンダリングされ、どの文字が交換されるかを正確に示します

UUID 550e8400-e29b-41d4-a716-446655440000 を取得し、リトル エンディアン規則を使用して .NET GUID バイト配列形式に変換します。 RFC 順序では、バイトは次のとおりです。最初のフィールド (550e8400) は 55 0e 84 00、2 番目のフィールド (e29b) は e2 9b、3 番目のフィールド (41d4) は 41 d4、4 番目と 5 番目は a7 16 に等しい44 66 55 44 00 00。 .NET リトルエンディアンでは、最初のフィールドは 00 84 0e 55 になり、2 番目のフィールドは 9b e2 になり、3 番目のフィールドは 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() からのものである場合は最初の 3 つのフィールドをバイトスワップします。正規の RFC 形式は参照標準です。8、4、4、4、12 個の小文字 16 進文字 (ハイフン付き、中括弧なし、ビッグエンディアンのバイト順) です。 .NET システムと交換する場合は、正規化された形式に同意し、統合コードで明示的に変換を適用します。バイトオーダーの処理と変換を徹底的に文書化します。 GUID と UUID の間の核となる基本的な類似点は、ほとんどの 128 ビットが同一であることを意味します。