random, urandom -
カーネル乱数ソースデバイス
#include <linux/random.h>
int ioctl(fd, RNDrequest,
param);
(Linux 1.3.30
から提供されている)
/dev/random 、
/dev/urandom
キャラクタスペシャルファイルは
カーネル乱数ジェネレータへのインタフェースを提供する。
/dev/random
ファイルはメジャーデバイス番号
1
マイナーデバイス番号
8 である。
/dev/urandom
はメジャーデバイス番号
1
マイナーデバイス番号
9 である。
乱数ジェネレータはデバイスドライバやその他の源からの環境ノイズを
エントロピー・プールへ集める。
また、ジェネレータはエントロピー・プール内のノイズのビット数の推定値を
保持する。
このエントロピー・プールから乱数が生成される。
読み込みが行われると、
/dev/random
デバイスはエントロピー・プールのノイズビットの数の推定値のうち、
ランダムバイトのみを返す。
/dev/random
はワンタイムパッド
(one-time pad)
や鍵の生成のような
非常に高い品質を持った無作為性が必要になる用途に向いているだろう。
エントロピー・プールが空の時は、
/dev/random
からの読み出しは、
更なる環境ノイズが得られるまで、ブロックされる。
/dev/urandom
デバイスから読み出しでは、
エントロピーがより高くなるのを待つためのブロックは行われない。
その結果、もしエントロピー・プールに十分なエントロピーが存在しない場合、
返り値はこのドライバで使われているアルゴリズムに基づく暗号攻撃に対して、
論理的には弱くなることになる。
この攻撃をどのように行うかという事については、現在研究論文などの
形で入手できる資料はない、しかし、そのような攻撃は論理的に存在可能である。
もし、この事が心配なら、(
/dev/urandom ではなく)
/dev/random
を利用すればいい。
/dev/random や
/dev/urandom
に書き込みを行うと、
書き込まれたデータでエントロピー・プールが更新される。
しかし、
エントロピー・カウントが増えるわけではない。
つまり、
/dev/random と
/dev/urandom
の両方のファイルから読み出される内容に影響があるが、
/dev/random
からの読み出しが早くなるわけではないということだ。
使い方¶
/dev/random と
/dev/urandom
のどちらを使うべきか迷った場合、たいていは
/dev/urandom
の方を使いたいと思っているはずだろう。
一般に、長期に渡って使われる
GPG/SSL/SSH
のキー以外の全てのものに
/dev/urandom
を使用すべきである。
下記で推奨しているように再起動の前後で乱数種ファイルが保存される場合
(全ての主な Linux
のディストリビューションは少なくとも
2000 年以降は
乱数種を保存するようになっている)、起動シーケンスにおいて乱数種が
再ロードされた直後から、その出力はローカルのルートアクセスができない
攻撃者に対して暗号的に安全なものとなり、ネットワーク暗号化のセッションキー
として使うには完全に最適なものとなる。
/dev/random
からの読み出しは停止
(block)
する可能性があるので、ユーザは普通
このファイルを非停止
(nonblocking)
モードで開こうとし
(もしくはタイムアウトを指定して読み出しを実行し)、希望するレベルの
エントロピーはすぐには利用できない場合には、何らかの通知を行うことだろう。
カーネルの乱数ジェネレータは、暗号疑似乱数ジェネレータ
(Cryptographic pseudo-random number generator; CPRNG)
の種として使用できる
高品質な乱数種の材料を少し生成するために設計されている。
これは速度ではなく安全性を重視して設計されており、
ランダムなデータを大量に生成するのには全くもって適していない。
ユーザは
/dev/urandom (と
/dev/random)
から読み出す乱数種の材料の量をできるだけ節約すべきである。
このデバイスから不必要に大量のデータを読み出すと、このデバイスを使う
他のユーザにマイナスの影響を与えてしまうだろう。
暗号鍵を生成するのに必要な乱数種の材料の量は、鍵の実効サイズと同じである。
例えば、3072 ビットの RSA
および Diffie-Hellman
の秘密鍵の実効サイズは
128 ビット
(この秘密鍵を破るには
2^128
回の操作が必要ということ)
であり、
そのため鍵生成器が
/dev/random
から読み出す必要がある乱数種の材料の量は
128 ビット (16 バイト)
だけである。
CPRNG
アルゴリズムの欠陥に対する保護として、この最小値に対していくらかの
安全上のマージンを取るのはもっともだが、現在利用可能な暗号プリミティブで
256
ビットより多くの安全な乱数を必要とするようなものはない。
起動する度に、もしくは乱数種を変更する妥当な間隔
(1
分より短くなることはない)
の度に、カーネルの乱数プールから
256 ビット (32 バイト)
よりたくさん読み出す
ような場合には、そのプログラムの暗号処理がうまく実装されて「いない」可能性が
あると考えるべきであろう。
Configuration¶
システムにあらかじめ作成された
/dev/random と
/dev/urandom
が存在しないなら、次のようなコマンドで作成できる。
mknod -m 644 /dev/random c 1 8
mknod -m 644 /dev/urandom c 1 9
chown root:root /dev/random /dev/urandom
オペレータの操作なしに
Linux
システムが起動した直後は、
エントロピー・プールは意外性の乏しい均一な状態にあるだろう。
これにより、エントロピー・プールの実際のノイズ量は評価値より少なくなる。
この効果を打ち消すために、シャットダウンから
(次の)
起動時まで持ち越した
エントロピー・プールの情報が助けになる。
エントロピー・プールを持ち越すためには、
Linux
システムの起動時に実行される適切なスクリプトに、
以下の行を追加すればよい:
echo "Initializing random number generator..."
random_seed=/var/run/random-seed
# 乱数種を今回のスタートアップから次回のスタートアップまで持ち越す。
# ロードを行い、その後、全てのエントロピー・プールを保存する。
if [ -f $random_seed ]; then
cat $random_seed >/dev/urandom
else
touch $random_seed
fi
chmod 600 $random_seed
poolfile=/proc/sys/kernel/random/poolsize
[ -r $poolfile ] && bytes=`cat $poolfile` || bytes=512
dd if=/dev/urandom of=$random_seed count=1 bs=$bytes
また、Linux
システムのシャットダウン時に実行される適切なスクリプトに、
以下の行を追加すればよい:
# 乱数種を今回のシャットダウンから次回のスタートアップまで持ち越す。
# 全てのエントロピー・プールを保存する。
echo "Saving random seed..."
random_seed=/var/run/random-seed
touch $random_seed
chmod 600 $random_seed
poolfile=/proc/sys/kernel/random/poolsize
[ -r $poolfile ] && bytes=`cat $poolfile` || bytes=512
dd if=/dev/urandom of=$random_seed count=1 bs=$bytes
/proc インタフェース¶
ディレクトリ
/proc/sys/kernel/random
にあるファイル (2.3.16
から存在する) は、
/dev/random
デバイスへのその他のインタフェースを提供する。
読み込み専用のファイル
entropy_avail
は使用可能なエントロピーを表す。
通常、これは 4096
(ビット)
になり、エントロピー・プールが満杯の状態である。
ファイル
poolsize
はエントロピー・プールのサイズを表す。
このファイルの意味はカーネルバージョンにより異なる。
- Linux 2.4:
- このファイルはエントロピー・プールのサイズを「バイト」単位で規定する。
通常、このファイルの値は
512
になるが、書き込み可能であり、
アルゴリズムで利用可能な任意の値に変更できる。
選択可能な値は 32, 64, 128, 256,
512, 1024, 2048 である。
- Linux 2.6:
- このファイルは読み出し専用であり、
エントロピー・プールのサイズを「ビット」単位で規定する。
値は 4096 である。
ファイル
read_wakeup_threshold は
/dev/random
からのエントロピーを待って休止しているプロセスを起こすのに必要な
エントロピーのビット数を保持している。
デフォルトは 64
である。 ファイル
write_wakeup_threshold
はエントロピーのビット数を保持しており、この値以下になったら
/dev/random
への書き込みアクセスのために
select(2) または
poll(2)
を実行するプロセスを起こす。
この値はファイルに書き込みを行うことによって変更できる。
読み込み専用のファイル
uuid と
boot_id は
6fd5a44b-35f4-4ad4-a9b9-6b9be13e1fe9 のような
ランダムな文字列を保持している。
前者は読み込みの度に新たに生成され、
後者は 1
度だけ生成される。
ioctl(2) インタフェース¶
以下の
ioctl(2) 要求が
/dev/random や
/dev/urandom
に接続されたファイルディスクリプタに対して定義されている。
実行されたすべての要求は、
/dev/random と
/dev/urandom
に影響を与える入力エントロピー・プールとやり取りを行う。
RNDGETENTCNT
以外のすべての要求には
CAP_SYS_ADMIN
ケーパビリティが必要である。
- RNDGETENTCNT
- 入力エントロピー・プールのカウントを取得する。
取得される内容は proc
の entropy_avail
ファイルと同じである。
結果は引き数が指す整数
(int) に格納される。
- RNDADDTOENTCNT
- 入力エントロピー・プールのカウントを引き数が指す値だけ加算または減算する。
- RNDGETPOOL
- Linux 2.6.9 で削除された。
- RNDADDENTROPY
- 入力プールに追加のエントロピーを追加し、エントロピー・カウントを増やす。
この要求は /dev/random や
/dev/urandom
への書き込みとは異なる。
/dev/random や /dev/urandom
への書き込みでは、
何らかのデータが追加されるだけで、
エントロピー・カウントは増やされない。
以下の構造体が使用される。
-
struct rand_pool_info {
int entropy_count;
int buf_size;
__u32 buf[0];
};
- entropy_count
はエントロピー・カウントに加算
(または減算)
する値である。 buf
は大きさが buf_size
のバッファで、この内容がエントロピー・プールに追加される。
- RNDZAPENTCNT, RNDCLEARPOOL
- すべてのプールのエントロピー・カウントを
0
にし、何らかのシステムデータ
(現在の時刻など)
をプールに追加する。
ファイル¶
/dev/random
/dev/urandom
関連項目¶
mknod(1)
RFC 1750, "Randomness Recommendations for Security"
この文書について¶
この man ページは Linux
man-pages
プロジェクトのリリース
3.65 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。