🍇

RFC 9562: 汎用一意識別子(UUID)

2024/05/15に公開

要旨

本仕様は、UUID (汎用一意識別子) ─ GUID (グローバル一意識別子) とも呼ばれる ─ と、UUIDのためのユニフォーム・リソース・ネーム名前空間を定義する。UUIDは128ビット長で、空間と時間を超えて一意性を保証することを目的としている。UUIDは当初ApolloのNetwork Computing System (NCS)で使われ、その後、Open Software Foundation (OSF)の分散コンピューティング環境(DCE)、そしてMicrosoft Windowsプラットフォームで使用されてきた。

⚠️ UUIDの歴史

UUIDの歴史: <https://segment.com/blog/a-brief-history-of-the-uuid/>

Apollo Computerが設計した最初のUUIDは、以下のフォーマットだった。概念的にはUUIDv1とよく似ていた。

名称 長さ 説明
タイムスタンプ(time_high/
time_low)
6オクテット/48ビット 最初の6オクテットは、1980-01-01 00:00 UTCから経過した4マイクロ秒単位の時間数。2^{48}×4μs後は、2015-09-05 05:58:26.84262 UTCとなり、このオリジナルのUUIDで生成できる最後の時刻は2015年となる。
予約 2オクテット/16ビット 将来のために予約
アドレスファミリー 1オクテット/8ビット アドレスファミリー
ノード 7オクテット/56ビット 指定されたアドレスファミリーで許可されている形式のホストID

本仕様は、OSF(現在は「The Open Group」として知られる)の許可を得て、OSF DCE仕様から派生したものである。OSF DCE仕様以前のバージョンの情報は、本文書に組み込まれている。この文書により、RFC 4122を廃止する。

本文書の位置付け

本文書は、インターネット標準化過程の文書である。

この文書はInternet Engineering Task Force (IETF)の成果物である。IETFコミュニティのコンセンサスを表すものである。公開レビューを受けており、Internet Engineering Steering Group (IESG)によって公開が承認されている。インターネット標準の詳細については、RFC 7841のセクション 2を参照のこと。

本文書の現在のステータス、正誤表、および文書に対するフィードバックの提供方法に関する情報は、https://www.rfc-editor.org/info/rfc9562 で入手できる。

著作権表示

Copyright (c) 2024 IETFトラストおよび文書の著者として特定された人物。無断転載を禁じる。

