フォーチュナ:妄想乱数ジェネレーター


誰もが、最高の乱数ジェネレーターは、バリ島の野生のビーチの近くの日当たりの良い海岸に立つ、非常に敏感なマイクからの出力をデジタル化するデバイスであることを知っています。

そのようなデバイスをお持ちでない場合は、猫をお願いします。

したがって、常に適切なランダムデータが必要です。 暗号化キー、ソルト、パスワードを生成するために、それは重要ではありません。 重要なのはその品質です。

ある種の大きな数( seed )で初期化した後、それを変更していない優れた暗号PRNGがあるとします。
悪のfsbshnikハッカーが何らかの方法でこの番号を見つけた場合、彼はシーケンス全体を復元できますが、これはまったく良くありません。

したがって、このPRNGを定期的に新しい新しい乱数で定期的に初期化することは論理的です。
良い乱数を生成するには、良い乱数が必要であることがわかります。 円は閉じています。

ノイズ


または、より厳密な言語では、エントロピーのソース。 もちろん、理想的には、物理​​的な性質のものである必要がありますが、ランタイム環境ではそれらも欠落しています。 もちろんそれほど良くはありませんが、それでもなお。
大まかに言って、時変データはノイズの原因になります。 例:


そのようなソースが多ければ多いほど良いです。 一度に1つずつ、かなり少ないデータを表すことができますが、それらの組み合わせにより、私たちが非常に必要とする予測できないデータの多かれ少なかれの良いストリームを提供します。

エントロピーのソースが限られている場合、ほとんど最初からそれを拾うためのレシピがあります:

  1. 無限ループで整数変数をインクリメントする別のスレッドを開始します
  2. 1ミリ秒に1回、最後のビットで別のスレッドを調べて保存します(インクリメントを停止せずに)
  3. 1秒後に、〜1000ビットの良質のエントロピーが得られます

この変数から取り出すビット数は、ミリ秒ごとに変更できます。 エントロピーの品質は、使用するビット数に反比例しますが、その生成速度はビット数が高くなります。
また、1ミリ秒以上待機すると、この配信された最後のビットに対するサイドプロセスの影響がさらに大きくなり、それに応じて「ランダム性」の品質が向上します。

このようなジェネレーターの欠点は明らかです。

しかし、彼はより速い店主のための「種」の役割によく適しています。

フォルトゥナ


それでは、エントロピーのソースは一定数ありますが、それらをどうするのでしょうか?

PRNGを継続的に供給します

このようなPRNGは、連続シードの擬似乱数ジェネレーターと呼ばれます。 そして、仲間のシュナイアーとファーガソンによって作られたフォーチュナは、そのような発電機の優れた代表者です。

2つのレベルで構成されています。
  1. エントロピープール
  2. 内部発電機


最初のものは32個で、カルーセルの原理に従ってエントロピーが追加される32個のハッシュ(任意の選択)のみを表します。 収集期間中のこれらのハッシュはファイナライズされない(つまり、最終値を計算しない)ため、操作中にランダムデータが蓄積されます。

想像しやすくするために、これらの32個のハッシュは当分の間、大きく、大きく、大きなファイルをハッシュし、ハッシュしないように思われます。 太字で強調されていることが重要であり、その後に説明が続きます。

つまり、新しいメッセージ/リクエストがあなたに届いたので、あなたはそれをフォーチュンに与えました、彼女はそれを処理するためにプールNo.1に尋ねました。
上記のジェネレーターによっていくつかのバイトが生成されましたが、そこでも彼女はすでに2番目のバイトにそれらを与えました。
などなど。

これらはハッシュであるため、着信データはすべてメモリに蓄積されるのではなく、内部状態を変更します。 メモリは無駄になりません。

それで、32の恵まれたプールがあります。次は何ですか?

まず、少し

内モンゴル国内発電機


これはブロック暗号(たとえば、AES)とカウンター(数、AESブロックのサイズ。誰かが新しいデータを要求するたびに1ずつ増加します)です。 つまり、カウンタータスクは、単に異なるデータが毎回暗号化されるということです。
いずれにせよ、それらはまだランダムなキーで暗号化されています。
このジェネレーターは、実際には、カウンターをランダムなキーで暗号化することによって取得されるランダムなデータを提供するものです。
同時に、ランダムデータの別の部分を要求するたびに、必要以上のデータを生成し、その余剰分を自分の新しい暗号化キーとして使用します。

つまり、たとえば、ジェネレータに100バイトを要求し、116を生成し、100を与え、ブロック暗号の新しい暗号化キーとして16(128ビット)を使用しました。

同時に、カウンターはリセットされず、後続の各値は異なるキーで暗号化されます。

ミックスで


ジェネレーターの最初の暗号化キー値はどこから来て、プールシステムはどのように機能しますか?

最初は、すべての通常のジェネレーターと同様に、内部ジェネレーターは外部データで初期化されます。 魔法はありません。

ただし、プールで処理されるバイト数(ハッシュ) が1の場合、特定のしきい値(64バイト)を超えると、アルゴリズムの最も美しい部分が開始されます。

フォーチュナはそのようなポジティブな状況を追跡しています。 このカウンターは再シードカウントと呼ばれ、「内部ジェネレーターの暗号化キーを何回変更しましたか?」という意味です。

現在の再シード数は、新しい暗号化キーの生成に参加するプールのセットに依存します

32個のプールがあるため、「それらの関与の程度」は、デュースがカウントカウントに到達した範囲によって異なります。

最初のプールは毎回使用されます。
2番目-Reseedカウントを2で割った余りがゼロの場合
third-Reseedカウントを4で割った余りがゼロの場合
など

つまり、プール番号が大きいほど、使用される回数が少なくなり、エントロピーが長く蓄積されます。 32番目のプールは、2 ^ 32の再シード操作後にのみ戻ります。

リシード


それでは、内部ジェネレーターの暗号化キーを変更します。
最終的に、現在のシードに参加しているプールハッシュを確定します。 参加プール数*ハッシュバイト数のサイズのバイト配列を取得します。
そして、それを内部ジェネレーターに渡します。
ジェネレーターはこれらすべてのバイトを取得し、そこに現在の暗号化キーをミックスします(思い出すように、データ生成後に毎回変更します)。また、すべてをハッシュし、このハッシュを新しい暗号化キーとして使用します。

それだけです

これはどうですか?


プールシステムにより、フォーチュナは自己回復します。 最初に良いデータがプールに到着し、次に悪いデータが到着し始めた場合、良いデータからエントロピーが存在するプールを持つ別のシードが、宇宙の力のバランスを回復します。

また、ランダムデータの生成が依存する以前の情報(同じエントロピー)が失われないことに気付くことができます。 再シードのたびに、新しいキーは現在のキーと混合されますが、置き換えられません。

オプショナル


Fortunaの作成者は、数分ごとに数キロバイトのランダムデータを生成してディスクに保存することをお勧めします。これにより、次回アプリケーションを起動したときに、最初のエントロピーがどこにあるかわからなくなりますが、すぐに良いデータでFortunaを誘います。

それだけです、ご清聴ありがとうございました。

PS多くの実装があります。たとえば、Javaでは、愛されているBouncyCastleが使用されます。
searchcode.com/codesearch/raw/16881031

Source: https://habr.com/ru/post/J197908/


All Articles