/dev/urandom の神話を暴く

長年にわたり、開発者コミュニティではある根強い神話が流布してきました。それは、/dev/urandom は安全ではなく、すべての暗号学的目的には /dev/random を使用すべきであるというものです。この誤解は、Linux の man pages をざっと読んだだけで強化されることが多く、開発者が非ブロッキングデバイスを選択することでセキュリティを犠牲にしていると思い込ませる原因となっています。

実際には、両者の違いはセキュリティというよりも、主に可用性の問題です。Linux カーネルの乱数生成の背後にあるメカニズムを理解すれば、ほとんどすべての実用的な目的において、/dev/urandom は十分であるだけでなく、むしろ推奨されることがわかります。

核心となる誤解:真の乱数 vs. 擬似乱数

多くの開発者は、/dev/random は「真の」乱数(環境ノイズから直接導出されるもの)を提供し、/dev/urandom はより安全性の低い「擬似乱数」を提供すると信じています。これは、Linux カーネルの動作に関する根本的な誤解です。

計算量的セキュリティ vs. 情報理論的セキュリティ

なぜこの違いが神話であるのかを理解するためには、まず 2 つのセキュリティのタイプを区別する必要があります。

  1. 情報理論的セキュリティ: これは「ゴールドスタンダード」であり、無制限の計算能力を持つ攻撃者が暗号を解読できない状態を指します。ワンタイムパッドがその主な例です。これは極端に実用性が低いため、実用的なソフトウェアエンジニアリングではほとんど使用されません。
  2. 計算量的セキュリティ: これは AES、RSA、および楕円曲線暗号で使用されるセキュリティレベルです。これは、解決策が存在する可能性はあるものの、それを見つけるために世界のすべてのコンピュータを使っても宇宙の年齢よりも長い時間がかかるであろうと想定しています。

ほぼすべての暗号ライブラリ (OpenSSL, GnuTLS) やアルゴリズム (AES, RSA) が計算量的セキュリティのみを提供しているため、暗号化のために計算量的に安全なアルゴリズムを使用しながら、シードとして「真の」乱数を要求することは論理的に矛盾しています。もし基礎となるブロック暗号やハッシュ関数が破られていた場合、乱数のソースが最大の懸念事項になることはありません。

Linux RNG の実際の動作原理

/dev/random はエントロピー・プールから直接値を引き出し、プールが空になるとブロックし、一方で /dev/urandom は低品質な PRNG に切り替わる、という一般的な考えがあります。しかし、これは誤りです。

CSPRNG アーキテクチャ

/dev/random/dev/urandom は、どちらも同じ暗号学的に安全な擬似乱数生成器 (CSPRNG) によって供給されています。どちらのデバイスから提供される乱数のビットは、すべてこの CSPRNG を通じて処理されます。

  • Linux 4.8 より前: 両方のデバイスは同じ内部プールと CSPRNG を使用していました。唯一の違いは、カーネルが利用可能なエントロピーの推定値が一定のしきい値を下回った場合に、/dev/random がブロックすることでした。
  • Linux 4.8 以降: アーキテクチャは進化しましたが、根本的な原理は変わりません。/dev/urandom は、エントロピー・プールによってシードされた CSPRNG から出力を提供します。

重要なのは、「エントロピー・カウント」は正確な測定値ではなく、あくまで推定値であるということです。この推定値は保守的であったり不正確であったりする場合があるため、/dev/random でブロックすることは、実際に「より高い」セキュリティを保証するものではなく、単にシステムが待機することを保証するだけです。

ブロッキングの危険性

知覚されたセキュリティのために /dev/random を選択することは、重大なリスクをもたらします:可用性です。

/dev/random がブロックすると、アプリケーションが停止します。これは、本番環境において、一時的なセッションキーを待機している間に Web サーバーがハングするなどの、壊滅的な失敗につながる可能性があります。ある開発者がコミュニティの議論で次のように述べています:

"Occasionally page loads would block for seconds... I found a blocked process and sure enough it was blocked on reads to /dev/random."

技術的な失敗だけでなく、ブロッキングは危険な回避策を促します。開発者が、起動しないシステムやハングするサーバーに直面したとき、システムを動かすためだけに random() コールをパッチで除去したり、SSL を完全に無効化したりする誘惑に駆かられることがあります。これは、/dev/urandom を使用する場合よりもはるかに大きなセキュリティ・ホールを生み出します。

「エントロピー不足」への懸念への対処

/dev/random を支持する最も一般的な議論の一つは、/dev/urandom がエントロピーの「枯渇」時に安全ではなくなるというものです。これは、藁人形論法です。

暗号学において、一度 CSPRNG が十分なエントロピー(通常は 256 ビット)でシードされた後は、計算量的に安全な数値のストリームを無期限に生成し続けることができます。カーネルが行う継続的な再シードは、生成器が乱数に「足りなくなっている」からではなく、「自己修復」特性を提供するためです。もし攻撃者が RNG の内部状態をどのようににかして侵害した場合でも、新しいエントロピーの注入によって、最終的に状態は再び予測不能になります。

最終的な結論:/dev/urandom を使用せよ

man pages は、/dev/random を長期保存用のキー(GPG や SSH キーなど)に使用すべきだと示唆していますが、多くの暗号学者は、これを不必要なな予防措置と見なしています。Daniel Bernstein (djb) が指摘したように、256 ビットのシードを予測不能なキーの無限のストリームへと決定論的に拡張できると信じながら、同時に単一のキーで多くのメッセージを安全に暗号化できると信じていることは、矛盾しています。

ベストプラクティスの要約

  • ほとんどすべてのユースケースにおいて: /dev/urandom を使用してください。それは計算量的に安全であり、アプリケーションをブロックしません。
  • システム起動時: Linux の /dev/urandom は、カーネルが十分な初期エントロピーを集める前に数値を生成できる可能性があることに注意してください。ほとんどの現代的なディストリビューションは、シード・ファイルを使用してこれを緩和しています。ただし、仮想化環境(クローンされた VM)では、クローンやチェックポイントからの復元後に RNG を適切にシードしてください。
  • /dev/random は避けてください、情報理論的に安全なアルゴリズムを実装している場合を除外して(そのような実装は、ほぼ確実にしていません)。

Sources