本文書は、BCP 78および文書の発行日において有効なIETF文書に関するIETFトラストの法的規定(https://trustee.ietf.org/license-info)に従うものとする。これらの文書には、本文書に関するあなたの権利と制限が記載されているため、注意深く確認して欲しい。文書から抽出されたコード・コンポーネントには、トラスト法的条項のセクション4.eに記載されている改訂BSDライセンスのテキストを含まなければならず、改訂BSDライセンスに記載されているように保証なしで提供する。

1. はじめに

本仕様は、グローバル一意識別子(GUID)とも呼ばれる汎用一意識別子(UUID: Universally Unique IDentifier)のユニフォーム・リソース・ネーム名前空間を定義する。UUIDは128ビット長で、中央の登録プロセスは必要ありません。

UUIDの利用は、コンピューティングにおいて極めて普及しており、Microsoft Windowsなどの多くのオペレーティング・システムやMozilla Webブラウザなどのアプリケーションの中核となるID基盤を構成している。多くの場合、IDはさまざまな非標準的な方法で公開される可能性がある。

この仕様は、インターネット全体に利益をもたらすような方法で、可能な限りオープンにその方法を標準化しようとするものである。ここでの情報は、URN[RFC8141]あるいはそれ以外の方法との組み合わせで、UUIDを使用してサービスを実装しようとする人たちのための簡潔なガイドとなることを目的としている。

[RFC4122]から派生したITU-T勧告とISO/IEC標準[X667]が存在する。どちらの仕様も調整されており、技術的に完全に互換性がある。本文書のいかなる内容も、UUIDを定義したDCE標準を無効にするものと解釈してはならない。

⚠️ UUIDの実装について

UUIDの実装と検討事項のリストを収集しているサイト: https://github.com/swyxio/brain/blob/master/R - Dev Notes/uuid list.md

⚠️ PythonでUUIDを生成する

Python3のuuidというモジュールが標準ライブラリとしてバンドルされている。現状、RFC 4122準拠したuuid1()、uuid3()、uuid4()、uuid5()が生成できる。

>>> import uuid
>>> uuid.uuid1()
UUID('26f80942-1251-11ef-8c2c-424fdc2a8bf5')
>>> uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
UUID('9073926b-929f-31c2-abc9-fad77ae3e8eb')
>>> uuid.uuid4()
UUID('a4a9332c-fb3d-4707-9d70-31d846ff84cd')
>>> uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
UUID('cfbff0d1-9375-5685-968c-48ce8b15ae17')
>>> 

2. 動機

UUIDを使用する主な理由の1つは、UUIDを管理する中央管理機関が不要なことである。(ただし、2つのフォーマットはオプションのIEEE 802ノードIDを利用することができるが、他のフォーマットは利用しない)。その結果、オンデマンドでの生成を完全に自動化し、さまざまな目的に使用することができる。ここで説明するUUID生成アルゴリズムは、必要であればマシンあたり毎秒1,000万、あるいはそれ以上の非常に高いレートの割り当てをサポートするため、トランザクションIDとしても使用できる。

UUIDは固定サイズ(128ビット)で、他の代替手段と比べるとかなり小さい。これは、あらゆる種類のソート、順序付け、ハッシュ化、データベースへの格納、単純な割り当て、一般的なプログラミングの容易さという点で適している。

UUIDはユニークで永続的であるため、優れたURNになる。登録プロセスなしで新しいUUIDを生成できるユニークな能力により、UUIDは最小コストのURNの1つとなる。

2.1. 動機の更新

UUIDが最初に作成されてから、多くのことが変化してきた。最新のアプリケーションでは、データベース・キー、ファイル名、マシンやシステム名、イベント駆動型トランザクションの識別子など(ただし、これらに限定されない)、複雑な計算システムにおけるさまざまな項目のプライマリ識別子としてUUIDを作成し、利用する必要がある。

UUIDが人気を集めている分野の1つはデータベース・キーである。これは、最近のアプリケーションは分散化が進んでいることに起因している。分散システムでは、データベースでよく使われる「自動インクリメント」スキームはうまく機能しない。ネットワーク全体で連続する数値識別子を調整するのに必要な労力は、負担になりやすい。UUIDは調整を必要とせず、分散システム内で一意で適度に短い値を作成するために使用できるという事実により、UUIDを優れた選択肢にしているが、元々 [RFC4122]で定義されたUUIDバージョン1~5は、以下のような他の望ましい特性を欠いている:

  1. UUIDv4(セクション5.4で説明)のような時間順ではないUUIDバージョンは、データベースとインデックスの局所性が低くなる。これは、連続して作成される新しい値がインデックス内で互いに近接しないことを意味する。したがって、ランダムな位置で挿入を実行する必要がある。その結果、使用される一般的な構造(Bツリーとそのバリアント(亜種))に対する性能への悪影響は、劇的に大きくなる可能性がある。

  2. UUIDv1のタイムスタンプ(セクション5.1で説明)で使用される100ナノ秒のグレゴリオ暦エポックは一般的ではなく、[IEEE754]で説明するような標準的な数値フォーマットを使って正確に表すのは難しい。

  3. イントロスペクション/解析は、単純なバイトごとの比較が実行できずに、時系列で順序付けを必要とする。

  4. UUIDv1のノードフィールドでメディア・アクセス・コントロール(MAC)アドレスを使用することで、プライバシーとネットワーク・セキュリティの問題が生じる。さらされたMACアドレスは、ネットワーク・インタフェースを特定し、そのようなマシンに関する他のさまざまな情報(最低でも製造元、場合によっては他の詳細)を明らかにするための攻撃対象領域として使われる可能性がある。さらに、仮想マシンとコンテナの出現により、MACアドレスの一意性は保証されなくなった。

  5. [RFC4122]で指定された実装の詳細の多くは、すべてのアプリケーションに対して指定することが可能なわけでも、相互運用可能な実装を作成するために必要なわけでもないトレードオフを含んでいる。

  6. [RFC4122]は、UUIDを生成するための要件と、UUIDを単に格納するための要件を区別していなかったが、それらは異なることがよくある。

これらの問題により、多くの広域分散データベースのアプリケーションや大手アプリケーション・ベンダーは、データベース・キーとして使用する、より優れた時間ベースのソート可能な一意の識別子を作成するという問題の解決を模索してきた。そのため、過去10年以上にわたって、同じ問題を少し異なる方法で解決する数多くの実装が行われてきた。

本仕様の作成中、以下の16の異なる実装について、IDの合計長、ビットレイアウト、字句フォーマットと符号化、タイムスタンプのタイプ、タイムスタンプのフォーマット、タイムスタンプの精度、ノードのフォーマットとコンポーネント、衝突処理、マルチタイム・スタンプ・ティック生成シーケンスの傾向を分析した:

  1. [ULID]
  2. [LexicalUUID]
  3. [Snowflake]
  4. [Flake]
  5. [ShardingID]
  6. [KSUID]
  7. [Elasticflake]
  8. [FlakeID]
  9. [Snowflake]
  10. [orderedUuid]
  11. [COMGUID]
  12. [SID]
  13. [pushID]
  14. [XID]
  15. [ObjectID]
  16. [CUID]

これらの実装と上記の問題点を検証した結果、新しいUUIDがこれらの問題に対処するよう適応された、この文書につながった。

さらに、[RFC4122]自体も、以下に限定されるものではなく、多くのトピックに対処するために全面的な見直し(オーバーホール)を必要としていた:

  1. 各種正誤報告の実装。 主にビットレイアウトの明確化に関するもので、実装の不一致[Err1957]、[Err3546]、[Err4975]、[Err4976]、[Err5560]などにつながる。
  2. 他のUUIDバージョンをUUIDv1ビットレイアウトから切り離し、「time_hi_and_version」のようなフィールドが時間ベースではないUUIDの中で参照する必要がないようにする一方で、UUIDv3、UUIDv4、UUIDv5に対してUUIDv1と同様の定義セクションを提供する。
  3. 既存の実装やプロトタイプの実装で観察された多くの実世界のシナリオやコーナーケースに関する実装のベスト・プラクティスを提供する。
  4. MACアドレス、ハッシュ・アルゴリズム、安全なランダム性、その他のトピックに関連する、現代におけるセキュリティのベスト・プラクティスと考慮事項を扱う。
  5. 実装固有および/または実験的なUUID設計のための標準ベースのオプションを実装に提供する。
  6. 仕様に従って作成された実際のUUIDを例示する、より多くのテストベクタを提供する。

3. 用語

3.1. 要件言語

この文書のキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「NOT RECOMMENDED」、「MAY」、および「OPTIONAL」は、ここに示すように、すべて大文字で表示される場合に限り、 BCP 14 [RFC2119] [RFC8174]の記述に従って解釈される。

3.2. 略語

本文書では次の略語を使用する:

略語 正式名称 説明
ABNF Augmented Backus-Naur Form 拡張バッカス・ナウア記法
CSPRNG Cryptographically Secure Pseudorandom Number Generator 暗号的に安全な擬似乱数生成器
DBMS Database Management System データベース管理システム
IEEE Institute of Electrical and Electronics Engineers 米国電気電子学会
ITU International Telecommunication Union 国際電気通信連合
MAC Media Access Control メディアアクセス制御
MD5 Message Digest 5 メッセージ・ダイジェスト5
MSB Most Significant Bit 最上位ビット
OID Object Identifier オブジェクト識別子
SHA Secure Hash Algorithm セキュア・ハッシュ・アルゴリズム
SHA-1 Secure Hash Algorithm 1 (with message digest of 160 bits) セキュア・ハッシュ・アルゴリズム1 (160ビットのメッセージ・ダイジェスト)
SHA-3 Secure Hash Algorithm 3 (arbitrary size) セキュア・ハッシュ・アルゴリズム3 (任意のサイズ)
SHA-224 Secure Hash Algorithm 2 with message digest size of 224 bits 224ビットのメッセージ ダイジェスト サイズを持つセキュア・ハッシュ・アルゴリズム2
SHA-256 Secure Hash Algorithm 2 with message digest size of 256 bits 256ビットのメッセージ ダイジェスト サイズを持つセキュア・ハッシュ・アルゴリズム2
SHA-512 Secure Hash Algorithm 2 with message digest size of 512 bits 512ビットのメッセージ ダイジェスト サイズを持つセキュア・ハッシュ・アルゴリズム2
SHAKE Secure Hash Algorithm 3 based on the KECCAK algorithm KECCAKアルゴリズムに基づくセキュア・ハッシュ・アルゴリズム3
URN Uniform Resource Names ユニフォーム・リソース名
UTC Coordinated Universal Time 協定世界時
UUID Universally Unique Identifier 汎用一意識別子
UUIDv1 Universally Unique Identifier version 1 汎用一意識別子バージョン1
UUIDv2 Universally Unique Identifier version 2 汎用一意識別子バージョン2
UUIDv3 Universally Unique Identifier version 3 汎用一意識別子バージョン3
UUIDv4 Universally Unique Identifier version 4 汎用一意識別子バージョン4
UUIDv5 Universally Unique Identifier version 5 汎用一意識別子バージョン5
UUIDv6 Universally Unique Identifier version 6 汎用一意識別子バージョン6
UUIDv7 Universally Unique Identifier version 7 汎用一意識別子バージョン7
UUIDv8 Universally Unique Identifier version 8 汎用一意識別子バージョン8

4. UUIDのフォーマット

UUIDのフォーマットはサイズ16オクテット (128ビット) である。バリアント・ビットと次のセクションで説明するバージョン・ビットを組み合わせて、より細かな構造を決定する。これらのUUIDフォーマットとレイアウトに関して、ビット定義は0から始まり127で終わり、オクテット定義は0から始まり15で終わる。

逆に、明示的なアプリケーションやプレゼンテーション・プロトコルの仕様がない場合、各フィールドは最上位バイトを最初に符号化する(「ネットワーク ・バイト・オーダー」として知られている)。

UUIDをバイナリ形式で保存するには、すべてのフィールドをビッグエンディアン形式で読み取る。ただし、Microsoftのコンポーネント・オブジェクト・モデル(COM)のGUIDは、GUIDを保存するときにリトルエンディアンを利用するという既知の注意点がある。これに関する議論([MS_COM_GUID]を参照)は、この仕様の範囲外である。

UUIDはバイナリデータまたは整数として表しても良い(MAY)。URNで使用する場合、あるいはアプリケーションでテキストとして使用する場合、UUIDはダッシュ/ハイフンで区切られた大文字または小文字の英数字16進文字の複数のグループで構成する「16進数とダッシュ」文字列形式で表す必要がある。データベースで使用する場合は、セクション6.13参照のこと。

UUID文字列表現の正式な定義は、次のABNF [RFC5234]によって規定する。

UUID     = 4hexOctet "-"
           2hexOctet "-"
           2hexOctet "-"
           2hexOctet "-"
           6hexOctet
hexOctet = HEXDIG HEXDIG
DIGIT    = %x30-39
HEXDIG   = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"

[RFC5234]のセクション2.3に従って、アルファベットはすべて大文字でも、すべて小文字でも、大文字と小文字が混在してもよいことに留意する。上記のABNFからこのテキスト表現を使用したUUIDの例を図1に示す。

f81d4fae-7dec-11d0-a765-00a0c91e6bf6

図1: 文字列UUIDフォーマットの例

図1と同じUUIDは、バイナリ(図2)、符号なし整数 (図3)、および[RFC8141]で定義されたURN(図4)で表される。

111110000001110101001111101011100111110111101100000100011101000\
01010011101100101000000001010000011001001000111100110101111110110

図2: バイナリUUIDの例

329800735698586629295641978511506172918

図3: 符号なし整数UUIDの例 (10進数で表示)

urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6

図4: UUIDのURN名前空間の例

UUIDフォーマットを定義する方法は他にもたくさん存在する。以下にいくつかの例を説明する。これは完全なリストではなく、情報提供のみを目的として提供していることに留意する。

  • [Python]や[Microsoft]に見られるようないくつかのUUID実装は、中括弧で囲まれたダッシュを含む文字列形式でUUIDを出力する。

  • [X667]は、OIDでUUIDを使うための UUIDフォーマット定義を提供している。

  • [IBM_NCS]は、表1のバリアント0xxと互換性のある独自のUUIDフォーマットを生成するレガシー実装である。

⚠️ UUIDv1フォーマットの例

uuidv1-format

4.1. バリアント・フィールド

バリアント・フィールドは、UUIDのレイアウトを決定する。つまり、UUIDの他のすべてのビットの解釈は、バリアント・フィールドのビット設定に依存する。したがって、より正確には「タイプ」フィールドと呼ぶことができる。互換性のために元の用語をそのまま使用する。 バリアント・フィールドは、UUIDのオクテット8の最上位ビットの可変数で構成される。

⚠️ バリアント

16進数表記でxxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxxのNの桁の上位ビットがバリアントとなる。RFCの規格は、上位2ビットが0b10であることが定められているので、後続のビットは可変になるので、8、9、A、Bのいずれかとなる。これ以外のバリアントは後方互換か将来のために予約されている。

表1は、バリアント・フィールドの内容を示している。文字「x」は「無関係」値を示す。

MSB0 MSB1 MSB2 MSB3 バリアント 説明
0 x x x 1-7 予約済み。ネットワーク・コンピューティング・システム(NCS)の後方互換であり、セクション5.9に従っ てNil UUIDを含む。
1 0 x x 8-9,A-B 本文書で指定されているバリアント。
1 1 0 x C-D 予約済み。Microsoftの後方互換。
1 1 1 x E-F 将来の定義のために予約されており、セクション5.10に従ってMax UUIDを含む。

表1: UUIDのバリアント

どのような形であれ、ここで定義されているもの以外のバリアントとの相互運用性は保証されないが、実際には問題になる可能性は低い。

特に本文書のUUIDは、UUIDのビット64と65(オクテット8のビット0と1)は、表1の行2で指定されているように1と0に設定しなければならない(MUST)。したがって、すべてのビットとフィールドのレイアウトはこれらのビットの使用を避ける。

4.2. バージョン・フィールド

バージョン番号はオクテット6の最上位4ビット(UUIDのビット48~51)にある。

表2に、本文書で指定されたこのUUIDバリアント「10xx」のすべてのバージョンの一覧である。

MSB0 MSB1 MSB2 MSB3 バージョン 説明
0 0 0 0 0 未使用
0 0 0 1 1 本文書で規定するグレゴリオ暦の時間ベースのUUID
0 0 1 0 2 POSIXのUUIDが埋め込まれたDCEセキュリティ・バージョン用に予約
0 0 1 1 3 MD5ハッシュを使用する、本文書で規定する名前ベースのバージョン
0 1 0 0 4 本文書で規定する、ランダムまたは擬似的に生成されたバージョン
0 1 0 1 5 SHA-1ハッシュを使用する、本文書で規定する名前ベースのバージョン
0 1 1 0 6 本文書で規定するグレゴリオ暦の時間ベースのUUIDを並べ替えたもの
0 1 1 1 7 本文書で規定するUnixエポック時間ベースのUUID
1 0 0 0 8 本文書で規定するカスタムUUIDフォーマット用に予約
1 0 0 1 9 将来の定義のために予約
1 0 1 0 10 将来の定義のために予約
1 0 1 1 11 将来の定義のために予約
1 1 0 0 12 将来の定義のために予約
1 1 0 1 13 将来の定義のために予約
1 1 1 0 14 将来の定義のために予約
1 1 1 1 15 将来の定義のために予約

表2: この仕様で定義されるUUIDバリアント10xxバージョン

UUIDv4のバージョン/バリアントのレイアウトの例を表に示す。ここで、「M」は0x4(0b0100)の16進表現のバージョン配置を表し、「N」はバリアント10xxの4つの16進表現のうちの1つのバリアント配置を表す: 0x8 (0b1000)0x9 (0b1001)0xA (0b1010)0xB (0b1011)

00000000-0000-4000-8000-000000000000
00000000-0000-4000-9000-000000000000
00000000-0000-4000-A000-000000000000
00000000-0000-4000-B000-000000000000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

図5: UUIDv4バリアントの例

表1にある他の残りのUUIDバリアントは、異なるサブタイプまたはバージョン管理メカニズムを利用していることに留意すべきである。残りのUUIDバリアントとサブタイプの組み合わせの記録と定義は、本文書の範囲外である。

5. UUIDのレイアウト

オクテット内のビット割り当てや異なるバージョン間の混乱を最小限に抑えるために、UUIDレコード定義は、1行あたり4オクテットで構成されるビットレイアウト内のフィールドのグループとして提供される。フィールドは最上位のフィールドから順に表示される。

5.1. UUIDバージョン1

UUIDv1は、1582年10月15日00:00:00.00(グレゴリオ暦からキリスト教歴への改暦日)以降の100ナノ秒間隔のカウントとして協定世界時(UTC)で表される60ビットのタイムスタンプを特徴とする時間ベースのUUIDである。

UUIDv1は、クロックシーケンス・フィールドも備えており、クロックが時間的に逆向きに設定された場合や、ノードIDが変更された場合に発生する可能性のある重複を回避するために使用される。

⚠️ クロックシーケンス

クロックシーケンスという名前は誤解を招くかもしれない。単なるインクリメントされるだけ、あるいは乱数で数列ではない。クロックシーケンスの目的はただ一つ、重複を避けるためである。RFC 4122[RFC4122]の中で、以下のように書かれている。

4.1.5. クロックシーケンス

UUIDバージョン1では、クロックシーケンスは、クロックが時間的に逆に設定された場合やノードIDが変更された場合に発生する可能性のある重複を回避するために使用される。

クロックが逆に設定されたり、逆に設定されたかもしれず(例えば、システムの電源がオフになっている間)、UUID生成器がクロックが設定された値よりも大きなタイムスタンプを持つUUIDが生成されていないことを確認できない場合、クロックシーケンスを変更する必要がある。クロックシーケンスの前の値が分かっている場合、それをインクリメントするだけで済む。それ以外の場合、ランダムまたは高品質な擬似ランダム値に設定する必要がある。

同様に、ノードIDが変更された場合(例えば、ネットワークカードがマシン間で移動されたなどの理由で)、クロックシーケンスを乱数に設定することで、マシンのクロック設定のわずかな違いによる重複の可能性が最小限に抑えることができる。変更されたノードIDに関連するクロックシーケンスの値が分かっていれば、クロックシーケンスをインクリメントするだけで済むが、その可能性は低い。

クロックシーケンスは、システム間の相関を最小限に抑えるため、元々(つまり、システムの存続期間に1度だけ)乱数に初期化されなければならない(MUST)。これにより、システム間で急速に移動したり、切り替わる可能性のあるノード識別子に対する最大限の保護が提供される。初期値をノード識別子に相関があってはならない(MUST NOT)。

UUIDバージョン3または5の場合、クロックシーケンスは、セクション4.3で説明している名前から構築された14ビット値である。

UUID バージョン4の場合、クロックシーケンスは、セクション4.4で説明しているように、ランダムまたは擬似ランダムに生成された14ビット値である。

ノードフィールドはIEEE 802のMACアドレスで構成され、通常はホスト・アドレス、またはセクション6.9と6.10に従ってランダムに導出された値である。

fig6
図6: UUIDv1フィールドとビットレイアウト

フィールド 説明
time_low 60ビットの開始タイムスタンプの下位32ビット。 ビット0~31(オクテット0~3)を占める。
time_mid 60ビットの開始タイムスタンプの中央の16ビット。 ビット32~47(オクテット4~5)を占める。
ver セクション4.2で定義されている4ビットのバージョン・フィールドは、0b0001(1)に設定される。オクテット6のビット48~51を占める。
time_high 60ビットの開始タイムスタンプの最下位12ビット。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義された2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
clock_seq クロックシーケンスを含む14ビット。ビット66~79(オクテット8~9)を占める。
node 48ビットの空間一意識別子。ビット80~127(オクテット10~15)を占める。

UTCは利用できないが、ローカル時間を持っているシステムの場合、システム全体で一貫して使用している限り、UTCの代わりにローカル時間を使うことができる。ただし、ローカル時間からUTCを生成するにはタイムゾーン・オフセットが必要なだけなので、これは推奨しない。

クロックが時間的に逆に設定された場合、あるいは逆に設定された可能性があり(例えば、システムの電源がオフになっている場合など)、UUIDジェネレータは、クロックが設定された値よりも大きいタイムスタンプを持つUUIDが生成されていないことを確認できない場合、クロックシーケンスは変更しなければならない(MUST)。クロックシーケンスの前の値が既知の場合、それをインクリメントしてもよい(MAY)。そうでなければ、乱数値または高品質の擬似乱数値に設定する必要がある(SHOULD)。

同様に、ノードIDが変更された場合(例えば、ネットワーク・カードがマシン間で移動されたなどの理由で)、クロックシーケンスを乱数に設定することで、マシンのクロック設定のわずかな違いによる重複の可能性を最小限に抑えることができる。変更されたノードIDに関連付けられたクロックシーケンスの値がわかっていれば、クロックシーケンスをインクリメントしてもよい(MAY)が、その可能性は低い。

クロックシーケンスは、システム間の相関を最小限に抑えるために、最初に(つまり、システムの存続期間に一度だけ)乱数に初期化しなければならない(MUST)。これにより、システム間で急速に移動したり、切り替わったりする可能性のあるノードIDに対する最大限の保護を提供する。初期値はノードIDに関連付けてはならない(MUST NOT)。

IEEE 802から派生したノードに関する注意事項:

  • 複数のIEEE 802アドレスを持つシステムでは、利用可能などのアドレスを使用してよい(MAY)。

  • IEEEアドレスの持たないシステムでは、ランダムまたは擬似ランダムに生成された値を使用しなければならない(MUST)。セクション6.9と6.10を参照のこと。

  • 64ビットMACアドレスを利用するシステムでは、最下位の右端の48ビットを使用してもよい(MAY)。

  • IEEE 802.15.4の16ビットアドレスを利用するシステムは、代わりに、最下位の右端の48ビットが使用される64ビットMACアドレスを利用する必要がある(SHOULD)。別の方法として、32ビットのランダム・データを生成し、16ビットMACアドレスの末尾に接尾辞を付けて、48ビット値を作成する。

5.2. UUIDバージョン2

UUIDv2はDCEセキュリティUUIDのためのものである([C309]と[C311]を参照)。そのため、これらのUUIDの定義は本仕様の範囲外である。

5.3. UUIDバージョン3

UUIDv3は、セクション6.5に従って、ある名前空間から抽出され、その名前空間内で一意な名前からUUIDを生成することを目的としている。

UUIDv3の値は、与えられた名前空間ID値(セクション6.6)を、その名前空間の標準または規約によって定義したオクテットの基準シーケンスをネットワーク・バイト・オーダーで変換した後、特定の名前の値と連結した上でMD5ハッシュ[RFC1321]を計算することによって生成される。それからこのMD5値は、UUIDレイアウトの128ビットすべてを設定するために使用される。それからUUIDのバージョンとバリアントは、セクション4.2と4.1で定義しているように、それぞれのビットを置き換える。このビット置換の例は付録A.2にある。

特定の名前空間内で目的の名前の正規形式を選択することに関する情報は、セクション6.5の「名前に関する注意事項」項にある。

可能な場合は、UUIDv3の代わりにUUIDv5を使用する必要がある(SHOULD)。MD5のセキュリティに関する考慮事項の詳細については[RFC6151]を参照のこと。

fig7
図7: UUIDv3フィールドとビットレイアウト

フィールド 説明
md5_high レイアウトの最初の48ビットは、計算されたMD5値の最上位の左端の48ビットで埋められる。ビット0~47(オクテット0~5)を占める。
ver 0b0011(3)に設定された、セクション4.2で定義された4ビットのバージョン・フィールド。オクテット6のビット48~51を占める。
md5_mid 計算されたMD5値のmd5_highの続く16ビットのうち、最下位の右端の12ビットで構成されるレイアウトのさらに12ビット。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義されている2ビットのバリアント・フィールドで、0b10に設定さる。オクテット8のビット64と65を占める。
md5_low varフィールドに続くレイアウトの最後の62ビットは、計算されたMD5値の最後の64ビットのうち、最下位で右端のビットで埋められる。ビット66~127(オクテット8~15)を占める。

5.4. UUID バージョン 4

UUIDv4は、真の乱数または疑似乱数からUUIDを生成することを目的としている。

実装は、図8のUUIDフィールドを埋めるために使用される128ビットのランダム・データを生成する。その後、セクション4.1と4.2で定義されているように、UUIDのバージョンとバリアントは、それぞれのビットを置き換える。

あるいは、実装は、random_a、random_b、random_cに必要なビット数(合計122ビット)をランダムに生成し、必要な位置にバージョンとバリアントを連結する方法を選択してもよい(MAY)。

ランダム・データ生成のガイドラインは、セクション6.9を参照のこと。

fig8
図8: UUIDv4フィールドとビットレイアウト

フィールド 説明
random_a セクション6.9で規定されているように、ランダム・データで埋められるレイアウトの最初の48ビット。ビット0~47(オクテット0~5)を占める。
ver セクション4.2で定義される4ビットのバージョン・フィールドは、0b0100(4)に設定される。オクテット6のビット48~51を占める。
random_b セクション6.9により、ランダム・データを埋め込むことができるレイアウトのさらに12ビット。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義されている2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
random_c セクション6.9に従ってランダム・データで埋められるvarフィールドの直後のレイアウトの最後の62ビット。ビット66~127(オクテット8~15)を占める。

5.5. UUID バージョン5

UUIDv5は、セクション6.5に従って、ある「名前空間」から抽出され、その中で一意の「名前」からUUIDを生成することを目的としている。

UUIDv5値は、指定された名前空間ID値(セクション6.6)を、その名前空間の標準または慣行で定義するように、ネットワーク・バイトオーダーでオクテットの基準シーケンスに変換した後に、希望する名前値と連結した上で、SHA-1ハッシュ[FIPS180-4]を計算することによって生成される。その後、SHA-1値の最上位の左端の128ビットを使用して、UUIDレイアウトのすべての128ビットが設定され、SHA-1出力の残りの最下位の右端の32ビットは破棄される。UUIDのバージョンとバリアントは、セクション4.2と4.1で定義しているように、それぞれのビットを置き換える。このビット置換と余分なビットの破棄の例は付録A.4にある。

特定の名前空間内で目的の名前の正規化形式を選択することに関する情報は、セクション6.5の「名前に関する注意事項」項に記載されている。

通常、組織のセキュリティ・ポリシーによっては、SHA-1ライブラリが利用できなかったり、使用が安全でないとみなされるシナリオが存在するかもしれない。そのような場合、SHA-256またはより新しいSHAメソッドから派生した名前ベースのUUIDを生成することが望ましい場合がある。これらの名前ベースのUUIDはUUIDv5を利用してはならず(MUST NOT)、セクション5.8で定義されたUUIDv8空間内になければならない(MUST)。SHA-256の名前ベースのUUIDのUUIDv8の例示を付録B.2に記載する。

SHA-1セキュリティに関する考慮事項の詳細については[RFC6194]を参照のこと。

fig9
図9: UUIDv5フィールドとビットレイアウト

フィールド 説明
sha1_high レイアウトの最初の48ビットは、計算されたSHA-1値の最上位の左端の48ビットで埋められる。ビット0~47(オクテット0~5)を占める。
ver 0b0101(5)に設定された、セクション4.2で定義された4ビットのバージョン・フィールド。オクテット6のビット48~51を占める。
sha1_mid 計算されたSHA-1値のsha1_highの直後にある16ビットのうち、最下位の右端の12ビットで構成されるレイアウトのさらに12ビット。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義される2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
sha1_low varフィールドの直後のレイアウトの最後の62ビットは、残りのSHA-1ハッシュの最上位2ビットをスキップし、次の最上位の左端の62ビットを使用して埋められる。残ったSHA-1ビットは破棄され、使用されない。ビット66~127(オクテット8~15)を占める。

5.6. UUIDバージョン6

UUIDv6は、UUIDv1(セクション5.1)のフィールド互換バージョンであり、DBの局所性を向上させるために並べ替えられている。UUIDv6は主にUUIDv1が使用されている環境で実装することが想定される。従来のUUIDv1を使用しないシステムでは、代わりにUUIDv7(セクション5.7)を使用する必要がある(SHOULD)。

UUIDv1のタイムスタンプを下位、中位、上位のセクションに分割するのではなく、 UUIDv6はこの順序を変更し、タイムスタンプ・バイトが最上位から最下位の順に格納されるようにする。 つまり、セクション5.1でUUIDv1に指定された60ビットのタイムスタンプ値が与えられた場合、UUIDv6では最初の48の最上位ビットが最初に格納され、次に4ビットのバージョン(同じ位置)が続き、その後に元の60ビットのタイムスタンプ残りの12ビットが続く。

クロックシーケンスとノードビットは、セクション5.1の位置から変更されない。

クロックシーケンスとノードビットは、新しいUUIDv6が生成されるごとに擬似ランダム値にリセットする必要がある(SHOULD)。ただし、実装はセクション5.1の古いクロックシーケンスとMACアドレスの動作を保持することを選択してもよい(MAY)。UUID内でのMACアドレスの使用についての詳細は、セクション8を参照のこと。

16バイト、128ビットのUUIDv6のフォーマットを図10に示す。

fig10
図10: UUIDv6フィールドとビットレイアウト

フィールド 説明
time_high 60ビットの開始タイムスタンプの最上位32ビット。ビット0~31(オクテット0~3)を占める。
time_mid 60ビットの開始タイムスタンプの中央の16ビット。ビット32~47(オクテット4~5)を占める。
ver セクション4.2で定義されている4ビットのバージョン・フィールドは、0b0110(6)に設定される。オクテット6のビット48~51を占める。
time_low 60ビットの開始タイムスタンプの最下位12ビットを含む12 ビット。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義されている2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
clock_seq クロックシーケンスを含む14ビット。ビット66~79(オクテット8~9)を占める。
node 48ビットの空間的一意識別子。ビット80~127(オクテット10~15)を占める。

UUIDv6では、タイムスタンプをtime_highとtime_midに分割する手順は、time_highとtime_midの48ビットが同じ順序のままなので自分で選ぶことができる。タイムスタンプの最初の48ビットを最上位32ビットと最下位16ビットに分割する追加の手順は、既存のUUIDv1実装を再利用する場合に役立つことが分かる。

5.7. UUIDバージョン7

UUIDv7は、広く実装されよく知られているUnixエポック・タイムスタンプ・ソースから派生した時間順の値フィールドを特徴とする。これは、うるう秒を除く、UTCの1970年1月1日午前0時からのミリ秒数である。一般に、UUIDv7はUUIDv1(セクション5.1)またはUUIDv6(セクション5.6)よりもエントロピーの特性が改善されている。

⚠️ エントロピーとは

エントロピーとは、暗号化やランダムなデータを必要とする場合に、オペレーティング・システムやアプリケーションによって収集されるランダム性を言う。エントロピー不足、すなわちランダム性が低い場合は、性能はセキュリティに悪影響を及ぼす可能性がある。

UUIDv7値は、最上位48ビットにミリ秒単位のUnixタイムスタンプを割り当て、必要なバージョンとバリアント・ビットを除く残りの74ビットを、セクション6.9に従って一意性を提供するために生成された新しいUUIDv7ごとにランダムなビットで埋めることによって生成される。あるいは、実装はミリ秒内での追加の単調性を保証するために、最上位ビットから最下位ビットの順に、以下のサブフィールドの組み合わせで74ビットを一緒に埋めてもよい(MAY)。

  1. セクション6.2(方法3)の通り、オプションのサブミリ秒タイムスタンプの小数部分(最大12ビット)(OPTIONAL)。

  2. セクション6.2(方法1または2)に従った、慎重にシードされたオプションのカウンタ(OPTIONAL)。

  3. 残りの領域に対して生成される新規UUIDv7ごとのランダムデータ。

実装は可能であればUUIDv1とUUIDv6の代わりにUUIDv7を使用する必要がある(SHOULD)。

fig11
図11: UUIDv7フィールドとビットレイアウト

フィールド 説明
unix_ts_ms 48ビットのビッグエンディアンの符号なし数値で、セクション6.1に従ったミリ秒単位のUnixエポック・タイムスタンプ。ビット0~47(オクテット0~5)を占める。
ver セクション4.2で定義されている4ビットのバージョン・フィールドは、0b0111(7)に設定される。オクテット6のビット48~51を占める。
rand_a セクション6.9に従った一意性を提供するための12ビットの擬似乱数データ、および/またはセクション6.2に従った追加の単調性を保証するためのオプションの構成。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義された2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
rand_b セクション6.9による一意性を提供するための最後の62ビットの疑似乱数データ、および/またはセクション6.2による追加の単調性を保証するためのオプションのカウンタ。ビット66~127(オクテット8~15)を占める。

5.8. UUID バージョン 8

UUIDv8は、実験的またはベンダー固有のユースケースのためのフォーマットを提供する。唯一の要件は、セクション4.1と4.2で定義されているように、バリアント・ビットとバージョン・ビットを設定しなければならない(MUST)。UUIDv8の一意性は実装に固有であり、偽値であってはならない(MUST NOT)。

明示的に定義されたビットはバージョン・フィールドとバリアント・フィールドのビットのみで、実装固有のUUIDのために122ビットが残されている。明確にしておくが、UUIDv8はUUIDv4(セクション5.4)に置き換わるものではなく、122の追加ビットすべてがランダムデータで埋められる。

UUIDv8が使用される可能性のある状況の例をいくつか示す:

  • 実装は、UUIDの中にこの文書で定義されているもの以外の追加情報を埋め込みたいと考えている。

  • 実装は、現在のUUIDのうち1つの使用を抑制するような、他のアプリケーションおよび/または言語の制限を持っている。

付録Bは、2つのシナリオ例に対処するためのカスタムUUIDv8アルゴリズムの2つの具体例を示している。

fig12
図12: UUIDv8フィールドとビットレイアウト

フィールド 説明
custom_a レイアウトの最初の48ビットは、実装が適切と判断したときに埋めることができる。ビット0~47(オクテット0~5)を占める。
ver セクション4.2で定義されている4ビットのバージョン・フィールドは、0b1000(8)に設定される。オクテット6のビット48~51を占める。
custom_b レイアウトの12ビットは、実装が適切と判断した場合に埋めることができる。ビット52~63(オクテット6~7)を占める。
var セクション4.1で定義されている2ビットのバリアント・フィールドで、0b10に設定される。オクテット8のビット64と65を占める。
custom_c varフィールドの直後に続くレイアウトの最後の62ビットは、実装が適切と判断した場合に埋められる。ビット66~127(オクテット8~15)を占める。

5.9. Nil UUID

Nil UUIDは、128ビットすべてがゼロに設定されるように指定された特別な形式の UUIDである。

00000000-0000-0000-0000-000000000000

図13: Nil UUIDフォーマット

Nil UUID値は、128ビットUUIDが必要または使用される状況で、他のUUID値が存在しないことを伝えるのに役立つ。Nil UUIDは、「ここにはそのような値はない」という概念を表現できる。したがって、実装固有の状況で必要とされるような用途のために予約されている。

Nil UUID値は、本文書で定義されているバリアントではなく、表1の最初の行にあるApollo NCSバリアントの範囲内にあることに留意する。

5.10. Max UUID

Max UUIDは、128ビットをすべて1に設定するように指定された特別な形式のUUIDである。このUUIDは、セクション5.9で定義されたNil UUIDの逆と考えることができる。

FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF

図14: Max UUIDフォーマット

Max UUID値は、128ビットのUUIDが要求される状況でセンチネル値として使用することができるが、「UUIDリストの終了」のような概念を表現する必要があり、実装固有の状況で必要に応じてそのような使用のために予約されている。

最大UUID値は、本文書で定義されたバリアントではなく、表1の最後の行にあるように、「まだ定義されていない」将来のUUIDバリアントの範囲にあることに留意する。

6. UUIDのベスト・プラクティス

本文書は、各バージョンのUUIDを生成するための最小要件について説明している。それ以外はすべて実装の詳細であり、特定の実装に何が適切かを決めるのは実装者次第である。さまざまなUUID実装の間で異なるトレードオフを通して実装者を導くために、さまざまな関連要因を以下で説明する。

6.1. タイムスタンプに関する考慮事項

UUIDタイムスタンプのソース、精度、長さは、この仕様のためにUUIDv7を作成する際に大きな議論となった。アプリケーションに適切なタイムスタンプを選択することは非常に重要である。このセクションでは、この問題に関する最も一般的なポイントを詳しく説明する。

信頼性:
実装は、信頼できるソースから現在のタイムスタンプを取得し、時間順に並べ、継続的に増加し続ける値を提供する。環境またはオペレーティング・システムのタイムスタンプの変更が、実装要件と一致する方法で処理されることを保証するために、注意を払われなければならない。例えば、手動調整または時刻同期プロトコルによる修正が原因で、システム・クロックが逆方向に進む可能性がある場合、実装はそのようなケースをどのように処理するかを決定する必要がある。(以下の「変更、ファジング、スミアリング」を参照のこと。)

ソース:
UUIDv1とUUIDv6はどちらもグレゴリオ暦エポックのタイムスタンプを利用するが、UUIDv7はUnixエポックのタイムスタンプを利用する。他のタイムスタンプ・ソースまたはカスタム・タイムスタンプ・エポックが必要な場合、UUIDv8を使用しなければならない(MUST)。

1秒未満の正確さと精度:
タイムスタンプには、ミリ秒、マイクロ秒、ナノ秒など、さまざまなレベルの精度が存在する。さらに、さまざまなレベルの精度を時間順に混在させるために、1秒未満の精度の小数表現が望まれる場合もある。さらに、システム・クロック自体には基本的な粒度があり、それはオペレーティング・システムが提供する精度よりも小さいことが多い。UUIDv1とUUIDv6では、100ナノ秒の精度が存在する。一方、UUIDv7はUnixエポック内でデフォルトでミリ秒レベルの精度を特徴とするが、これはほとんど最新のシステムで可能な粒度を超えない。他の精度レベルでは、UUIDv8が利用可能である。セクション6.2と同様に、UUIDv1またはUUIDv6では、同じ値のシステム時間で生成されたUUIDの数をカウントし、そのカウントを使ってタイムスタンプの下位ビットを構築することで、高解像度のタイムスタンプをシミュレートできる。高分解能タイムスタンプのカウントは、ゼロからシステム時間間隔あたりの100ナノ秒間隔の数までの範囲となる。

長さ:
特定のタイムスタンプの長さは、タイムスタンプ・フィールドの最大値に達する前に、UUIDにいくつのタイムスタンプ・ティックが含まれ得るかに直接影響する。特定のタイムスタンプに対して適切な長さが選択されるように留意する。UUIDv1とUUIDv6は、西暦5623年まで有効な60ビットのタイムスタンプを利用し、UUIDv7は西暦10889年まで有効な48ビットのタイムスタンプを特徴としている。

変更、ファジング、スミアリング:
実装は実際のタイムスタンプを変更してもよい(MAY)。例としては、1) 不正確なクロックを修正する、2) うるう秒を処理する、3) パフォーマンス上の理由から(マイクロ秒数を1000で割る代わりに)、1024(または他の値)で割ってミリ秒値を取得するなどのために、UUID内で実クロック値を提供することに関するセキュリティへの考慮事項が含まれる。この仕様では、クロック値が実際の時刻にどの程度近づく必要があるかについて、要件も保証もしない。UUIDを頻繁に生成する必要がない場合、UUIDv1またはUUIDv6タイムスタンプは、単にシステム時間に、システム時間間隔ごとの100ナノ秒間隔の数を乗算したものになる。

