web-dev-qa-db-ja.com

暗号的に安全な乱数ジェネレーターはどのように機能しますか?

標準の乱数ジェネレーターの仕組みを理解しています。しかし、暗号法を使用する場合、乱数は実際にはランダムでなければなりません。

安全なハッシュを生成するために cosmic white noise を読み取る機器があることは知っていますが、標準のPCにはありません。

暗号的に安全な乱数ジェネレーターは、反復可能なパターンなしでどのように値を取得しますか?

66
Byron Whitlock

暗号化キーの生成に使用する可能性のある暗号的に安全な数のランダムジェネレーターは、他の人が観察できないソースからエントロピー(つまり、予測不可能な入力)を収集することによって機能します。

たとえば、Linuxの/ dev/random(4)は、データを返すハードディスク、キープレス、着信ネットワークパケットなどのソースからのハードウェア割り込みのタイミングの変化から情報を収集します。カーネルが収集したエントロピーの量を過大評価しない限り、このアプローチは安全です。数年前、さまざまなソースからのエントロピーの推定はすべて削減され、はるかに保守的になりました。 Linuxがエントロピーを推定する方法の説明 です。

上記のどれも特に高スループットではありません。/dev/random(4)はおそらく安全ですが、データが安全にランダムであると確信できない場合、データの提供を拒否することにより、そのセキュリティを維持します。たとえば、暗号キーとナンスのlotを生成する場合は、おそらくハードウェアの乱数ジェネレーターに頼ることになるでしょう。

多くの場合、ハードウェアRNGは、同じ速度に近い速度で動作しているが、熱雑音に応じて速度がわずかに変化する一対のオシレーター間の差からサンプリングするように設計されています。正しく覚えていれば、英国のプレミアム債券宝くじに使用されている乱数ジェネレーターERNIEは、このように機能します。

代替スキームには、CCD( lavaRND を参照)、放射性崩壊( hotbits を参照)または大気ノイズ( random.org を参照)でのノイズのサンプリングが含まれますまたは、ステーション以外の場所にチューニングされたAMラジオをサウンドカードに差し込むだけです)。または、コンピューターのユーザーに直接、 狂ったチンパンジーのようにキーボードを叩く 1分間、ボートが浮いているように尋ねることができます。

アンドラスが指摘したように、私は最も一般的なエントロピー収集スキームのいくつかについて話すだけだと考えました。 Thomas Porninの答え および JohannesRösselの答え どちらも、収集されたエントロピーを再度マングリングする方法を説明する上で良い仕事をしています。

109
Richard Barrell

暗号化の目的で必要なのは、ストリームが「一様にランダムなビットと計算上区別できない」ことです。 「計算上」とは、それが本当にランダムである必要はなく、神自身のコンピューターにアクセスすることなく誰にでも見えるように見えることを意味します。

実際には、これは、システムが最初に一連のn真にランダムなビットを収集する必要があることを意味します。 nは、徹底的な検索を阻止するのに十分な大きさでなければなりません。つまり、すべての2 ^ nnビットの組み合わせを試すことは実行不可能です。これは、nが90-or-soより大きい限り、今日の技術に関して達成されますが、暗号作成者はlove 2のべき乗なので、 n = 128を使用します。

これらのnランダムビットは、物理学に関する限り、予測できない「物理的イベント」を収集することによって取得されます。通常、タイミングが使用されます:CPUには1秒あたり数十億回更新されるサイクルカウンターがあり、いくつかのイベントは避けられない量のジッターで発生します(着信ネットワークパケット、マウスの動き、キーストローク...)。システムはこれらのイベントをエンコードし、SHA-256などの暗号的に安全なハッシュ関数を適用することでそれらを「圧縮」します(出力はnビットに切り捨てられます)。ここで重要なのは、物理的なイベントのエンコードに十分なエントロピーがあることです。大まかに言って、上記のイベントは少なくとも2 ^ nの組み合わせを集合的に想定できます。ハッシュ関数は、その定義により、そのエントロピーをn-bit文字列に集中させるのに適しています。

nビットを取得したら、PRNG(擬似乱数生成器)を使用して、必要な数のビットを生成します。 PRNGは、十分に広い未知のn-bitキーで動作すると仮定すると、その出力が一様にランダムなビットと計算上区別できない場合、暗号的に安全であると言われます。 90年代の一般的な選択肢は RC4 でした。これは実装が非常に簡単で、非常に高速です。しかし、それは測定可能なバイアスを持っていることが判明しました。つまり、最初に期待されていたほど見分けがつかなかったのです。 eSTREAMプロジェクト は、PRNG(実際のストリーム暗号は、ほとんどのストリーム暗号がPRNGで構成されているため、出力を暗号化するデータとXORします)の新しいデザインを収集し、それらを文書化することで構成されました、暗号作成者による分析の促進。 eSTREAMポートフォリオには、十分に安全であると見なされた7つのPRNG設計が含まれています(つまり、分析に抵抗し、暗号作成者はwhyに抵抗することをよく理解する傾向があります)。それらのうち、4つは「ソフトウェア用に最適化」されています。幸いなことに、これらの新しいPRNGはRC4よりもはるかに安全であるように見えますが、非常に高速です(ここでは1秒あたり数百メガバイトについて話しています)。それらのうち3つは「無料で使用可能」であり、ソースコードが提供されます。

