UUID Version 3 (MD5名前ベース)
UUID v3を解説。名前空間と名前をMD5でハッシュして決定論的にUUIDを生成する仕組み。v5との違いやトレードオフについても詳しく説明します。
詳細な説明
UUID Version 3はUUID v5のMD5ベース版です。v5と同様に、名前空間UUIDと名前文字列を入力として受け取り、同じ入力に対して常に同じUUIDを生成します。唯一の違いはハッシュ関数で、v3はMD5(128ビット出力)を使用し、v5はSHA-1(160ビット出力)を使用します。
アルゴリズム:
- 名前空間UUIDの16バイトと名前のUTF-8バイトを連結する
- MD5ハッシュを計算する(16バイトの出力)
- バージョンビット(ビット48-51)を
0011(3)に設定する - バリアントビット(ビット64-65)を
10に設定する
MD5はちょうど128ビットを生成し、UUIDも128ビットであるため、ハッシュ出力はわずか6ビット(バージョン4ビット + バリアント2ビット)を上書きするだけでそのままUUIDにマッピングされます。つまり、MD5ハッシュの122ビットが保持されます。v5の場合、SHA-1の出力は160ビットなので、6ビット上書きの前に32ビットが破棄され、利用可能な122ビットにおいてv5のほうがわずかに優れた分布特性を持ちます。
v3とv5のどちらを使うべきか? RFC 9562は明確に「後方互換性が問題にならない場合はSHA-1を推奨する」と述べています。実際には、新しいプロジェクトにはv5を選択してください。v3を使用するのは、既にv3 UUIDを生成しているシステムとの互換性を維持する必要がある場合のみです。同じ名前空間+名前でv3からv5に変更すると、異なるUUIDが生成され、既存の参照が壊れる可能性があります。
MD5の脆弱性に関する文脈: MD5は衝突耐性において暗号学的に破られたと見なされています(異なる入力から同じハッシュを意図的に生成可能)。しかし、UUID v3においてはこの脆弱性は主に理論的なものです。攻撃者は名前空間+名前の連結フォーマット内で特に衝突を見つける必要があり、UUIDはセキュリティ検証には使用されません。とはいえ、v5を使用すればこの理論的な懸念すら排除できます。
コード例:
import uuid
id = uuid.uuid3(uuid.NAMESPACE_DNS, "example.com")
# 9073926b-929f-31c2-abc9-fad77ae3e8eb
import java.util.UUID;
UUID id = UUID.nameUUIDFromBytes("example.com".getBytes());
// Note: Java's nameUUIDFromBytes uses MD5 (v3), no namespace
興味深い詳細: Javaの UUID.nameUUIDFromBytes() メソッドはv3 UUIDのみを生成し、名前空間パラメータを受け付けません。JavaでUUID v5を生成するには、サードパーティライブラリまたは独自の実装が必要です。
ユースケース
UUID v3は、MD5ハッシュを使用して識別子のマッピングを確立したレガシーシステム(古いコンテンツ管理システムやLDAPディレクトリサービスなど)で使用されており、ハッシュアルゴリズムを変更すると既存のUUID参照が壊れてしまいます。