パディング:
タイムスタンプのパディングが必要な場合、実装は最上位ビット(左端)にデータをパディングしなければならない(MUST)。このパディング・データの例としては、Unixタイムスタンプの最上位の左端のビットを0で埋め、UUIDv7の48ビットのタイムスタンプを完成させる。データをパディングする別のアプローチとして、最上位のビットの左端を、2038-01-19以降の32ビットUnixタイムスタンプのロールオーバー数で埋める方法がある。

切り捨て:
タイムスタンプを切り捨てる必要がある場合は、下位の最下位ビットを使わなければならない(MUST)。例えば、64ビットUnixタイムスタンプをUUIDv7のために最下位の右端の48ビットに切り捨てることが挙げられる。

エラー処理:
システムが1つのシステム時間間隔内に多過ぎるUUIDを要求することによって生成器をオーバーランした場合、UUIDサービスはエラーを返すか、システムクロックが追いつくまでUUID生成器をストールすることができる。また、カウンタのロールオーバーによる故意に重複した値を返してはならない(MUST NOT)。プロセッサがUUID生成を頻繁にオーバーランする場合、追加のノードIDをシステムに割り当てることができることに留意する。これにより、タイムスタンプ値ごとに複数の UUIDを潜在的に利用できるようになり、より高速な割り当てが可能になる。同様の手法はセクション6.4で説明している。

