結論
UUIDはセッションIDに使わない。というか使ってはいけない。
根拠
RFC 4122の6章、セキュリティに関する考慮事項から抜粋した。
最初の1段落のみ抜粋
6 . Security Considerations
Do not assume that UUIDs are hard to guess; they should not be used
as security capabilities (identifiers whose mere possession grants
access), for example. A predictable random number source will
exacerbate the situation.
日本語訳
UUIDで利用される乱数生成器は安全であるとは限りません。
例えば、セキュリティ機能(アクセス許可用の識別子)として使用しないでください。
推測可能な乱数ソースが利用されていた場合アクセス許可用の識別子として機能しません。
元々想定されているユースケース
分散システムにおけるシステム間のバレてもいい一意のID発行をするために開発された。
元々通信の安全性を担保させる場面でのユースケースは考慮されていない。
UUIDv4はだめなのか
生成方法をおさらいしましょう。RFC 4122 4.4章からの抜粋です。
4.4. Algorithms for Creating a UUID from Truly Random or
Pseudo-Random NumbersThe version 4 UUID is meant for generating UUIDs from truly-random or
pseudo-random numbers.The algorithm is as follows:
o Set the two most significant bits (bits 6 and 7) of the
clock_seq_hi_and_reserved to zero and one, respectively.o Set the four most significant bits (bits 12 through 15) of the
time_hi_and_version field to the 4-bit version number from
Section 4.1.3.o Set all the other bits to randomly (or pseudo-randomly) chosen
values.
日本語訳
4.4. 真の乱数または疑似乱数からUUIDを作成するためのアルゴリズム
バージョン4 UUIDは、真の乱数または疑似乱数からUUIDを生成するためのものです。
アルゴリズムは次のとおりです。o clock_seq_hi_and_reservedの上位2ビット(bit 6とbit 7)をそれぞれ0と1に設定します。
o time_hi_and_versionフィールドの上位4ビット(ビット12~15)を、セクション4.1.3の4ビットのバージョン番号に設定します。
o他のすべてのビットをランダム(または擬似ランダム)に選択した値に設定します。
- 6ビットが固定値である
- 擬似乱数でもよい(「安全な乱数であれ」とか、「真の乱数であれ」とは言っていない。)
- 線形合同法でもUUIDの実装上はRFC違反とならない。
セキュリティ機能としてのセッションIDを実装する前に考えるべきこと
- そもそも128bitという幅は、将来的に安全であるのか(5年~10年スパン)
- 計算能力が上がった時、そもそもセッションIDとして耐えられるのか
- そもそも6ビット固定だし、有効なビット幅は122bitなんだよな。
- 耐えられなかった時、耐性を上げるため生成される乱数自体を長くしたり、乱数生成方法を変えられるなど拡張性はあるのか
最低限この2点は考えて採用したほうが良いかもしれない。
そして、UUIDはこれらを自分でコントロールできない(長さも変えられなければ、乱数生成方法を担保することもできない。使ってるライブラリ次第。突然メンテナが発狂して線形合同法でヨシッとか言ってしまうかもしれない)
結局のところ
分散システムで、サーバがセッションを一元管理しないならJWTが良さそう。
一元管理するなら元々セッション管理を行う前提で設計されているフレームワークの機能を使ったりするのが一番お手軽な気がした。
もちろんそういうフレームワークAPIの前提として、「セキュリティを担保する物」であるので、突然メンテナが発狂しても「何してくれてんだ直せ」ってクレームを付けることはできる。
繰り返しにはなるけれど、UUIDの前提はあくまで「分散システムにおいてダブらなければどんな振り方でも良い」なので超小規模な環境が前提のライブラリなら線形合同法でもまぁ良いかとしても文句は言えない。
セキュリティの用途が前提であれば用途に対して安全な生成法(乱数の質や長さ)で適切に生成されたIDでなければならない。