一般的ではないパッケージをインストールせずに、暗号学的に強力な疑似ランダムデータの高速ストリームを生成する最良の方法は何ですか?/dev/urandomからの描画は遅すぎます。
私は「ワイプ」マンページを読むことからアイデアがありました:
新鮮なRC6アルゴリズムをPRNGとして使用します。 RC6は128ビットシードでキー化され、次に、ヌルブロックが繰り返し暗号化されて、擬似ランダムストリームが取得されます。
単一のキーのみでnullブロックを暗号化することは、特に大量の疑似ランダムデータが必要な場合は、おそらく最善のアイデアではないため、bashでこれをすばやく作成しました。
while dd if=/dev/zero bs=$(shuf -n 1 -i 1024-67108864) count=1 2>/dev/null | openssl aes-256-cbc -nosalt -k "$(head -c 32 < /dev/random)"; do :; done > [whateverneedsrandomness]
これは、ランダムな32バイトのシードでゼロのストリームを暗号化します。ストリームは平均32 MBごとに再シードされます(範囲は1 KBから64 MBの間で、1バイトの解像度です)。再シード間隔はランダムです。これは、新しいキーがどこで使用されているか誰にも推測されないようにするためです。 CTRは一定のストリームにのみ有効であると読んだため、CTRの代わりにCBCを意図的にブロックモードとして選択しました。非常に限られた暗号の知識により、常に再起動する繰り返しカウンターは、 「ストリーム」の長さが数MBになるのは良い考えですが、確かにはわかりません。
Opensslから出るストリームが完全に暗号化されているかどうかが心配です。入力がブロックサイズで割り切れない場合、opensslは余分なデータを空白のままにしますか(結果のストリーム全体に散在する0の「ギャップ」を残します)? パディング はそれと何か関係がありますか?
だから私の質問は、これは高速ランダムデータを作成する良い方法ですか?また、間違ったブロックモードを使用するなど、見落とし/見落としなどはありますか?
編集:自明性は盲目でしたので、見逃しました。 OpenSSLはすでに、マシンの/dev/urandom
でシードされた独自の内部PRNGへのインターフェイスを提供していますが、独自の暗号で拡張しています。これを行うだけです:
openssl Rand 10000000
1000万の疑似ランダムバイトを生成します。私のラップトップでは、これは/dev/urandom
の約3倍、つまり11 MByte/sほど速いようです。これが十分に速くない場合は、読み進めてください。
元の応答:
それは本当に関連するハードウェアとコンテキストに依存します。 bashスクリプト/dev/urandom
とOpenSSLについて話しているので、次のように考えています。
実際、独自のCコードを記述できる場合、最良のオプションは、CTRモードで AES-NI 命令を使用するAES暗号化(これらの命令を提供する最近のPCで)、または専用のストリーム暗号です。 (例 these )。 2.4 GHz Core2 CPUでは、Sosemanukから700 MByte/sの疑似ランダムバイトを取得できました。今後は、スクリプトに限定されると思います。
OpenSSL暗号化の使用は悪い考えではありませんが、詳細は次のとおりです。
/dev/urandom
ではなく/dev/random
を使用してください。 /dev/urandom
実装の誤解された偏執狂的なクォームにもかかわらず、/dev/random
は暗号化に適しています(OSブートスクリプトは内部PRNGが適切にシードされることを保証します)。一方、/dev/random
はブロックする可能性があるため、本当に遅くなる(ブロックされたプロセスよりも遅くなることはない)。bash
は文字列を使用します。 /dev/random
および/dev/urandom
は、値0のバイトを含むbytesを返します。これにより、人工的にキーが切り捨てられ、セキュリティが低下する場合があります。これは悪いです。代わりに、バイトを16進数でエンコードし、-K
および-iv
コマンドライン引数をopenssl
でエンコードする必要があります。-K
と-iv
を使用している場合は、そうしません。これにより、次のスクリプトが作成されます。
#!/bin/sh
key=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | md5sum | cut -d' ' -f1)
iv=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | md5sum | cut -d' ' -f1)
dd if=/dev/zero bs=65536 count=8192 2>/dev/null | openssl aes-128-cbc -K $key -iv $iv
呼び出されると、このスクリプトは、暗号化の目的に適した、正確に536870928疑似ランダムバイトのシーケンスを出力します。 bs
パラメータとcount
パラメータは自由に変更してください。ただし、dd
はRAMサイズbs
のバッファを割り当てるため、通常はbs
を小さくしすぎないようにしてください。カーネル(8192から65536は通常、適切な値です)。
ここでは、バイトから16進数への変換の便宜のためにのみMD5を使用しています(MD5の既知の欠点は、この場合のセキュリティにはまったく影響しません)。
このスクリプトは、適切なLinuxインストールで機能します。デフォルトで存在するはずのパッケージのみを使用します。私のそれほど強力ではないラップトップでは、このスクリプトは73 Mバイト/秒の速度で疑似ランダムバイトを生成します。これは悪くはなく、おそらく目的に十分です(それが十分でない場合、おそらくI /に他の問題が発生します。 Oボトルネック)。
ランダムデータソースを頻繁に使い果たしてしまう場合は、 http://www.entropykey.co.uk/ などのハードウェア乱数ジェネレータに投資することをお勧めします。
通常、CPUの乱数ジェネレーターハードウェアによって生成できるランダムデータの量に制限されます。これらのような外部デバイスは、はるかに高速で適切なランダムデータを生成できます。