6.2. 単調性とカウンタ

単調性(後続の各値が最後の値より大きいこと)は、時間ベースのソート可能なUUIDの重要要素である。通常、本文書による時間ベースのUUIDは、タイムスタンプが埋め込まれているため単調になる。しかし、実装はこのセクションで扱う概念によって追加の単調性を保証できる。

バッチで生成されたUUIDも単調なことを保証するよう留意する。つまり、同じタイムスタンプに対して、1,000個のUUIDが生成される場合、それらの1,000個の UUIDの生成順序を整理するための十分なロジックが必要になる。バッチUUID生成の実装では、特定のタイムスタンプ中に生成されるUUIDごとにインクリメントする単調なカウンタを利用してもよい(MAY)。

UUIDのバッチを作成する必要がないシングルノードUUID実装の場合、UUIDv6とUUIDv7に埋め込まれたタイムスタンプは、新しいUUIDを生成する前にタイムスタンプをインクリメントすることを保証するだけで、十分な単調性を提供できる。分散ノードについてはセクション6.4で説明する。

実装は、バッチUUID生成が必要な場合、あるいは高頻度のUUID生成に伴う単調性を懸念するシングルノードUUID実装に対して、以下の方法を採用する必要がある(SHOULD)。

固定ビット長の専用カウンタ(方法1):
実装によっては、UUIDタイムスタンプ・ティック中に作成されたUUIDの総数を集計することだけを目的として、UUIDレイアウトに特定のビット数を割り当てるものもある。固定ビット長カウンタが存在する場合は、埋め込まれたタイムスタンプの直後に配置しなければならない(MUST)。これにより並べ替えが容易になり、カウンタの増分に対してランダムなデータを生成できるようになる。この方法では、UUIDv7のrand_aセクション(またはその左端ビットのサブセット)が、UUID 世代ごとにインクリメントする固定ビット長の専用カウンタとして使用する。rand_bが新しいUUIDごとに生成される後続のランダム・ビットは、推測不可能なUUIDの生成に役立つ。さらに多くのカウンタ・ビットが必要な場合は、rand_bの最上位(左端)ビットを追加のカウンタ・ビットとして使用してもよい(MAY)。

単調ランダム (方法2):
この方法では、ランダム・データを拡張してカウンタとしても機能させる。この単調な値は、タイムスタンプ・ティックで作成された各UUIDに対して、最下位位置でインクリメントしなければならない「ランダムにシードされたカウンタ」と考えることができる。UUIDv7のrand_bセクションは、1つのタイムスタンプ・ティック中のUUIDの一括生成を処理するために、このメソッドと共に利用すべきである(SHOULD)。すべてのUUID生成のインクリメント値は、ゼロより大きい任意の長さのランダムな整数である。これは、UUIDが基礎となるエントロピーによって提供される推測不可能性の要求レベルを保持することを保証する。特定の期間に生成されるUUIDの数が重要であり、推測可能性が問題にならなければ、増分値は1であってもよい(MAY)。ただし、カウンタを1ずつ増やすことは、結果の値が容易に推測可能であるため、推測不可能性を優先する実装では使用すべきではない(SHOULD NOT)。

左端のランダム・ビットをクロック精度を向上させて置き換える (方法3):
ミリ秒のタイムスタンプ精度を持つUUIDv7では、システムで利用可能な追加のクロック精度を使用して、タイムスタンプの直後に続く最大12個のランダム・ビットを置き換えることができる。これにより、実装環境で適切なビット数を使用して、サブミリ秒の精度で時間順に並べられた値を提供することができる。この方法では、追加の時間精度ビットが、UUIDv7のrand_aフィールドで次に使用可能なビットとしてタイムスタンプに続かなければならない(MUST)。

この値を計算するには、クロックのティック値の小数部(UUIDv7の場合はミリ秒の小数)で表されるタイムスタンプの部分から始める。UUIDv7のrand_aフィールドの場合、利用可能なビット空間4096で表現可能な値の数を計算する。浮動小数点演算またはスケーリングされた整数演算を使用して、このミリ秒の小数部に4096を乗じ、0と指示されたビットに許容される最大値との間の数値を求めるために、(0方向に)整数の結果に切り捨てる。これは、時間に基づいて単調にソートされる。小数部が増加するたびに、そのビットで利用可能な精度までビットフィールド値が大きくなる。

例えば、システムのタイムスタンプが2023年1月1日12:34:56.1234567だと仮定する。1ミリ秒を超える精度を取ると、ミリ秒の小数点部として0.4567という値が得られる。これを12ビットで符号化したい場合は、そのビットに収まる可能性のある値の数(4096または2^{12})を取り、それにミリ秒の小数値0.4567を乗算し、結果を整数に切り詰めれば、1870という整数値が得られる。16進数で表すと0x74E、2進数のビットでは0b011101001110となる。その後、この12ビットをUUIDのランダムセクション(UUIDv7のrand_aフィールドなど) の最上位(左端)部分として使うことができる。これは、UUIDに収まる任意のビット長に対して機能し、アプリケーションは利用可能なクロック精度に基づいて適切な長さを決定できる。UUIDv7の場合、ランダムビット用に十分なスペースを確保するため、最大12ビットに制限されている。

追加のタイムスタンプ精度を符号化する主な利点は、システムクロックですでに利用可能な追加の時間精度を利用して、一意である可能性がより高い値を提供することである。したがって、実装を簡素化することができる。この手法は、他の方法のと組み合わせて使うこともでき、その場合、この追加の時間精度はタイムスタンプの直後に続く。次に、クロックシーケンスとして使用するビットがあれば、そのビットが次に続く。


以下のサブトピックでは、信頼性の高い固定ビット長の専用カウンタを作成することのみに関連する問題を取り扱う:

