通常の乱数ジェネレータの結果をハッシュすると、暗号的に安全なPRNGが生成されますか?
たとえば、sha1(Rand())
は事実上安全なPRNGでしょうか?
そうでないとしたら、どうやって攻撃しますか?
編集:攻撃によって、生成された一連の値を確認した後に生成される次の値を決定することを想定しています。
注:このようにPRNGを実装することを選択していないことに注意してください。同様の構成要素をコードで見たので、このプロパティの分析に本当に興味があります。私には良い考えのようには見えませんが、それを攻撃する最善の方法を考えるのに苦労しています。
RNGの出力をハッシュすることは、通常、暗号的に安全なRNGを作成するためのコンポーネントですが、魔法ではありません。安っぽいRNGを突然安全にすることはできません。
暗号で保護されたRNGの主要なコンポーネントは、絶対的な予測不可能性です。出力を予測できる場合は、その予測を攻撃の一部として使用できます。ハッシュを介して出力を実行しても、予測可能性は変わりません。
たとえば、私のすごい乱数ジェネレーターが4と7を返すことを交互に繰り返すとしましょう。私のRNGは恐ろしいものであり、あなたは正しいでしょう。しかし、SHA1を介して出力を実行するとします。したがって、SHA1(4)とSHA1(7)を返すことが交互に行われます。 それでもランダムではありません。答えはNOです。
しかし、ハッシュは暗号RNGに役立ちます
一方、エントロピーの真の情報源(たとえば、プルトニウムの ブロック に向けられたガイガーカウンター)があるとしましょう。当社のサンプリング装置により、出力ストリームは57%1と43%0です。結果はまったく予測できないという点でランダムですが、「1」を推測すると、より正確になります。
暗号化ハッシュを介して出力を実行することにより、このバイアスを無効にすることができます。暗号化ハッシュの特性の1つは、入力が何であっても、出力が本質的にバイアスされないことです。明らかに、同じ値を2回ハッシュしないように、入力のサンプルブロックを十分に長く収集する必要があります。しかし、最終的な出力では、1と0の数がほぼ同じになるため、暗号化がより安全になります。
ハッシュは、PRNG Rand()
のように)のセキュリティを高めるのにまったく効果がありません。実際、PRNG=の出力がハッシュ関数の出力よりも大きい場合、セキュリティが低下します。
sha(Rand())
は、基本的に、あいまいさによるセキュリティです。 PRNG outputappearをよりランダムにすることでより安全になると想定していますが、これは誤りです。私はアプローチしません。 暗号的に安全な疑似乱数ジェネレーター(CSPRNGs) の件名、私は件名に精通していないので、任意のRand()
が安全ではない場合、その出力をどのように変更しても、安全性は維持されず、安全性が低下する可能性さえあります。
さて、あなたが PHP/CのRand()
について話している場合、それが暗号的に安全なPRNGになるにはほど遠いことを知ることが重要です。
CodesInChaosが言った のように、Rand()
の最大の問題はそのシードのソースです。 _php-src/ext/standard/php_Rand.h
_ を見ると、シードがどのように生成されるかが明確にわかります
_GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
_
php_combined_lcg()
は 線形合同生成器(LLG) に要約されます。これらのLLGは、暗号化の目的で使用することはお勧めしません。
php_combined_lcg()
によって返される値は、uniqid()
によって返される値と同じです。これは、生成されたファイル名、生成されたパスワード、実装が不十分なトークンなどから漏洩する可能性があります。攻撃者がその値を取得すると、残りは簡単です。 time()
およびgetpid()
の値は、適度に強制されます。
パート1
いいえ、これは安全ではありません。意味的に安全ではありません(Random()は安全ではないため)
ハッシュ関数はその入力のエントロピーを減らすので、それは安全ではないと主張します。つまり、ハッシュ関数は通常、入力と結果のマッピングが1:1未満であり、生の入力自体よりも前の入力と衝突する可能性が高くなります。
この場合、非ランダム入力はより多くのビットで単に「長く」なりますが、ほとんどの暗号化のニーズの基礎であるよりランダムになりません。 (ワンタイムパッドを考えてください)
より良い解決策:
非ランダム入力を「HKDF」にフィードします。 HKDFでは、ソースキー/ PRFが必ずしもランダムではないという前提で、1つのキーから多くのキーを派生させることができます。 HKDFは、ランダムな非秘密の「塩」を使用してランダム性を追加する「抽出してから拡張する」パラダイムを使用します。サンプルHMAC(salt, yourKey)
別のアプローチは、その非ランダム入力をAESや3DESなどのストリーム暗号にフィードし、それをワンタイムパッド(またはそれを使用するつもりであれば何でも)として使用することです。
どうやって攻撃しますか?
これがどのように使用されているかを知る必要があります。この攻撃は、random()に対する攻撃と同じですが、その後にハッシュ遅延が追加されます。この攻撃の単純化されたバージョンは、総当たりする必要がある領域が2 ^ 51よりもはるかに小さく、無視できない可能性があることを認識しています。
ストリーム暗号の例では、SHA1が衝突を引き起こす 281.5テラバイト 未満が暗号化されることを意味し、Rand()関数はそれをさらに削減します。 (誰かがこれを計算する方法を知っているなら、私はその情報に感謝します)
パート2
あなたが疑ったように、PRNGとの関係がない「ハッシュ」の側面に焦点を当てるだけです:
衝突は悪いものです。攻撃者は、選択されたメッセージ攻撃、既存の偽造、または結果のハッシュ出力を使用する場所に応じてさまざまな他の攻撃を実装するなど、多くのことを実行できます。
ハッシュに関しては、衝突は2 ^ n/2演算で発生する可能性が最も高いです(ほぼ出力スペースのサイズの平方根)。
Name Size Attack Operations
SHA-1 160 2^80 (Insecure, don't use)
SHA-256 256 2^128
SHA-512 512 2^256
Whirlpool 512 2^256 (AES based and slowest)
上記のリストは、出力のビット数のみに基づいた(理論上)最良の衝突抵抗です。
ハッシュの現実的なセキュリティは、理論的な最大値よりも安全性が低い可能性が高いことに注意してください。 SHA-1を例にとると、最もよく知られている衝突ファインダーは2 ^ 51のハッシュ評価のみを必要とし、理論的な最良のケースは2 ^ 80です)