設計の観点から、PRNGはブロック暗号の要素の多くを再利用します。雪崩とビットの広い内部状態への拡散の同じ概念が使用されます。または、まともなPRNGをブロック暗号から構築できます。ブロック暗号のキーとしてn-bitシーケンスを使用し、カウンターの連続する値を暗号化します( m-bitシーケンス(ブロック暗号でm-bitブロックを使用する場合)。これにより、ブロック暗号が安全であり、生成されたストリームがm * 2 ^(m/2) bits以下である限り、ランダムに計算上区別できないビットの擬似ランダムストリームが生成されます。 (m = 128の場合、これは約3,000億ギガバイトを意味するため、ほとんどの目的に十分な大きさです)。そのような使用法は counter mode(CTR) として知られています。

通常、CTRモードのブロック暗号は、専用のストリーム暗号ほど高速ではありません(ストリーム暗号のポイントは、ブロック暗号の柔軟性を失うことで、パフォーマンスの向上が期待されることです)。ただし、Intelの最新のCPUの1つが AES-NI 命令(基本的にハードウェアでのAES実装であり、CPUに統合されている)を持っている場合、CTRモードのAESは比類なき速度(1秒あたり数ギガバイト)をもたらします。

51
Thomas Pornin

まず、暗号的に安全なPRNG=のポイントはnotであり、完全に予測不可能なシーケンスを生成します。 (多かれ少なかれ)真のランダム性を大量に生成するものが存在しない1 それを不可能にします。

そのため、予測するのが難しいだけに頼ります。ここで「ハード」とは、それまでに必要なものがいずれにせよ時代遅れになるまでに、実行不可能なほど長い時間がかかることを意味します。これに関与する数学的アルゴリズムがいくつかあります。よく知られたCSPRNGを使用して、それらがどのように機能するかを見ると、一目でわかります。

このようなPRNGを構築する最も一般的なバリアントは次のとおりです。

  • (おそらく安全な)擬似ランダムビットストリームを既に出力しているストリーム暗号を使用します。
  • カウンターモードでのブロック暗号の使用

カウンターのハッシュ関数も時々使用されます。ウィキペディアには 詳細 があります。

一般的な要件は、ジェネレータのビットストリームから元の初期化ベクトルを決定することが不可能であり、次のビットを簡単に予測できないことだけです。

初期化に関しては、ほとんどのCSPRNGはシステムで利用可能なさまざまなソースを使用します。ラインノイズ、割り込み、またはシステム内の他のイベントなどの真にランダムなものから、特定のメモリロケーション&cなどの他のものです。初期化ベクトルは、ランダムであり、数学的アルゴリズムに依存しないことが望ましい。 DebianのOpenSSLの実装では、この初期化がしばらく中断され、深刻なセキュリティ問題が発生しました。


1 これには問題もあり、熱ノイズなどは温度によって特性が異なるため、バイアスを除去する際には注意が必要です。ほとんどの場合、バイアスがあり、除去する必要があります。そして、それ自体は些細な作業ではありません。

16
Joey

乱数ジェネレーターを考慮するには、暗号学的に安全、アルゴリズムと以前に生成された(多数の)ビットを知っている敵による攻撃に対して安全である必要があります。これが意味することは、その情報を持っている人は、ジェネレータの隠された内部状態を再構築できず、生成される次のビットが50%を超える精度で予測できることです。

以前の出力ビットから内部状態を再構築することは一般的に簡単なので、通常、通常の疑似乱数ジェネレーターは暗号的に安全ではありません(多くの場合、内部状態全体は直接生成される最後のNビットだけです)。良好な統計特性を持たない乱数ジェネレーターも、内部状態を知らなくても少なくともその出力がパーティで予測可能なため、暗号的に安全ではありません。

そのため、それらがどのように機能するかについては、任意の優れた暗号システムを暗号的に安全な乱数ジェネレーターとして使用できます-暗号システムを使用して「通常の」乱数ジェネレーターの出力を暗号化します。敵は通常の乱数ジェネレータの平文出力を再構築できないため、直接攻撃することはできません。これはやや循環的な定義であり、暗号システムのキーをどのようにキー設定して安全に保つかという疑問を招きます。これはまったく別の問題です。

6
Chris Dodd

各ジェネレーターは独自のシード戦略を使用しますが、ここでは CryptGenRandomに関するWindows APIドキュメント

Microsoft CSPでは、CryptGenRandomは他のセキュリティコンポーネントで使用されるものと同じ乱数ジェネレーターを使用します。これにより、多数のプロセスがシステム全体のシードに貢献できます。 CryptoAPIは、すべてのユーザーに中間ランダムシードを保存します。乱数ジェネレーターのシードを形成するために、呼び出し側アプリケーションは、たとえばマウスまたはキーボードのタイミング入力などのビットを提供します。これらのビットは、保存されたシードとさまざまなシステムデータおよびプロセスIDなどのユーザーデータの両方と結合されますスレッドID、システムクロック、システム時間、システムカウンター、メモリステータス、空きディスククラスター、ハッシュされたユーザー環境ブロック。この結果は、疑似乱数ジェネレーター(PRNG)のシードに使用されます。

Windows Vista Service Pack 1(SP1)以降では、NIST Special Publication 800-90で指定されたPRNGに基づいたAESカウンターモードの実装が使用されます。WindowsVistaでは、Windows Storage Server 2003、およびWindows XPでは、連邦情報処理標準(FIPS)186-2で指定されているPRNGが使用されます。アプリケーションが適切なランダムソースにアクセスできる場合、pbBufferバッファにCryptGenRandomを呼び出す前にいくつかのランダムデータ:CSPはこのデータを使用して、内部シードをさらにランダム化しますCryptGenRandomを呼び出す前にpbBufferバッファーを初期化するステップを省略してもかまいません。

5