固定ビット長専用カウンタのシーディング:
固定ビット長カウンタ方式を利用した実装では、新しいタイムスタンプが刻まれるごとに、カウンタがランダムに初期化される。ただし、タイムスタンプが増加していない場合、カウンタは代わりに好ましいインクリメント・ロジックによってインクリメントされる。方法1と並行してランダムにシードされたカウンタを利用する場合、ソート可能性に影響を与えることなく、カウンタの増分ごとにランダム値を再生成してもよい(MAY)。欠点は、適切な長さのカウンタが選択されなかったり、生成されたランダムデータが必要な増分数のための余地がほとんど残さない場合、方法1はオーバーフローがしやすいということである。固定ビット長カウンタ方式を利用する実装では、カウンタ全体ではなく、カウンタの一部をランダムに初期化してもよい(MAY)。例えば、24ビットのカウンタでは、最下位右端の位置にある23ビットをランダムに初期化できる。残りの最上位、左端のカウンタ・ビットは、カウンタのロールオーバーを防ぐためだけにゼロとして初期される。

固定ビット長専用カウンタ長:
使用中のタイムスタンプ精度のレベルを適切に処理できるカウンタのビット長を選択する。例えば、ミリ秒精度は一般的に、ナノ秒精度のタイムスタンプよりも大きなカウンタを必要とする。一般的なガイダンスとして、カウンタは少なくとも12ビットであるべきで、42ビットより長くてあってはならない(SHOULD)。選択したカウンタ長が、カウンタ後のUUIDのランダム部分に十分なエントロピーの余地を残すことを保証するよう留意する必要がある。このエントロピーは、バッチ内で作成されたUUIDの推測不可能性の特性を改善するのに役立つ。


以下のサブトピックでは、どちらのタイプのカウンタ方式でも、ロールオーバー処理について説明する:

カウンタ・ロールオーバー・ガード:
固定ビット長カウンタのセグメントをロールオーバー・ガードとして割り当てることを説明した上記の「固定ビット長専用カウンタ・シーディング」の手法も、カウンタ・ロールオーバーの問題を軽減するのに役立つ。これと同じ手法を、最下位の右端の位置で可能な増分の長さの合計が、増分されるランダム値の合計の長さよりも短くすることを保証することで、単調ランダム・カウンタ方式で使用することができる。このように、最上位の左端のビットをロールオーバー・ガードとしてインクリメントできる。

カウンターロールオーバーの処理:
ソートの問題を避けるために、カウンタのロールオーバーはアプリケーションによって処理しなければならない(MUST)。一般的なガイダンスとして、絶対的な単調性とソート可能性を重視するアプリケーションは、カウンタをフリーズし、タイムスタンプが進むのを待つ必要がある。これは、単調性が崩れないことを保証する。あるいは、実装は実際の時間よりも先にタイムスタンプをインクリメントし、カウンタを再初期化してもよい(MAY)。


実装は、埋め込みカウンタを特徴とするUUIDが本質的に単調であることを保証するために、以下のロジックを使用してもよい(MAY):

  1. 現在のタイムスタンプを以前に保存されたタイムスタンプと比較する。

  2. 現在のタイムスタンプが以前のタイムスタンプと等しい場合、望ましい方法に従ってカウンタをインクリメントする。

  3. 現在のタイムスタンプが以前のタイムスタンプより大きい場合は、新しいタイムスタンプに望ましいカウンタ・メソッドを再初期化し、新しいランダムバイトを生成する(バイトがフリーズされていた場合、または単調カウンタのシードとして使用されていた場合)。

単調エラーチェック:
実装は、現在生成されているUUIDが以前に生成されたUUIDより大きいかどうかをチェックする必要がある(SHOULD)。そうでない場合、クロックのロールバック、うるう秒の処理、カウンタのロールオーバーなど、さまざまな問題が発生している可能性がある。アプリケーションは、これらのシナリオを捕捉し、次に生成されるUUIDが以前のUUIDよりも大きくなるように問題を修正するのに十分なロジックを組み込む必要がある(SHOULD)。そうでない場合は、少なくとも適切なエラーを報告する必要がある。このシナリオに対処するために、アプリケーションは以前のタイムスタンプを再利用し、以前のカウンタ・メソッドをインクリメントしてもよい(MAY)という一般的なガイダンスがある。

6.3. UUID生成状態

(オプションの)UUID生成状態は、システム全体の共有揮発性ストアに読み込まれる場合(そして、安定ストアが更新されるたびに更新される)、ブート時に一度だけ安定ストレージから読み出す必要がある。

この安定ストレージは、UUID生成のさまざまな部分を記録するために使用してもよい(MAY)。これは、バッチUUID生成の目的や、UUIDv6及びUUIDv7での単調エラーチェックに役立つことが証明されている。これらの保存された値には、最終既知のタイムスタンプ、クロックシーケンス、カウンタ、ランダムデータが含まれるが、これらに限定されない。

実装が利用可能な安定ストアを持たない場合、その実装はこれがバッチ内で最初に生成されたUUIDであるかのようにUUID生成を進めてもよい(MAY)。これは、クロックシーケンス、カウンタ、ランダムデータのような値の生成頻度を増加させ、重複の可能性が高くなるため、最も望ましくない実装である。さらに、乱数の頻繁な生成は、そのような乱数の基礎として使用されるエントロピー源および/またはエントロピー・プールににより大きなストレスを与える。

実装はまた、衝突耐性が最大の懸念事項である場合、アプリケーション・エラーを返してもよい(MAY)。このエラーのセマンティクスはアプリケーションと実装次第である。アプリケーションにおける衝突耐性の重み付けについての詳細はセクション6.7を参照のこと。

UUIDv1及びUUIDv6では、ノードIDが絶対に変更されない場合(例えば、ノードIDの導出元のネットワーク・インタフェース・カードがシステムから切り離せない場合)、または変更によってクロックシーケンスもランダムな値に再初期化される場合、安定ストアに保持する代わりに、現在のノードIDを返すことができる。

UUIDv1及びUUIDv6では、UUIDが生成されるたびに状態を常に安定ストアに書き込む必要は必ずしもない。安定ストアのタイムスタンプは、UUIDでまだ使用されていない値よりも大きい値に定期的に設定することができる。生成されたUUIDのその値よりも小さいタイムスタンプを持ち、クロックシーケンスとノードIDが変更されない限り、状態の共有揮発性コピーだけが更新される必要がある。さらに、安定ストアのタイムスタンプ値が、システムの再起動にかかる標準的な時間よりも未来にある場合、クラッシュがクロックシーケンスの再初期化を引き起こすことはない。

UUIDが生成されるたびに共有状態にアクセスするのがコストが高過ぎる場合は、システム全体のジェネレータを実装して、呼び出されるたびにタイムスタンプのブロックを割り当てることができる。プロセスごとのジェネレータは、そのブロックが使い果たすまでそのブロックから割り当てることができる。

6.4. 分散UUIDの生成

実装によっては、共通の場所に保存するUUIDを2つ以上のノードが独立して生成する、マルチノードのクラスタ化されたアプリケーションの利用を望んでもよい(MAY)。UUIDはすでに、衝突の可能性を低くすることを保証するのに十分なエントロピーを備えているが、UUIDを生成するノードの総数が増加するにつれて、衝突の可能性も増加する。

このセクションでは、分散環境におけるマルチノードUUID実装によって観察された2つの追加的な衝突耐性アプローチについて詳しく説明する。

このセクションは完全を期すために2つの方法について詳しく説明するが、分散UUID生成のための追加の衝突耐性が要件の場合、実装は擬似ランダムノードIDオプションを利用すべきであることに留意する。同様に、分散環境でのUUID生成の実装では、どちらの方法の利用も必須ではない。

ノードID:
この方法では、擬似ランダムなノードID値がUUIDレイアウト内に配置される。この識別子は、ノードのビット空間が一意であることを保証するのに役立ち、その結果、異なるノードIDを持つ他のノードによって作成された他のUUIDと衝突しないUUIDを生成する。埋め込みノードIDを利用することを選択した実装は、UUIDv8を利用する必要がある(SHOULD)。ノードIDは、セクション8に従ってIEEE 802 MACアドレスであってはならない(SHOULD NOT)。位置とビット長は実装に委ねられ、この仕様の範囲外である。さらに、ノード間のユニークなノードIDの作成とネゴシエーションも、この仕様の範囲外である。

一元化されたレジストリ:
この方式では、UUIDの生成を担当するすべてのノードが中央レジストリを参照し、生成された値がユニークであることを確認する。アプリケーションの規模を拡大するにつれて、中央レジストリとの通信がボトルネックとなり、UUID生成に否定的な影響を与える可能性がある。中央/グローバル・レジストリを持つ共有知識スキームはこの仕様の範囲外であり、推奨されない(NOT RECOMMENDED)。


さまざまなホストでUUIDを生成する分散アプリケーションは、すべてのホストの乱数ソースに依存することを望まなければならない(MUST)。

6.5. 名前ベースのUUID生成

ハッシュ・アルゴリズム(MD5またはSHA-1)を特徴とするUUIDを表現するために「ハッシュ・ベース」という言葉を使うことを好む人もいるが、本文書では、以前に公開された文書や既存の実装との一貫性を保つために、「名前ベース」という用語の使用を維持する。

名前ベースのUUIDの要件は以下のとおりである:

  • 同じ名前空間内の同じ名前から(同じ基準フォーマットを使用して)異なる時間に生成されたUUIDは等しくなければならない(MUST)。

  • 同じ名前空間内の異なる2つの名前(同じまたは異なる基準フォーマット)から生成されたUUIDは、(非常に高い確率で)異なるはずである。

  • 2つの異なる名前空間で同じ名前(同じまたは異なる基準フォーマット)から生成されたUUIDは、(非常に高い確率で) 異なるはずである。

  • 名前から生成された2つのUUIDが、(同じ基準フォーマットを使用して)等しい場合、それらは(非常に高い確率で)同じ名前空間の同じ名前から生成されたことになる。

⚠️ 基準フォーマット

ハイフンで区切られた16進数の文字列を表示するフォーマットのこと。

名前に関する注意:

名前(および名前空間)の概念は、テキスト名に限定されるものではなく、広く解釈されるべきである。オクテットの基準シーケンスとは、その名前形式の正規表現の仕様に準拠するものである。名前には多くの通常の形式があるが、基準のものとなるのは1つだけである。UUIDの新しい名前空間の実装者は、その空間における名前の基準フォーマットの仕様を参照するか、名前空間が存在しない場合はそのような正規形式を定義する必要がある。例えば、執筆時点では、ドメインネームシステム(DNS)[RFC9499]には、共通 (www.example.com)、プレゼンテーション (www.example.com.)、ワイヤ・フォーマット (3www7example3com0)の3つの伝達フォーマットがある。[X500]識別名(DN)を見ると、[RFC4122]ではテキストベースまたはバイナリのDERベースの名前を入力として許可している。URL(ユニフォーム・リソース・ロケータ)[RFC1738]の場合、プロトコル識別子 www.example.comまたはhttps://www.example.comの有無にかかわらず、完全修飾ドメイン名(FQDN)を指定できる。オブジェクト識別子(OID)[X660]に関しては、先頭のドットなしのドット表記(2.999)を選択するか、先頭のドット(.2.999)を含めるか、OID国際化リソース識別子(OID-IRI) (/Joint-ISO-ITU-T/Example)など、[X680]にある多くのフォーマットの1つを選択することもできる。ほとんどのユーザは、DNSの共通フォーマット、URLのFQDNフォーマット、X.500のテキスト・フォーマット、OIDの先頭ドットなしのドット表記をデフォルトとして使用するかもしれないが、名前ベースのUUIDの実装は一般に、前述の例示の名前やここで定義されていない他の名前に対して名前ベースのUUIDを計算する任意の入力を許可する必要がある(SHOULD)。名前空間内の各名前フォーマットは、異なるUUIDを出力する。そのため、名前を割り当てや名前空間内での一意性を保証するために使用される仕組みや規則は、この仕様の範囲外である。

6.6. 名前空間IDの使用と割り当て

このセクションでは、DNS[RFC9499]、URL[RFC1738]、OID[X660]、DN[X500] など、潜在的に興味深い名前空間の名前空間IDについて詳しく説明する。

さらに、本セクションでは、割り当て、IANA登録、および名前空間IDに関連するその他の詳細についても詳しく説明する。

名前
空間
名前空間ID値 名前参照 名前空間ID参照
DNS 6ba7b810-9dad-11d1-80b4-00c04fd430c8 [RFC9499] [RFC4122], RFC 9562
URL 6ba7b811-9dad-11d1-80b4-00c04fd430c8 [RFC1738] [RFC4122], RFC 9562
OID 6ba7b812-9dad-11d1-80b4-00c04fd430c8 [X660] [RFC4122], RFC 9562
X500 6ba7b814-9dad-11d1-80b4-00c04fd430c8 [X500] [RFC4122], RFC 9562

