次の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でこれを回避するより良い、またはより安全な方法はありますか?
いいえ、完全に安全ではありません。各コマンドを見てみましょう:
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。