web-dev-qa-db-ja.com

/ dev / randomから読み取ってもデータは生成されません

コマンドをよく使う

cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' | head --bytes 32

疑似ランダムパスワードを生成します。これは/dev/randomでは機能しません。

具体的には

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t 'は出力を生成します
  • cat /dev/random | strings --bytes 1は出力を生成します
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t 'しない出力を生成する

注:/dev/randomを使用する場合、エントロピーを生成するために、マウスを小刻みに動かすか、キー(Ctrl、Shiftなど)を押す必要があります。

最後の例が機能しないのはなぜですか?trには、/dev/urandomがすぐにいっぱいになるが/dev/randomができないような大きな内部バッファがありますか?

追伸CentOS 6.5を使用しています

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014
19
Aaron J Lang

最終的にはそうなります。

に:

_cat /dev/random | strings --bytes 1 | tr -d '\n\t '
_

catは決してバッファリングしませんが、ここでは連結するものがないため、とにかく不要です。

_< /dev/random strings --bytes 1 | tr -d '\n\t '
_

stringsただし、その出力はもはやターミナルではないので、出力はターミナルに送られるときlinesとは対照的に、(4または8kBのような)ブロックによって出力をバッファリングします。

そのため、出力する4kBに相当する文字が蓄積された場合にのみstdoutへの書き込みが開始され、_/dev/random_でしばらく時間がかかります。

tr出力はターミナルに送信されるため(ターミナルのシェルプロンプトで実行している場合)、出力は行ごとにバッファーされます。 _\n_を削除しているので、完全な行が書き込まれることはないため、代わりに、完全なブロックが蓄積されるとすぐに書き込みます(出力が端末に送信されない場合など)。 。

したがって、trは、stringsが_/dev/random_から十分に読み取って8kB(2ブロックの可能性により多く)のデータを書き込むまで、何も書き込まない可能性があります(最初のブロックがおそらくいくつかの改行、タブ、またはスペース文字が含まれています)。

このシステムで試してみると、_/dev/random_から毎秒平均3バイトを取得できます(_/dev/urandom_の12MiBとは対照的)。したがって、最良のシナリオ(最初の4096バイト) _/dev/random_はすべて印刷可能なものです)、trが何かを出力し始める22分前に話しています。しかし、それは数時間になる可能性が高くなります(簡単なテストでは、1〜2ブロックの読み取りごとにstringsがブロックを書き込むことがわかります。出力ブロックには改行文字の約30%が含まれているので、 trが4096文字を出力する前に、少なくとも3ブロックを読み取る必要があります)。

それを回避するには、次のようにします。

_< /dev/random stdbuf -o0 strings --bytes 1 | stdbuf -o0 tr -d '\n\t '
_

stdbufは、LD_PRELOADトリックを介してコマンドのstdioバッファリングを変更するGNUコマンド(一部のBSDにもあります)です。

stringsの代わりに、_tr -cd '[:graph:]'_を使用して、タブ、改行、スペースを除外することもできます。

ロケールをCに固定して、UTF-8文字による将来の予期せぬ事態を回避することもできます。

27

多くのセキュリティアプリケーションで乱数を生成するには、十分なエントロピーが必要です。エントロピーは、ランダム性がどれほど予測不可能であるかを測定します。確定的プロセッサはエントロピーを生成できないため、エントロピーは、非確定的動作のハードウェアコンポーネントから、またはユーザーのアクションのタイミング(マウスを揺らす場所など)を再現するのが十分に難しい他の要因から、外部から取得する必要があります入って来る)。十分なエントロピーが利用可能になると、暗号を使用して、事実上無制限の乱数ストリームを生成できます。

Linuxは、エントロピーをプールに蓄積し、次に暗号化を使用して、/dev/random/dev/urandomの両方を通じて、許容可能な乱数を生成します。違いは、/dev/randomは非常に保守的なエントロピー計算を適用して、生成するすべてのバイトのプール内のエントロピーの見積もりを削減するのに対し、/dev/urandomはプール内のエントロピーの量に関係しないことです。 。

プール内のエントロピーの推定値が低すぎる場合、/dev/randomは、さらにエントロピーが蓄積されるまでブロックします。これにより、/dev/randomが出力を生成できる速度が大幅に低下する可能性があります。これはあなたがここで観察しているものです。 trとは関係ありません。しかしstringsはバッファリングで出力を読み取るため、少なくとも1バイトの入力を生成するためだけに/dev/randomからバッファー全体(数KB)を読み取る必要があります。

/dev/urandomは、暗号化キーの生成に完全に受け入れられます 。なぜなら、エントロピーは実際には知覚可能な方法で減少しないためです。 (ユニバースが存在するよりも長くマシンを実行し続ける場合、これらの考慮事項を無視することはできませんが、それ以外の場合は問題ありません。)/dev/urandomが適切でないケースは1つだけです。エントロピーを生成する時間がまだない新しくインストールされたシステム、または読み取り専用メディアからブートする新しくブートされたシステム。

ブートチェーンからstringsを削除すると、おそらくプロセスがスピードアップします。 trの下では、印刷されない文字がフィルタリングされます。

</dev/random LC_ALL=C tr -dc '!-~'

しかし、/dev/urandom hereを使用できますが、蓄積する時間がなかったシステムでパスワードを生成しないように注意する必要があります。十分なエントロピー。 Linuxのエントロピープールのレベルは/proc/sys/kernel/random/entropy_availで確認できます(/dev/randomを使用する場合、このファイルの数値は控えめなものになる可能性があります)。

高品質の(疑似)乱数を取得するには_/dev/urandom_を使用し、本当に予測できない乱数が絶対に必要な場合にのみ_/dev/random_を使用する必要があります。 NSAのリソースを下回る攻撃者はvery _/dev/urandom_を解読するのに苦労します(そして ゴムホース暗号 を忘れないでください)。カーネルは、バッファを「本当にランダムな」バイトで満たします。これが_/dev/random_が提供するものです。悲しいことに、それらが生成されるレートは低いため、_/dev/random_から多くを読み取るwillランダム性を待っているストール。

random.org またはその password generator を使用することを検討するかもしれません。 このページ コマンドラインのいくつかのヒント(すべてをお勧めするわけではありませんが、アイデアが得られるはずです)、またはmkpasswd(1)(以下Fedora 19は_expect-5.45-8.fc19.x86_64_)の一部です。

1
vonbrand