web-dev-qa-db-ja.com

暗号的に安全なランダム文字列を生成するUnixコマンド

次のUnixコマンドは、20文字をランダムに生成するために暗号で安全ですか(a-zA-Z0-9のみ)?

dd if=/dev/urandom bs=256 count=1 2> /dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c20

Unixでこれを回避するより良い、またはより安全な方法はありますか?

8
Justin

いいえ、完全に安全ではありません。各コマンドを見てみましょう:

dd if=/dev/urandom bs=256 count=1 2> /dev/null

これは、暗号化された安全なランダムソースである/dev/urandomから単一の256バイトブロックを読み取ります。問題はここから始まり、この256バイトの制限に関連しています。実際、ここでddを使用する必要さえありません。次のコマンドは、それ自体でブロックデバイスから完全に読み取ることができます。

LC_ALL=C tr -dc 'A-Za-z0-9'

このコマンドは、英数字以外のすべての文字を削除します。 LC_ALL=C文字セットを制限する はプレーンASCIIになり、[:alnum:]は62文字に一致します。記号と印刷できない文字は削除されます。ここでの問題は、このコマンドに256バイトしか与えられないことです。そのため、これらのバイトが英数字で少なすぎるとどうなりますか? trコマンドは、256バイトの入力を喜んで受け取り、数バイトだけがフィルターに一致する場合、数バイトの出力のみを吐き出します。

head -c20

このコマンドは、出力を20バイトに切り捨てるだけです。実際の出力は0から20文字の間で変化します。*統計的には、毎回20文字全体を出力する可能性が最も高いです。


ランダムな英数字を取得する優れた方法は、少ないコマンドで実行できます。これにより、trは必要に応じて/dev/urandomから多くのデータを読み取り、英数字ASCIIを次のコマンドに継続的に吐き出します。headは要求した20バイトを持ち、パイプを閉じ、trがランダムデータの読み取りを停止して終了するようにします。これを使用する必要があります。

LC_ALL=C tr -dc '[:alnum:]' < /dev/urandom | head -c20

これにより、同等の強度のログを持つ20個のランダムな文字が保証されます2(6220)≈119.1ビット。

*リスクは主に理論的なものです。各バイトには(256 = 62)/ 256の確率(約76%)があり、は英数字ではありません。少なくとも256-20バイトが英数字ではない確率は非常に低いですが、ゼロではありません:(194/256)236 ≈3.8×10-28

17
forest