表3: 名前空間ID

項目は[RFC8126]に従って、仕様必須(Specification Required)ポリシーを使用して、このレジストリに追加することができる。

代表専門家の場合、一般的に言って、名前空間IDは以下のように割り当てられる。

  • DNSの最初の名前空間ID値は、時間ベースのUUIDv1と「6ba7b810-9dad-11d1-80b4-00c04fd430c8」から計算され、開始点として使用される。

  • 後続の名前空間ID値は、time_low「6ba7b810」の最下位右端ビットをインクリメントする一方、UUIDの残りを「9dad-11d1-80b4-00c04fd430c8」に凍結する。

  • 新しい名前空間ID値は、これと同じロジックを使用しなければならず(MUST)、以前に使用された名前空間ID値を使用してはならない(MUST NOT)。

  • したがって、「6ba7b815」は、完全なIDが「6ba7b815-9dad-11d1-80b4-00c04fd430c8」である新しい名前空間ID値の次に使用可能なtime_lowである。

  • この特殊な用途である名前空間ID値のtime_lowの上限は、「ffffffff」または「ffffffff-9dad-11d1-80b4-00c04fd430c8」であり、将来の名前空間ID値には十分なスペースが必要である。

名前空間ID値「6ba7b813-9dad-11d1-80b4-00c04fd430c8」とその用法は、この文書または[RFC4122]では定義されていないことに留意する。したがって、名前空間ID値として使用すべきではない(SHOULD NOT)。

新しい名前空間ID値がグローバルに利用可能で、完全な相互運用性を持つためには、セクション7に従って実証しなければならない(MUST)。実装は、ベンダ固有、アプリケーション固有、デプロイ固有の名前空間ID値を使い続けてよい(MAY)。ただし、相互運用性は保証されないことに留意する。これらのカスタム名前空間ID値は、上記のロジックを使用してはならない(MUST NOT)。代わりに、UUIDv4またはUUIDv7名前空間ID値を生成することが推奨される(RECOMMENDED)。最終的な名前ベースのUUIDの衝突確率(セクション6.7)と一意性(セクション6.8)が問題にならない場合、実装はカスタムでアプリケーション固有の名前空間ID値を生成するために、代わりにUUIDv8を利用してもよい(MAY)。

実装は、このセクションにリストされているもの以外の、新しく登録されたIANA名前空間ID値、またはカスタムでアプリケーション固有の名前空間ID値を考慮するために、カスタム名前空間を入力する機能を提供すべきである(SHOULD)。

6.7. 耐衝突性

実装では、アプリケーション内でのUUID衝突の結果と、セクション6.1及び6.2のような他のコンポーネントとエントロピー(ランダム性)を使用するUUIDバージョンのどちらを使用するかを決定する際の結果を比較検討する必要がある。これは、特にセクション6.4で定義される分散ノード衝突耐性に当てはまる。

以下に、アプリケーション内での衝突の深刻さの違いを説明するのに役立つ2つのシナリオ例を示す。

低影響:
UUIDの衝突は重複したログ・エントリを生成し、その結果、データから得られる統計が不正確になる。衝突によって悪影響を受けない実装は、本文書で定義されているUUIDによって提供されるエントロピーと一意性を維持して続行できる。

大きな影響:
合鍵のせいで、飛行機は間違った進路を選択し、人命が危険にさらされる。このシナリオでは、ミスは許されない。衝突は避けなければならない。失敗は許されない。この種のシナリオを扱うアプリケーションは、与えられたアプリケーションの文脈内で、できるだけ多くの衝突耐性を採用しなければならない。

6.8. グローバルとローカルの一意性

この仕様によって作成されたUUIDは、ローカルの一意性の保証を提供するために使用してもよい(MAY)。例えば、ローカル・アプリケーション・コンテキスト内で作成されたUUIDがデータベース内で一意であることを保証することは、アプリケーション・コンテキスト外、他のアプリケーション内、あるいは世界中でのグローバルな一意性が要求されない実装によっては、十分かもしれない(MAY)。

真のグローバルな一意性は共有知識スキームなしでは保証することは不可能だが、共有知識スキームは実用的な実装目的で一意性を提供するためにUUIDで要求されるものではない。実装は、この仕様で保証される一意性を拡張するために、適切と判断した場合、セクション6.4で導入される共有知識スキームを使用してもよい(MAY)。

6.9. 推測不可能性

実装は、暗号論的擬似乱数生成器(CSPRNG、暗号論的にセキュアな疑似乱数生成器)を利用して、予測が困難(「推測不可能」)かつ衝突の可能性が低い(「ユニーク」)値を提供する必要がある(SHOULD)。ただし、実行環境で適切なCSPRNGが利用できない場合は例外である。適切なCSPRNGの動作を保証するために、プロセス・フォークなどの状態変更時に、CSPRNGの状態が適切に再シードされるように留意する。CSPRNGは、セクション6.7と8の最良の部分が最新のUUIDに存在することを保証する。

暗号品質の乱数を生成するための更なるアドバイスは、[RFC4086]、[RFC8937]、 [RANDOM]にある。

6.10. ホストを識別しないUUID

このセクションでは、IEEE 802アドレスが利用できないか、その使用が望ましくない場合に、UUIDv1またはUUIDv6値を生成する方法について説明する。

実装は、このセクションで提供される擬似ランダム・ロジックの代替として、MACアドレス・ランダム化技術[IEEE802.11bh]を利用してもよい(MAY)。

あるいは、実装はセクション6.9に従って48ビットの暗号化品質の乱数を取得し、ノードIDとして使用することを選択してもよい(MAY)。48ビットの完全にランダム化されたノード値を生成した後、実装はノードIDの最初のオクテットの最下位ビットを1に設定しなければならない(MUST)。このビットはユニキャストまたはマルチキャスト・ビットであり、ネットワーク・カードから取得したIEEE 802アドレスでは決して設定されない。したがって、ネットワーク・カードを備えたマシンとネットワーク・カードを備えていないマシンで生成されたUUIDの間に競合が生じることはない。ランダム化された48ビットのノード値の生成とそれに続くビット修正の例については、付録Aで詳しく説明する。IEEE 802アドレスとユニキャスト、マルチキャスト、ローカル/グローバル・ビットの詳細は、[RFC9542]を参照のこと。

以前の仕様との互換性を保つため、本文書では、ローカル/グローバル・ビットが設定されているMACアドレスと設定されていないMACアドレスの両方がネットワーク内で可能であるため、間違いなくより正しいローカル/グローバル・ビットではなく、ユニキャストまたはマルチキャスト・ビットを使用することに留意する。ユニキャストまたはマルチキャスト・ビットの場合はそうではない。1つのノードが複数のノードにマルチキャストするMACアドレスを持つことはできない。

さらに、コンピュータ名やオペレーティング・システム名などの項目は、厳密に言えばランダムではないが、他のシステムで得られた結果と区別するのに役立つ。

これらのデータを使用してノードIDを生成する正確なアルゴリズムは、利用可能なデータとそれらを取得する関数の両方がシステム固有であることが多いため、システム固有である。しかし、一般的なアプローチは、可能な限り多くのソースをバッファに蓄積し、([FIPS180-4]で定義されているSHA-256やSHA-512のような)メッセージ・ダイジェストを使用し、ハッシュ値から任意の6バイトを取得し、上で説明したようにマルチキャスト・ビットを設定する。

6.11. ソート

UUIDv6とUUIDv7は、ソートを必要とする実装(例えば、データベース・インデックス)が、解析やイントロスペクションを必要とせずに、Opqaueな生のバイトとしてソートするように設計されている。

時間順に並べられた単調なUUIDは、新しい値がインデックス内で互いに近いため、データベース・インデックスの局所性の恩恵を受ける。その結果、オブジェクトはより簡単にクラスタ化され、パフォーマンスが向上する。このインデックスの局所性とランダムなデータ挿入の現実的な違いは、1桁かそれ以上になる可能性がある。

この仕様によって作成されたUUIDフォーマットは、テキスト表現で辞書順にソートできるようにすることを目的としている。

この仕様によって作成されるUUIDは、ビッグエンディアン・バイトオーダー(ネットワーク・バイトオーダー)を念頭に作成されている。リトルエンディアン・スタイルが必要な場合は、UUIDv8をカスタムUUIDフォーマットで利用できる。

6.12. 不透明性

一般的な指針として、不必要にUUID値を解析することは避けることが推奨される。その代わり、UUIDをできるだけ不透明に扱う。もちろん、アプリケーション固有の懸念には、ある程度のイントロスペクションが必要になるかもしれないが (例えば、セクション4.1や4.2、あるいはUUIDのタイムスタンプを調べるなど)、ここでのアドバイスは、絶対に必要な場合を除き、この解析や他の解析を避けることである。一般的に、このアドバイスに従うと、アプリケーションはよりシンプルになり、相互運用性が高まり、パフォーマンスが向上する傾向がある。

⚠️ 不透明に扱うとは

不透明に扱うとは、UUIDの内部構造、生成方法、フォーマットの詳細について考えず、単にUUIDが一意の識別子として機能することにのみ注目して使用するという意味である。

  1. 内部構造は気にしない: UUIDの中身が何か意味するものであるとか、特定のビットが何かを意味するとかを気にしてはいけない。
  2. UUIDを比較する際、部分的な比較や特定のビットの比較をせず、全体として比較すること。UUIDの一致は全体の完全一致を指す。
  3. UUIDがどのように生成されたかは考慮せず、一意であることを信頼して使用すること。
  4. UUIDの生成アルゴリズムによる一意性を信頼し、UUIDが衝突しないことを前提として扱うこと。

6.13. DBMSとデータベースの考慮事項

データベースのようなアプリケーションにとって、UUIDをテキストとして格納することは不必要に冗長であり、128ビットのUUID値を表現するために288ビットが必要になる。したがって、可能な場合には、UUIDをデータベース・アプリケーション内で基礎となる128ビットのバイナリ値として格納する必要がある(SHOULD)。

他のシステムでは、UUIDは必要に応じてバイナリ形式またはテキストとして可能してもよい(MAY)。双方のアプローチのトレードオフは以下のとおりである:

  • バイナリ形式で格納すると、必要なスペースが少なく済み、データのアクセスが速くなる可能性がある。

  • テキストとして格納すると、多くのスペースが必要になるが、検索後に結果のテキスト形式を使用する場合、翻訳の必要性が少なくなり、実装が簡単になる可能性がある。

DBMSベンダーは、主キー、時制データベースのサロゲートキー、ポリモーフィック・リレーションに含まれる外部キー、JSON列やキー・バリュー・データベースのキーなど(ただし、これらに限定されない)の識別子または識別子の左側部分として使用するために、この仕様で定義されているUUID形式を生成して格納する機能を提供することが推奨される。モノリシック・データベースを使用するアプリケーションは、(クライアントが生成するUUIDではなく)データベースが生成するUUIDを使用することが、最適なUUID単調性を提供することに気付くかもしれない。UUIDに加えて、完全性とフィードバックを保証するために追加の識別子を使用してもよい(MAY)。

データベース・スキーマの設計者は、テーブル内の主キーとして名前ベースのUUID(セクション5.3と5.5を参照)を使用しないよう留意する。データベース・スキーマの設計でよく見られる問題は、値が決して変更されないという仮定だが、後でそれが間違った仮定であることが判明することがある。郵便番号、免許証やその他の識別番号、その他多くの識別子は、ある時点では一意で不変のように見えるが、後になって変更しなければならない特殊なケースが発生する。名前ベースのUUIDの「名前」入力として使用される識別子をその後変更すると、データベース構造が無効になる可能性がある。そのようなシナリオでは、名前ベースではないUUIDバージョンを使用することで、問題のフィールドがそのような変更に適応しやすい場所に配置されることが観察される(主キーはこのステートメントから除外される)。一般的なアドバイスとしては、名前ベースのUUIDナチュラルキーを避け、代わりに、このセクションで詳述した前述の問題に基づいて、時間ベースのUUIDサロゲートキーを利用することである。

7. IANA に関する考慮事項

(本文書によって作成されたもの以外の)IANAレジストリにおける[RFC4122]へのすべての参照は、UUIDのためのIANA URN名前空間登録[URNNamespaces]を含め、本文書への参照に置き換えられた。[RFC4122]のセクション4.1.2への参照は、本文書のセクション4を参照するように更新する。

最後に、IANAはセクション7.1及び7.2で規定されているように、UUIDサブタイプと特殊なケースの「名前空間ID値」を <https://www.iana.org/assignments/uuid> で追跡する必要がある。

