Man On a Mission

システム運用屋が、日々のあれこれを記録していくブログです。情報処理技術者試験の話題多し。高度試験の攻略なども。最近はやや歴史づいてます…。

【Linux】/dev/random と /dev/urandomの違い

今日は、簡単ながらLinuxの擬似デバイスファイルである/dev/randomと/dev/urandomについて。

最初にデバイスファイルについて

Linuxでは、キーボードやらハードディスクやらの各種デバイスを「ファイル」として取り扱う仕組みを備えています。
この、デバイスを扱うファイルは、「デバイスファイル」または「スペシャルファイル」と呼ばれ、/dev以下に配置されています。

なんでこんな仕組みにしているかというと、周辺機器などのデバイスの操作を行いやすくするためです。
バイスファイルは、デバイスドライバのインターフェースとして機能します。すなわち、各種デバイスに対する操作を、ファイルに対する操作と同じように利用できるわけです。Linuxの「端末」もデバイスファイルとなってますので、これを使って簡単な例を挙げましょう。

 Linuxでは、「/dev/tty」というデバイスファイルが、現在使っている端末となります。
これに、文字をリダイレクトしてみます。

$ echo 'hell yeah!' > /dev/tty
hell yeah!

すると、端末上にその文字が出力されます。
こういう仕組みによって、デバイスが抽象化され、プログラムが楽になるわけです。

擬似デバイスファイル

さて、これらのデバイスファイルには、実際のハードウェアにはつながってない擬似デバイスファイルというものもあります。
例をあげると、/dev/null、/dev/zero、/dev/randomなどなど。

擬似デバイスファイルを読み書きしても、ハードウェアを操作できるわけではないのですが、代わりに、それぞれが便利な機能を提供してくれます。
例えば、/dev/zeroを読みだすと延々\0を出力したり、/dev/randomからはランダム文字列を取り出せたり。

/dev/random と /dev/urandom

ここから本題。
擬似デバイスファイルには、ランダムな文字列(もう少し正確にいうと擬似乱数文字列)を出力するファイルが2種類あります。
一つは前節でも触れた/dev/random、もうひとつは/dev/urandomです。
これらのファイルからは、延々と乱数文字列を読み出せるので、ddコマンドと併せてHDDの消去などに利用したり、暗号関連プログラムの内部処理などに利用したりします。
しかし、どちらも同じ乱数文字列を出力するのならば、一つで事足りるはずです。なぜ、二つあるのか?
以下、その違いについて述べていきます。

違いはエントロピープール枯渇時の挙動

/dev/randomおよび/dev/urandomは、擬似乱数文字列を生成する際、乱数種(ランダムシード)を利用します。
この乱数種は、エントロピープールから取り出されます。

エントロピープールは、Linuxカーネルの保持するバッファであり、複数の環境ノイズ源から乱雑な数値を集めたものです。
環境ノイズ源には、入力デバイスの発生イベント種別や間隔、割り込み発生間隔、ディスクシーク時間などが挙げられます。

さて、このエントロピープールから乱数種を取り出し、疑似乱数文字列を生成するわけですが、当然ながら蓄積されたエントロピープールは有限です。延々と乱数文字列を吐き出していると、エントロピープール内の数値を使い切ってしまう事態が生じます。

この、エントロピープール内の数値を使い切ってしまった時、この時の挙動の違いが/dev/randomと/dev/urandomの違いです。

試しに、以下のコマンドを実行してみましょう。

$ cat /dev/random

しばらく乱数文字列を吐き出しますが、途中で停止してしまうはずです。マウスを動かすなど、適当に操作していると、再度乱数文字列を吐き出し始めます。

途中で停止するのは、エントロピープール内の数値を使い切って、乱数種を取り出せなくなったからです。
このような場合、/dev/randomは、再び一定のエントロピーに達するまで処理を中断します。
(ブロック、といいます。)

これに対して、/dev/urandomは、過去に使った乱数種を再利用することで処理を続けます。
/dev/randomと違って、延々と乱数文字列を吐き出し続けても、途中で止まったりしないわけです。

/dev/urandomの方が利便性は高いのですが、乱数種を再利用する、ということは安全性に問題を抱えているということでもあります。
/dev/randomは乱数種を再利用しませんので、/dev/urandomとくらべてより安全な乱数文字列を生成します。
そのため、暗号関連のプログラムが内部処理で利用するのは、通常/dev/randomの方です。

ちなみにエントロピープールの貯蓄状態は以下で確認できます。

cat /proc/sys/kernel/random/entropy_avail

「cat /dev/random」と併せて使うと、その挙動がよく分かると思います。
わかったところで、何がどうなるかは知りませんが。

それでは今日はこの辺で。