UUID & ランダムトークン生成

UUID v4とランダムHEXトークンを生成し、手元のUUIDがどのバージョンかも確認できます。入力も結果もブラウザの外へ出ません。

UUID v4

UUIDの判定

ランダムHEXトークン

UUIDの構造

UUID(Universally Unique Identifier)は128ビットの識別子で、中央で番号を割り振らなくてもレコードやファイルに一意な名前を付けられます。 通常は16進数32桁を8-4-4-4-12の形でハイフンでつなぎ、36文字で書きます。現行の規格は2024年5月発行のRFC 9562で、従来のRFC 4122を置き換えました。 どのバージョンでも、3番目のグループの先頭の1桁がバージョン、4番目のグループの先頭の1桁がバリアント(標準では8・9・a・bのいずれか。上位2ビットが 10)を表します。xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx の「4」がv4を示し、yは8・9・a・bのどれかです。

v4ではこの6ビットを固定し、残りの122ビットを乱数で埋めます。ほかに、時刻とノードから作るv1、名前空間と名前のハッシュ(MD5・SHA-1)で同じ入力から同じ値になるv3・v5、 先頭にUnixミリ秒の時刻を持ち作成順に並ぶv7などがあります。全ビット0のNil UUIDと全ビット1のMax UUIDも特別な値として定義されています。

このツールのv4の作り方

ブラウザ標準の crypto.randomUUID() を呼び出します。これは暗号学的に安全な乱数源から作ったUUID v4を返す関数で、HTTPSまたはlocalhostのような安全なコンテキストでのみ使えます。 使えない環境では crypto.getRandomValues() で16バイトの乱数を取り、6バイト目の上位4ビットを 0100(v4)、8バイト目の上位2ビットを 10(標準バリアント)に置き換えて、8-4-4-4-12の形に整えます。 どちらの場合も乱数の源はMath.random()ではありません。予測されやすいMath.random()は、推測されては困る識別子には向かないためです。個数・大文字・ハイフン・波括弧のオプションは表記を変えるだけで、値は変わりません。

衝突確率は計算で見る

ランダムなビット数をbとして、n個のうちどれかが重複する確率は、誕生日問題の近似式 p ≈ n² / (2 · 2b) で求められます(pが小さい間だけ有効)。v4はb = 122で、2122は約5.3 × 10³⁶です。

生成数 n重複の確率 p
1,000,0009.4 × 10⁻²⁶
1,000,000,0009.4 × 10⁻²⁰
1,000,000,000,0009.4 × 10⁻¹⁴
1,000,000,000,000,0009.4 × 10⁻⁸

10億個作っても確率は約9.4 × 10⁻²⁰です。確率が50%に達するには約2.7 × 10¹⁸個が必要で、毎秒10億個を作り続けても約86年かかります。 10億分の1以下に抑えられる上限は約1.0 × 10¹⁴個です。ただしこれは乱数源が一様で予測不能であることが前提です。重複が現実に起きるのは、弱い乱数やクローンされた仮想マシン、値を使い回すバグが原因で、計算上の確率が理由ではありません。 そのため、クライアントが作るIDを保存する列にはデータベースでUNIQUE制約を付けてください。

データベースの主キーに使うとき

乱数のv4はどこでも調整なしに作れて便利ですが、順序付きインデックスでは挿入位置が分散し、ページ分割が増えます。連番や時刻順のIDは末尾に追記されるだけで済みます。時刻順のv7はこの問題を和らげますが、作成時刻が値に現れ、このツールが作るのはv4だけです。 保存形式も重要で、36文字の文字列は36バイト、専用のuuid型や16バイトのバイナリなら16バイトです。10億行なら1コピーあたり20GBの差になり、エンジンによっては二次インデックスにも主キーが複製されます。可能なら専用の型を使いましょう。

計算例

例1(読み取り)。 f47ac10b-58cc-4372-a567-0e02b2c3d479 の3番目のグループは4で始まるのでv4、4番目のグループはa(2進で1010)で始まり上位2ビットが10なので標準バリアントです。上の判定欄に貼ると同じ結果が出ます。 固定されるのは4+2ビットなので、乱数部は 128 − 6 = 122ビットです。

例2(トークン)。 nバイトのHEXトークンは文字数が2n、ビット数が8nです。16バイトは32文字・128ビット、32バイトは64文字・256ビットなので、16バイトのトークンはv4(122ビット)より探索空間がわずかに大きく、形式にも縛られません。

よくある誤解と注意点

HEXトークンを使う場面

APIキー、セッションID、招待リンク、CSRFトークンなど、推測されては困る値に使います。crypto.getRandomValues()で得たバイトを1バイトあたり16進2文字で表します。 利用者には一度だけ見せ、保存はハッシュにするのが安全です。ハッシュの確認にはハッシュ生成ツール、人が入力するパスワードにはパスワード生成ツール、UUIDの形式を検証する正規表現の試験には正規表現テスターが使えます。

よくある質問

生成した値はサーバーに送られたり保存されたりしますか?

いいえ。ブラウザのWeb Crypto APIで作られ、送信も保存もされません。ページを再読み込みすると別の値になります。

UUIDが重複することはありますか?

理論上はゼロではありませんが、v4は122ビットの乱数空間なので、10億個でも上の近似式で約9.4 × 10⁻²⁰です。実際のリスクは乱数源の質にあるため、重要な列にはUNIQUE制約を付けましょう。

UUIDとGUIDは違うものですか?

同じ128ビット形式で、GUIDはMicrosoft系での呼び名です。バイト列を直接やり取りする場合のみ、バイト順に注意が必要です。

ハイフンを外したり大文字にしても同じUUIDですか?

同じです。値の本体は16進数32桁で、ハイフンや波括弧は表記上の装飾、大文字小文字も意味は変わりません。保存形式を1つに決めて、比較前にそろえてください。

APIキーにはUUIDとHEXトークンのどちらが向きますか?

HEXトークンです。UUIDは一意性のための識別子で秘密向けではなく、形式が決まっていて乱数部も122ビットしかありません。UUIDは名前付け、トークンは認証に使い分けましょう。

関連ツール