要求を評価する際、代表専門家は、コミュニティからのフィードバック、参照仕様がどの程度明確に定義されているか、この仕様の要求事項を考慮する必要がある。ベンダー固有、アプリケーション固有、展開固有の値は登録できない。仕様文書は、安定した自由に利用できる方法(理想的にはURLで配置される)で公開する必要があるが、標準である必要はない。代表専門家は登録申請を承認または拒否し、その決定をIANAに伝える。拒否には、説明と、場合によっては、要求を成功させるための提案を含める必要がある。

7.1. IANA UUIDサブタイプのレジストリと登録

本仕様は、一般的に広く使われているUUID標準の「UUIDサブタイプ」レジストリを定義する。

名前 ID サブタイプ バリアント 参考資料
グレゴリオ暦時間ベース 1 version OSF DCE / IETF [RFC4122], RFC 9562
DCEセキュリティ 2 version OSF DCE / IETF [C309], [C311]
MD5名前ベース 3 version OSF DCE / IETF [RFC4122], RFC 9562
ランダム 4 version OSF DCE / IETF [RFC4122], RFC 9562
SHA-1名前ベース 5 version OSF DCE / IETF [RFC4122], RFC 9562
グレゴリオ暦を並べ替え時間ベース 6 version OSF DCE / IETF RFC 9562
Unix時間ベース 7 version OSF DCE / IETF RFC 9562
カスタム 8 version OSF DCE / IETF RFC 9562

表4: IANA UUIDサブタイプ

この表は、[RFC8126]に従って標準化活動によって拡張される可能性がある。

代表専門家向け:

  • 「OSF DCE / IETF」バリアントのサブタイプ「バージョン」の最小値および最大値の「ID」は0~15である。「将来の定義のために予約」または「未使用」と記載されている表1内のバージョンは、適切に定義されるまでは、このIANAレジストリから省略される。

  • 「サブタイプ」列は自由形式のテキストである。ただし、公開時点では、「バージョン」と「ファミリー」のみが、既知のUUIDサブタイプである。「ファミリー」サブタイプは「Apollo NCS」バリアント空間の一部である(両方ともこの仕様の範囲外である)。Microsoftのバリアントにはサブタイプの仕組みが定義されている場合があるが、それは未知であり、この仕様の範囲外である。同様に、最終的な「将来の定義のために予約」バリアントは、将来新しいサブタイプ・ロジックが導入される可能性がある。サブタイプIDは重複することが許可される。つまり、ID「1」は複数のバリアント空間に存在する可能性がある。

  • 「バリアント」列は自由形式のテキストである。ただし、4つの値のうちの1つが含まれる可能性がある。最初の3つは「OSF DCE / IETF」、「Apollo NCS」、「Microsoft」で、最後のバリアント値は「将来の定義のために予約」バリアントに属し、将来的には新しい名前が導入される可能性はある。

7.2. IANA UUID名前空間IDレジストリと登録

本仕様では、広く使われている一般的な名前空間ID値の「UUID名前空間ID」レジストリを定義する。

代表専門家向けの情報を含む、この登録の詳細については、セクション6.6に記載されている。

8. セキュリティに関する考慮事項

実装は、UUIDが推測されにくいと想定すべきではない(SHOULD NOT)。例えば、UUIDをセキュリティ・ケーパビリティ(所有するだけでアクセスが許可される識別子)として使用してはならない(MUST NOT)。乱数ソースに予測可能性が発見された場合、脆弱性が生じる。

実装は、UUIDが他のオブジェクトへの参照をリダイレクトするためにわずかに修正されたかどうかを容易に判断できると想定してはならない(MUST NOT)。人間には、UUIDをチラッと見ただけで、UUIDの完全性を簡単にチェックする能力はない。

MACアドレスはプライバシーに関する固有のセキュリティ・リスクを引き起こすため、UUID内で使用すべきではない(SHOULD NOT)。その代わり、CSPRNGデータは、UUID生成の一意性を保証するのに十分なエントロピーを持つソースから選択される必要がある(SHOULD)。詳細については、セクション6.9と6.10を参照のこと。

UUIDに埋め込まれたタイムスタンプは、攻撃対象領域を非常に小さくする。埋め込みカウンタと組み合わせたタイムスタンプは、特定のUUIDとそれに対応するデータの作成順序を示しが、データ自体やアプリケーション全体については何も定義しない。UUIDが、どのような形であれ、アプリケーション・コンテキスト内のセキュリティ操作で使用するために要求される場合、UUIDv4(セクション5.4)を使用する必要がある(SHOULD)。

MD5のセキュリティに関する考慮事項については[RFC6151]を、SHA-1のセキュリティに関する考慮事項については[RFC6194]を参照のこと。

9. 参考文献

9.1. 引用規格

[C309] X/Open Company Limited, "X/Open DCE: Remote Procedure Call", ISBN 1-85912-041-5, Open CAE Specification C309, August 1994, <https://pubs.opengroup.org/onlinepubs/9696999099/toc.pdf>.

[C311] The Open Group, "DCE 1.1: Authentication and Security Services", Open Group CAE Specification C311, August 1997, <https://pubs.opengroup.org/onlinepubs/9696989899/toc.pdf>.

[FIPS180-4] National Institute of Standards and Technology (NIST), "Secure Hash Standard (SHS)", FIPS PUB 180-4, DOI 10.6028/NIST.FIPS.180-4, August 2015, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf>.

[FIPS202] National Institute of Standards and Technology (NIST), "SHA-3 Standard: Permutation-Based Hash and Extendable- Output Functions", FIPS PUB 202, DOI 10.6028/NIST.FIPS.202, August 2015, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf>.

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC8141] Saint-Andre, P. and J. Klensin, "Uniform Resource Names (URNs)", RFC 8141, DOI 10.17487/RFC8141, April 2017, <https://www.rfc-editor.org/info/rfc8141>.

