質問のタイトルと本文では、OSがエントロピーを作成する方法(実際にはエントロピーを取得する必要があります)と、このエントロピーから疑似ランダム性を生成する方法の2つの質問をします。違いを説明することから始めます。
ランダム性はどこから来ますか?
乱数ジェネレーター(RNG)には2つのタイプがあります。
- 決定論的ランダムビットジェネレーター(DRBG)またはその組み合わせとも呼ばれる疑似乱数ジェネレーター(PRNG)は、固定サイズの可変内部状態を維持し、その状態からの出力を計算する決定論的アルゴリズムです。
- 「真の」乱数ジェネレーターとも呼ばれるハードウェア乱数ジェネレーター(HRNG)は、物理現象に基づいています。真にランダムであることが知られている情報源はなく、予測可能であることが知られていない情報源のみであるため、「真」は少し誤った名称です。
物理現象のシミュレーションなどの一部のアプリケーションは、統計テストに合格する乱数で満足することができます。暗号化キーの生成などの他のアプリケーションには、より強力なプロパティである予測不能性が必要です。予測不可能性は、セキュリティプロパティであり、統計的プロパティではありません(それだけではありません)。これは、敵が乱数ジェネレーターの出力を推測できないことを意味します。(より正確には、敵がRNG出力の各ビットを推測する確率を測定することにより、RNGの品質を測定できます。確率が1/2とは明らかに異なる場合、RNGは不良です。)
放射能の減衰、バックグラウンドノイズの天体観測、株式市場の変動など、統計的特性に優れたランダムデータを生成する物理現象があります。このような物理的測定には、バイアスされた確率分布を均一な確率分布に変換するための調整(ホワイトニング)が必要です。誰もが知っている物理的な測定値は暗号化には適していません。株式市場の変動はジオハッシュには適しているかもしれませんが、それらを使用して秘密鍵を生成することはできません。
暗号化には秘密が必要です:敵は条件付けに入ったデータを見つけることができてはなりません。ある暗号学的に安全な疑似乱数発生器、その出力に加えて、暗号用途での使用に適しているPRNGアルゴリズム:(CSPRNG)良好な統計的特性を有します。CSPRNGを暗号的に安全にするプロパティの1つは、その出力によって、敵が内部状態を再構築できないことです(CSPRNGによって生成されたビット以外のすべてのビットを知ることは、欠落ビットの検出に役立ちません)。CSPRNGの作成方法は簡単ではありません。プロの暗号作成者から提供されたレシピに従うことができます(標準を使用してください)そのようなHash_DRBG、HMAC_DRBG又はCTR_DRBGからようなアルゴリズム、NIST SP 800-90A)またはANSI X9.31 PRNG。CSPRNGを保護するには、その状態の2つのプロパティが必要です。
- 状態は最初から常に秘密にしておく必要があります(ただし、状態を公開しても過去の出力は表示されません)。
- 状態は線形でなければなりません。RNGは同じ状態から2回起動してはなりません。
乱数ジェネレーターのアーキテクチャ
実際には、ほぼすべての優れた乱数ジェネレーターがCSPRNGと1つ以上のエントロピーソースを組み合わせます。簡単に言えば、エントロピーはデータソースの予測不可能性の尺度です。純粋にハードウェアRNGに基づいて乱数ジェネレーターを作成することは困難です。
- 生の物理データは、確率的データを均一な分布に変換するために、とにかく調整する必要がありそうです。
- ランダム性のソースからの出力は秘密にしておく必要があります。
- エントロピーソースは、需要に比べて遅いことがよくあります。
したがって、オペレーティングシステムのRNGは、ほとんど常に次のように機能します。
- 予測不可能な内部状態を構築するのに十分なエントロピーを蓄積します。
- 累積エントロピーをシードとして、つまり内部状態の初期値として使用して、CSPRNGを実行します。
- オプションで、定期的に追加のエントロピーを内部状態に混合します。(エントロピーは測定可能なレートで「消費」されないため、これは厳密に必要ではありません。システム全体を損なうことなく、RNG状態を漏洩する特定の脅威に対して役立ちます。)
エントロピー収集にはハードウェアへのアクセスが必要であり、エントロピーソースは共有リソースを構成するため、乱数生成サービスはオペレーティングシステムの仕事の一部です。オペレーティングシステムはそれらをアセンブルし、アプリケーションに適した出力を引き出す必要があります。オペレーティングシステムでは、エントロピーソースの擬似ランダム調整が必要です。これは基本的に難しくないため、暗号的にも安全かもしれません(そして、アプリケーションが相互に信頼しないオペレーティングシステムで必要です;完全に協調的なシステムでは、オペレーティングシステムが内部で独自のCSPRNGを実行する必要がありますとにかく提供しませんでした)。
永続ストレージを備えたほとんどのシステムは、起動時にディスクからRNGシードを読み込み(あらゆる種類の永続ストレージの略語として「ディスク」を使用します)、シードから生成された新しい擬似ランダムデータでシードを上書きします。または、そのシードと別のエントロピーソースから生成されたランダムデータで利用できる場合。この方法では、再起動後にエントロピーが利用できない場合でも、前のセッションからのエントロピーが再利用されます。
保存された状態には注意が必要です。状態が線形でなければならないと言ったのを覚えていますか?同じディスク状態から2回起動すると、同じRNG出力が得られます。ご使用の環境でこれが可能であれば、エントロピーの別のソースが必要です。バックアップから復元するとき、または仮想マシンのクローンを作成するときは注意してください。クローンを作成するための1つの手法は、保存されたエントロピーを、予測可能ではあるが一意の環境データ(時間やMACアドレスなど)と混合することです。環境データが予測可能な場合、格納されたVM状態を所有しているユーザーは、フォークされたVMインスタンスのシードを再構築できることに注意してください。
エントロピーソース
エントロピーソースを見つける(そして正しく使用する)ことは、オペレーティングシステムでの乱数生成の最も難しい部分です。利用可能なエントロピーソースは、ハードウェアおよびハードウェアが実行される環境に依存する必要があります。
運がよければ、ハードウェアはエントロピーソースとして使用できる周辺機器を提供します:ハードウェア乱数ジェネレーターは、専用またはサイドパーパスのいずれかです。例えば:
NIST SP800-90Bは、ハードウェアRNGの設計ガイドラインを提供します。ハードウェアRNGの評価は困難です。ハードウェアRNGは通常デリケートな獣であり、注意して使用する必要があります:多くのタイプは、不安定化するためにブート後と読み取りの間に時間が必要であり、多くの場合、温度などの環境条件に敏感です。
Ivy Bridgeアーキテクチャに基づくIntel x86-64プロセッサは、熱ノイズによってシードされたCSPRNGからの出力を提供するRdRand
命令を提供します。ほとんどのスマートフォンプロセッサにはハードウェアエントロピーソースが含まれていますが、Androidは常にそれを使用するとは限りません。
強いエントロピーソースを欠くシステムは、弱いエントロピーソースを組み合わせて、それらが十分であることを望みます(言葉が強すぎることを保証します)。ランダムなマウスの動きはクライアントマシンで人気があり、マウスを動かすように求める特定の暗号化プログラムによるセキュリティショーを見たかもしれません(21世紀のPCオペレーティングシステムでは、アプリケーションが気にすることなくOS はエントロピーを蓄積しますが)。
例を見たい場合は、Linuxを見ることができますが、完璧ではないことに注意してください。特に、/dev/random
ブロックはあまりにも頻繁に(それなぜならブロックに十分なエントロピーはエントロピーの過度に保守的な概念と、使用可能になるまで)、一方では、/dev/urandom
最初の起動時を除いて、ほとんど常に良いですが、それが十分なエントロピーを持っていないを示しません。Linuxには多くのHRNGデバイス用のドライバーがあり、さまざまなデバイス(入力デバイスを含む)およびディスクタイミングからのエントロピーを蓄積します。
(機密)永続ストレージがある場合は、それを使用して、上記のようにブート間でエントロピーを保存できます。最初の起動は、繊細な時間である:システムは、特に、本質的に同じ方法で、工場から出動作量産デバイスに、その時点でかなり予測可能な状態であってもよいです。永続的なストレージを備えた一部の組み込みデバイスは、工場の初期シードでプロビジョニングされます(工場内のコンピューターで実行されるRNGによって生成されます)。仮想サーバー環境では、ホストまたはエントロピーサーバーから仮想マシンをインスタンス化するときに初期エントロピーをプロビジョニングできます。
不正なシードのデバイスは、実際には広範囲に及ぶ問題です。RSA 公開キーの研究では、多くのサーバーとデバイスに、不十分なRNGで生成されたキーが含まれていることがわかりました。OS設計者として、この問題を自分で解決することはできません。最初の起動時にRNGが適切にシードされることを保証するのは、展開チェーンを制御するエンティティの仕事です。OS設計者としてのタスクは、その最初のシードを提供するインターフェイスを含む適切なRNGを提供し、RNGが適切にシードされる前に使用された場合に適切なエラーシグナリングを保証することです。