[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[X667] ITU-T, "Information technology - Open Systems Interconnection - Procedures for the operation of OSI Registration Authorities: Generation and registration of Universally Unique Identifiers (UUIDs) and their use as ASN.1 object identifier components", ISO/IEC 9834-8:2004, ITU-T Recommendation X.667, September 2004.

9.2. 参考規格

[COMBGUID] "Creating sequential GUIDs in C# for MSSQL or PostgreSql", commit 2759820, December 2020, <https://github.com/richardtallent/RT.Comb>.

[CUID] "Collision-resistant ids optimized for horizontal scaling and performance.", commit 215b27b, October 2020, <https://github.com/ericelliott/cuid>.

[Elasticflake] Pearcy, P., "Sequential UUID / Flake ID generator pulled out of elasticsearch common", commit dd71c21, January 2015, <https://github.com/ppearcy/elasticflake>.

[Err1957] RFC Errata, Erratum ID 1957, RFC 4122, <https://www.rfc-editor.org/errata/eid1957>.

[Err3546] RFC Errata, Erratum ID 3546, RFC 4122, <https://www.rfc-editor.org/errata/eid3546>.

[Err4975] RFC Errata, Erratum ID 4975, RFC 4122, <https://www.rfc-editor.org/errata/eid4975>.

[Err4976] RFC Errata, Erratum ID 4976, RFC 4122, <https://www.rfc-editor.org/errata/eid4976>.

[Err5560] RFC Errata, Erratum ID 5560, RFC 4122, <https://www.rfc-editor.org/errata/eid5560>.

[Flake] Boundary, "Flake: A decentralized, k-ordered id generation service in Erlang", commit 15c933a, February 2017, <https://github.com/boundary/flake>.

[FlakeID] "Flake ID Generator", commit fcd6a2f, April 2020, <https://github.com/T-PWK/flake-idgen>.

[IBM_NCS] IBM, "uuid_gen Command (NCS)", March 2023, <https://www.ibm.com/docs/en/aix/7.1?topic=u-uuid-gen-command-ncs>.

[IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic.", IEEE Std 754-2019, DOI 10.1109/IEEESTD.2019.8766229, July 2019, <https://standards.ieee.org/ieee/754/6210/>.

[IEEE802.11bh] IEEE, "IEEE Draft Standard for Information technology-- Telecommunications and information exchange between systems Local and metropolitan area networks--Specific requirements - Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications Amendment: Enhancements for Extremely High Throughput (EHT)", Electronic ISBN 978-1-5044-9520-2, March 2023, <https://standards.ieee.org/ieee/802.11bh/10525/>.

[KSUID] Segment, "K-Sortable Globally Unique IDs", commit bf376a7, July 2020, <https://github.com/segmentio/ksuid>.

[LexicalUUID] Twitter, "Cassie", commit f6da4e0, November 2012, <https://github.com/twitter-archive/cassie>.

[Microsoft] Microsoft, "2.3.4.3 GUID - Curly Braced String Representation", April 2023, <https://learn.microsoft.com/ en-us/openspecs/windows_protocols/ms-dtyp/222af2d3-5c00-4899-bc87-ed4c6515e80d>.

[MS_COM_GUID] Chen, R., "Why does COM express GUIDs in a mix of big- endian and little-endian? Why can't it just pick a side and stick with it?", September 2022, <https://devblogs.microsoft.com/oldnewthing/20220928-00/?p=107221>.

[ObjectID] MongoDB, "ObjectId", <https://docs.mongodb.com/manual/reference/method/ObjectId/>.

[orderedUuid] Cabrera, I. B., "Laravel: The mysterious "Ordered UUID"", January 2020, <https://itnext.io/laravel-the-mysterious-ordered-uuid-29e7500b4f8>.

[pushID] Lehenbauer, M., "The 2^120 Ways to Ensure Unique Identifiers", February 2015, <https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html>.

[Python] Python, "uuid - UUID objects according to RFC 4122", <https://docs.python.org/3/library/uuid.html>.

[RANDOM] Occil, P., "Random Number Generator Recommendations for Applications", June 2023, <https://peteroupc.github.io/random.html>.

[RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, DOI 10.17487/RFC1321, April 1992, <https://www.rfc-editor.org/info/rfc1321>.

[RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform Resource Locators (URL)", RFC 1738, DOI 10.17487/RFC1738, December 1994, <https://www.rfc-editor.org/info/rfc1738>.

[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC4122] Leach, P., Mealling, M., and R. Salz, "A Universally Unique IDentifier (UUID) URN Namespace", RFC 4122, DOI 10.17487/RFC4122, July 2005, <https://www.rfc-editor.org/info/rfc4122>.

[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC6151] Turner, S. and L. Chen, "Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms", RFC 6151, DOI 10.17487/RFC6151, March 2011, <https://www.rfc-editor.org/info/rfc6151>.

[RFC6194] Polk, T., Chen, L., Turner, S., and P. Hoffman, "Security Considerations for the SHA-0 and SHA-1 Message-Digest Algorithms", RFC 6194, DOI 10.17487/RFC6194, March 2011, <https://www.rfc-editor.org/info/rfc6194>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8937] Cremers, C., Garratt, L., Smyshlyaev, S., Sullivan, N., and C. Wood, "Randomness Improvements for Security Protocols", RFC 8937, DOI 10.17487/RFC8937, October 2020, <https://www.rfc-editor.org/info/rfc8937>.

[RFC9499] Hoffman, P. and K. Fujiwara, "DNS Terminology", BCP 219, RFC 9499, DOI 10.17487/RFC9499, March 2024, <https://www.rfc-editor.org/info/rfc9499>.

[RFC9542] Eastlake 3rd, D., Abley, J., and Y. Li, "IANA Considerations and IETF Protocol and Documentation Usage for IEEE 802 Parameters", BCP 141, RFC 9542, DOI 10.17487/RFC9542, April 2024, <https://www.rfc-editor.org/info/rfc9542>.

[ShardingID] Instagram Engineering, "Sharding & IDs at Instagram", December 2012, <https://instagram-engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c>.

[SID] "sid : generate sortable identifiers", Commit 660e947, June 2019, <https://github.com/chilts/sid>.

[Snowflake] Twitter, "Snowflake is a network service for generating unique ID numbers at high scale with some simple guarantees.", commit ec40836, May 2014, <https://github.com/twitter-archive/snowflake>.

[Sonyflake] Sony, "A distributed unique ID generator inspired by Twitter's Snowflake", commit 848d664, August 2020, <https://github.com/sony/sonyflake>.

[ULID] "Universally Unique Lexicographically Sortable Identifier", Commit d0c7170, May 2019, <https://github.com/ulid/spec>.

[URNNamespaces] IANA, "Uniform Resource Names (URN) Namespaces", <https://www.iana.org/assignments/urn-namespaces/>.

[X500] ITU-T, "Information technology - Open Systems Interconnection - The Directory: Overview of concepts, models and services", ISO/IEC 9594-1, ITU-T Recommendation X.500, October 2019.

[X660] ITU-T, "Information technology - Procedures for the operation of object identifier registration authorities: General procedures and top arcs of the international object identifier tree", ISO/IEC 9834-1, ITU-T Recommendation X.660, July 2011.

[X680] ITU-T, "Information Technology - Abstract Syntax Notation One (ASN.1) & ASN.1 encoding rules", ISO/IEC 8824-1:2021, ITU-T Recommendation X.680, February 2021.

[XID] "Globally Unique ID Generator", commit efa678f, October 2020, <https://github.com/rs/xid>.

付録A. テストベクタ

UUIDv1とUUIDv6の両方のテストベクタは、同じ60ビットのタイムスタンプ、「0x1EC9414C232AB00 (138648505420000000) Tuesday, February 22, 2022 2:22:22.000000 PM GMT-05:00」を使用する。

UUIDv1とUUIDv6の両方とも、clock_seqnodeで同じ値を使用する。これらはすべてランダム・データで生成されている。ランダム化されたノードでは、セクション6.10に従って、最初のオクテットの最下位ビットは値1に設定される。したがって、開始値「0x9E6BDECED846」が「0x9F6BDECED846」に変更された。

64ビットのUnixタイムスタンプから100ナノ秒のグレゴリオ暦タイムスタンプ値への変換に使われた疑似コードは、参考のために文書に残す。

# Gregorian-to-Unix Offset:
# The number of 100 ns intervals between the
# UUID Epoch 1582-10-15 00:00:00
# and the Unix Epoch 1970-01-01 00:00:00
# Greg_Unix_offset = 0x01b21dd213814000 or 122192928000000000

# Unix 64-bit Nanosecond Timestamp:
# Unix NS: Tuesday, February 22, 2022 2:22:22 PM GMT-05:00
# Unix_64_bit_ns = 0x16D6320C3D4DCC00 or 1645557742000000000

# Unix Nanosecond precision to Gregorian 100-nanosecond intervals
# Greg_100_ns = (Unix_64_bit_ns/100)+Greg_Unix_offset

# Work:
# Greg_100_ns = (1645557742000000000/100)+122192928000000000
# Unix_64_bit_ns = (138648505420000000-122192928000000000)*100

# Final:
# Greg_100_ns = 0x1EC9414C232AB00 or 138648505420000000

図15: テストベクタ・タイムスタンプの擬似コード

A.1. UUIDv1値の例

-------------------------------------------
field      bits value
-------------------------------------------
time_low   32   0xC232AB00
time_mid   16   0x9414
ver         4   0x1
time_high  12   0x1EC
var         2   0b10
clock_seq  14   0b11, 0x3C8
node       48   0x9F6BDECED846
-------------------------------------------
total      128
-------------------------------------------
final: C232AB00-9414-11EC-B3C8-9F6BDECED846

図16: UUIDv1例 テストベクタ

A.2. UUIDv3値の例

DNS名前空間ID値と名前「www.example.com」を使用したMD5計算の詳細を図17に示す。フィールドのマッピングとすべての値を図18に示す。最後に、バージョンとバリアントのビットスワップをさらに詳しく説明するために、図19を参照のこと。

Namespace (DNS):  6ba7b810-9dad-11d1-80b4-00c04fd430c8
Name:             www.example.com
------------------------------------------------------
MD5:              5df418813aed051548a72f4a814cf09e

図17: UUIDv3例 MD5

-------------------------------------------
field     bits value
-------------------------------------------
md5_high  48   0x5df418813aed
ver        4   0x3
md5_mid   12   0x515
var        2   0b10
md5_low   62   0b00, 0x8a72f4a814cf09e
-------------------------------------------
total     128
-------------------------------------------
final: 5df41881-3aed-3515-88a7-2f4a814cf09e

図18: UUIDv3例 テストベクタ

MD5 hex and dash:      5df41881-3aed-0515-48a7-2f4a814cf09e
Ver and Var Overwrite: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Final:                 5df41881-3aed-3515-88a7-2f4a814cf09e                 

図19: UUIDv3例 Ver/Varビットスワップ

A.3. UUIDv4値の例

このUUIDv4の例は、16バイトのランダムデータを生成して919108F752D133205BACF847DB4148A8となる16進数値を生成することで作成した。これを図20に示すようにフィールドに埋めるために使用する。

最後に、バージョンとバリアントのビットスワップをさらに詳しく説明するために、図21を参照のこと。

-------------------------------------------
field     bits value
-------------------------------------------
random_a  48   0x919108f752d1
ver        4   0x4
random_b  12   0x320
var        2   0b10
random_c  62   0b01, 0xbacf847db4148a8
-------------------------------------------
total     128
-------------------------------------------
final: 919108f7-52d1-4320-9bac-f847db4148a8

図20: UUIDv4例 テストベクタ

Random hex:            919108f752d133205bacf847db4148a8
Random hex and dash:   919108f7-52d1-3320-5bac-f847db4148a8
Ver and Var Overwrite: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Final:                 919108f7-52d1-4320-9bac-f847db4148a8

図21: UUIDv4例 Ver/Varビットスワップ

A.4. UUIDv5値の例

DNS 名前空間ID値と名前「www.example.com」を使用したSHA-1計算フォームの詳細を図22に示す。フィールドのマッピングとすべての値を図23に示す。最後に、バージョンとバリアントのビットスワップとSHA-1値の未使用/破棄部分をさらに詳しく説明するために、図 24を参照のこと。

Namespace (DNS):  6ba7b810-9dad-11d1-80b4-00c04fd430c8
Name:             www.example.com
----------------------------------------------------------
SHA-1:            2ed6657de927468b55e12665a8aea6a22dee3e35

図22: UUIDv5例 SHA-1

-------------------------------------------
field      bits value
-------------------------------------------
sha1_high  48   0x2ed6657de927
ver         4   0x5
sha1_mid   12   0x68b
var         2   0b10
sha1_low   62   0b01, 0x5e12665a8aea6a2
-------------------------------------------
total      128
-------------------------------------------
final: 2ed6657d-e927-568b-95e1-2665a8aea6a2                    

図23: UUIDv5例 テストベクタ

SHA-1 hex and dash:    2ed6657d-e927-468b-55e1-2665a8aea6a2-2dee3e35
Ver and Var Overwrite: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Final:                 2ed6657d-e927-568b-95e1-2665a8aea6a2
Discarded:                                                 -2dee3e35

図24: UUIDv5例 Ver/Varビットスワップと破棄されたSHA-1セグメント

A.5. UUIDv6値の例

-------------------------------------------
field       bits value
-------------------------------------------
time_high   32   0x1EC9414C
time_mid    16   0x232A
ver          4   0x6
time_high   12   0xB00
var          2   0b10
clock_seq   14   0b11, 0x3C8
node        48   0x9F6BDECED846
-------------------------------------------
total       128
-------------------------------------------
final: 1EC9414C-232A-6B00-B3C8-9F6BDECED846

図25: UUIDv6例 テストベクタ

A.6. UUIDv7 値の例

このUUIDv7テストベクタの例では、最初の48ビットを埋めるために、ミリ秒精度のよく知られたUnixエポック・タイムスタンプを利用している。

rand_arand_bにはランダムなデータが入る。

タイムスタンプは「Tuesday, February 22, 2022 2:22:22.00 PM GMT-05:00」で、0x017F22E279B0または1645557742000として表される。

-------------------------------------------
field       bits value
-------------------------------------------
unix_ts_ms  48   0x017F22E279B0
ver          4   0x7
rand_a      12   0xCC3
var          2   0b10
rand_b      62   0b01, 0x8C4DC0C0C07398F
-------------------------------------------
total       128
-------------------------------------------
final: 017F22E2-79B0-7CC3-98C4-DC0C0C07398F

図26: UUIDv7例 テストベクタ

付録B. 実例

以下のセクションは、UUIDv8(セクション5.8)をカスタムおよび/または実験的なアプリケーション・ベースのロジックにどのように使用できるかを示す、実例が含まれている。以下の例は、本文書の他のアルゴリズムが受けたような厳密なテスト、プロトタイピング、フィードバック・ループを経ていない。著者らは実装者がこのセクションで定義されている項目を使用するのではなく、独自のUUIDv8アルゴリズムを作成することを推奨する。

B.1. UUIDv8値の例 (時間ベース)

このUUIDv8テストベクタの例では、10ナノ秒精度のよく知られた64ビットUnixエポック・タイムスタンプを利用し、最下位右端ビットを切り捨て、custom_acustom_bの最初の60ビットを埋める。この2つのセグメント間のバージョン・ビットをバージョン値8に設定する。

バリアント・ビットが設定され、最後のセグメントcustom_cにはランダムなデータが入る。

タイムスタンプは「Tuesday, February 22, 2022 2:22:22.000000 PM GMT-05:00」で、0x2489E9AD2EE2E00または164555774200000000(10ナノ秒ステップ)で表される。

-------------------------------------------
field     bits value
-------------------------------------------
custom_a  48   0x2489E9AD2EE2
ver        4   0x8
custom_b  12   0xE00
var        2   0b10
custom_c  62   0b00, 0xEC932D5F69181C0
-------------------------------------------
total     128
-------------------------------------------
final: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0

図27: UUIDv8例 時間ベースの実例

B.2. UUIDv8値の例 (名前ベース)

セクション5.5に従って、最新のハッシュ・アルゴリズムを使用する名前ベースのUUIDは、UUIDv8空間内で作成しなければならない(MUST)。これらは、SHA-256やSHA-512([FIPS180-4]で定義)、SHA-3またはSHAKE([FIPS202]で定義)、あるいはまだ定義されていないアルゴリズムのような新しいハッシュ・アルゴリズムを利用してもよい(MAY)。

付録 A.4のSHA-1計算のSHA-256バージョンをどのように実現できるかを説明する例として図28に詳しく説明する。このセクションでの名前ベースのUUIDv8値の生成は、SHA-1の代わりにSHA-256を使用する点が異なるだけで、セクション5.5で定義されているのと同じロジックに従う。

図29にフィールド・マッピングとすべての値を示す。最後に、バージョンとバリアントのビットスワップとSHA-256値の未使用/破棄部分をさらに詳しく説明するために、図30を参照のこと。SHAKEで見られるような任意のサイズの出力を生成するハッシュ・アルゴリズムの重要な注意点は、出力ハッシュは128ビット以上でなければならない(MUST)。

Namespace (DNS):       6ba7b810-9dad-11d1-80b4-00c04fd430c8
Name:                  www.example.com
----------------------------------------------------------------
SHA-256:
5c146b143c524afd938a375d0df1fbf6fe12a66b645f72f6158759387e51f3c8

図28: UUIDv8例 SHA256

-------------------------------------------
field     bits value
-------------------------------------------
custom_a  48   0x5c146b143c52
ver        4   0x8
custom_b  12   0xafd
var        2   0b10
custom_c  62   0b00, 0x38a375d0df1fbf6
-------------------------------------------
total     128
-------------------------------------------
final: 5c146b14-3c52-8afd-938a-375d0df1fbf6

図29: UUIDv8例 名前ベースのSHA-256の実例

A: 5c146b14-3c52-4afd-938a-375d0df1fbf6-fe12a66b645f72f6158759387e51f3c8
B: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
C: 5c146b14-3c52-8afd-938a-375d0df1fbf6
D:                                     -fe12a66b645f72f6158759387e51f3c8

図30: UUIDv8例 Ver/Varビットスワップと破棄されたSHA-256セグメント

図30を検証する:

  • A行は、ダッシュを挿入した16進数値として、完全なSHA-256を列挙している。

  • B行は、バージョンとバリアントの16進数の位置を列挙しており、上書きする必要がある。

  • C行は、バージョンとバリアントが上書きされた後の最終的な値を列挙している。

  • D行は、元のSHA-256の計算で破棄された残りの値を列挙している。

謝辞

リッチ・ザルツ、マイケル・ミーリング、ベン・キャンベル、ベン・ラムジー、ファビオ・リマ、ゴンサロ・サルゲイロ、マーティン・トムソン、マレー・S・クシェラウィ、リック・ファン・ライン、ロブ・ウィルトン、ショーン・レナード、セオドア・Y・ツォー、 ロバート・キーファー、セルゲイ・プロホレンコ、LiosKの貢献に感謝する。

また、IETFコミュニティおよびGitHub上で、本文書の作成に至った議論に貢献してくれたすべての人々も同様である。

本文書は、UUIDに関するOSF DCE仕様([C309]の付録A)を大いに参考にしている。テッド・ツォーの有益なコメントに感謝する。

また、ラルフ・S・エンゲルスシャル、ジョン・ラーマス、ポール・ソープの入念な読み合わせとビットの微調整にも感謝している。ラーマス教授は、ISO/IECとの調整においても貴重な存在だった。

著者のアドレス

カイザー・R・デイビス
Cisco Systems
メール: kydavis@cisco.com

ブラッド・G・ピーボディ
Uncloud
メール: brad@peabody.io

ポール・J・リーチ
ワシントン大学
メール: pjl7@uw.edu

更新履歴

  • 2024.5.13
  • 2024.5.25: 本文書の位置付け
  • 2024.5.28: 不透明に扱うこと、UUIDの歴史
  • 2024.6.7: Errataを追加
GitHubで編集を提案

Discussion