
Unix系 オペレーティングシステムでは、/dev/randomと/dev/urandomは、暗号的に安全な擬似乱数生成器(CSPRNG)から乱数を生成するための特別なファイルです。CSPRNGは、デバイスドライバなどの環境ノイズから収集されたエントロピー(乱数を生成する値)をシードとして生成されます。ユーザーは、このファイルを読み取るだけで、CSPRNGから乱数を得ることができます。[1]すべてのオペレーティングシステムが/dev/randomと/dev/urandomに対して同じ方法を実装しているわけではありません。
古いオペレーティングシステムでは、利用可能なエントロピーが要求された値よりも少ない場合、 /dev/random は通常ブロックされていました。最近では(オペレーティングシステム間の差異については後述)、十分なエントロピーが蓄積されるまで起動時にブロックされ、その後ブロックが解除されるのが一般的です。/dev/urandomデバイスは、起動時に疑似乱数生成器のシードがエントロピーで完全に初期化されていない場合でも、通常はブロックデバイスになることはありませんでした。
この特別なファイルは1994年にLinuxで誕生しました。その後すぐに他のUnix系オペレーティングシステムにも採用されました。[2]

Linuxカーネルは、/dev/randomと/dev/urandomという別々のデバイスファイルを提供しています。2020年のカーネルバージョン5.6以降、/dev/randomはCSPRNGが初期化されていない場合にのみブロックされます。初期化後は、/dev/randomと/dev/urandomは同じ動作をします。[3]
2016年10月、 Linuxカーネルバージョン4.8のリリースに伴い、カーネルの/dev/urandomは、 Bernsteinの評価の高いストリーム暗号ChaCha20をベースにしたTheodore Ts'oによるChaCha20ベースの暗号擬似乱数生成器(CPRNG)実装[4]に切り替えられました。
Linuxカーネルのバージョン5.17以降、乱数ジェネレーターはエントロピーコレクターのSHA-1 暗号ハッシュ関数から、より新しく、より高速で、より安全なハッシュ関数であるBLAKE2sに切り替えました。 [5]
カーネル空間での乱数生成は、1994年にTheodore Ts'oによってLinux [2]向けに初めて実装されました[6]。 実装では、生成器が最初に設計された当時施行されていた暗号技術の輸出規制を回避するため、暗号ではなくセキュアハッシュが使用されました[説明が必要]。また、実装は、ハッシュや暗号が最終的に脆弱であることが判明する可能性があるという前提で設計されているため、そのような脆弱性に対しても設計は耐久性があります。プールの侵害からの迅速な回復は要件とは見なされていません。プールの侵害の要件は、オペレーティングシステムの無関係な部分に対するはるかに容易で直接的な攻撃に十分であるためです。
Ts'oの実装では、生成器はエントロピープール内のノイズビット数の推定値を保持しています。このエントロピープールから乱数が生成されます。/dev/randomデバイスは、読み出すと、エントロピープール内のノイズビット数の推定値の範囲内のランダムバイトのみを返します。エントロピープールが空の場合、/dev/randomからの読み取りは、追加の環境ノイズが収集されるまでブロックされます。 [7]その目的は、暗号的に安全な疑似乱数生成器として機能し、可能な限り大きなエントロピーを持つ出力を提供することです。これは、著者によって、高価値または長期保護のための暗号鍵の生成に使用するために提案されています。[7]
/dev/randomに対応するものとして、内部プールを再利用してより多くの疑似乱数ビットを生成する/dev/urandom(「無制限」[8]、非ブロッキング乱数ソース[7] )があります。これは、呼び出しがブロックされないことを意味しますが、出力のエントロピーは/dev/randomからの対応する読み取りよりも少なくなる可能性があります。/dev/urandomは依然としてほとんどの暗号用途に適した疑似乱数生成器として意図されていますが、対応するマニュアルページの著者は、理論的には/dev/urandomで使用されるアルゴリズムに対する未公開の攻撃が存在する可能性があり、そのような攻撃を懸念するユーザーは代わりに/dev/randomを使用する必要があると指摘しています[7] 。しかし、そのような攻撃が発生する可能性は低いです。なぜなら、エントロピープールが予測不可能になると、ビット数が減少してもセキュリティが損なわれることはないからです[9] 。
/dev/randomへの書き込みも可能です。これにより、任意のユーザーがランダムデータをプールに混在させることができます。ランダムでないデータは無害です。なぜなら、エントロピー推定値を増やすために必要なioctlを発行できるのは特権ユーザーだけだからです。 [疑わしい–議論する]現在のエントロピー量と Linux カーネルエントロピープールのサイズは、どちらもビット単位で/proc/sys/kernel/random/に保存されており、それぞれ コマンドとコマンドで表示できます。
cat /proc/sys/kernel/random/entropy_availcat /proc/sys/kernel/random/poolsize
Gutterman、Pinkas、Reinmanは2006年3月にLinux乱数生成器[10]の詳細な暗号解析を発表し、いくつかの脆弱性について説明しています。彼らが報告する最も深刻な問題は、ルータやディスクレスクライアントなどの組み込みシステムやLive CDシステムで発生する可能性があります。これらのシステムでは、起動時の状態が予測可能であり、環境から供給されるエントロピーが限られている可能性があります。不揮発性メモリを備えたシステムの場合、彼らはシャットダウン時にRNGから一部の状態を保存し、次回の再起動時にRNGの状態に含めることを推奨しています。ネットワークトラフィックが主なエントロピー供給源となるルータの場合、再起動をまたいで状態を保存するには、「潜在的な攻撃者は、ルータが最初に稼働した時点からすべてのネットワークトラフィックを盗聴するか、ルータの内部状態に直接アクセスする必要がある」と指摘しています。この問題は、ネットワークトラフィックを遠隔から捕捉でき、RNGを使用してデータ暗号化用の鍵を生成する可能性のある無線ルータの場合に特に深刻であると彼らは指摘しています。
Linuxカーネルは、インストールされている場合、いくつかのハードウェア乱数生成器をサポートしています。これらのデバイスの生の出力は、/dev/hwrngから取得できます。[11]
Linuxカーネル3.16以降では、[12]カーネル自体がハードウェア乱数生成器からのデータを、HWRNGの定義可能なエントロピー推定品質に基づいてスライディングスケールで/dev/randomにミックスします。つまり、この処理を行うためにrng-toolsのrngdなどのユーザー空間デーモンは必要ありません。
エントロピープールは、timer_entropyd、haveged、randomsoundなどのプログラムによって改善できます。rng-toolsを使用すると、Entropy Keyなどのハードウェア乱数生成器が/dev/randomに書き込むことができます。diehardテストプログラムdiehard、dieharder、entはこれらの乱数生成器をテストできます。[13] [14] [15] [16]
2014年1月、ダニエル・J・バーンスタインは、 Linuxが複数のエントロピー源を混在させている仕組みに関する批判[ 17]を発表しました。彼は、他のエントロピー源を監視できるエントロピー源の一つが、自身の出力を改変することで他のエントロピー源のランダム性を無効化できるという攻撃について概説しています。関数 を考えてみましょう。ここで、 Hはハッシュ関数、x、y、zはエントロピー源であり、zはCPUベースの悪意のあるHRNG Zの出力です。
バーンスタインは、攻撃者がDSAとECDSAを侵害するためには、RNG出力の最初の4ビットを0にすることで、 を16回繰り返す必要があると推定しました。これは、Linuxが単一の高品質シードを使用するのではなく、継続的にHを再シードするため可能です。[17]
バーンスタインはまた、CSPRNGが初期化された後はエントロピー注入は無意味であると主張している。[17]
カーネル5.17(カーネル5.10.119にバックポート)において、Jason A. DonenfeldはLinuxエントロピープールインフラストラクチャの新しい設計を提案しました。Donenfeldは、単一の4096ビットLFSRで構成される従来のプールは、 2つの攻撃に対して脆弱であると報告しました。(1) 攻撃者は既知の入力の効果を取り消すことができます。(2) プール全体の状態が漏洩した場合、攻撃者はプール内のすべてのビットをゼロに設定できます。Donenfeldの新しい設計は、より高速で安全であり、256ビットプールのミキシングにblake2sハッシュ関数を使用しています。[18]
FreeBSDオペレーティングシステムは、/dev/urandomから/dev/randomへのリンクを提供しています。どちらも、適切にシードが設定されるまではブロックしません。FreeBSDのPRNG(Fortuna)は定期的にシードを再設定しますが、エントロピーの推定は行いません。ネットワークとディスクのアクティビティが少ないシステムでは、再シードは1秒未満で実行されます。[19]
DragonFly BSDはFreeBSDからフォークされた際にランダムデバイスファイルを継承した。[20] [非一次ソースが必要] [21]
OpenBSD 5.1(2012年5月1日)以降、/dev/randomと/dev/arandomはRC4ベースのCSPRNG関数であるarc4randomを使用しています。この関数は、OpenBSD 5.5(2014年5月1日)でより強力なChaCha20を使用するように変更されました。システムは、 OpenBSD Cryptographic Frameworkを通じて、利用可能なハードウェア乱数生成器(一部のIntel PCIハブに搭載されているものなど)を自動的に使用します。[22] [23] /dev/arandomはOpenBSD 6.3(2018年4月15日)で削除されました。[24]
NetBSDのレガシーarc4random()APIの実装もChaCha20に移行されました。[25]
Apple OSはすべて、少なくとも2019年12月以降、おそらくそれ以前からFortunaに移行しています。[26] FortunaはSHA-256に基づいています。セキュアエンクレーブRNG、ブートフェーズタイミングジッター、ハードウェア割り込み(タイミングは想定)など、複数のエントロピーソースが使用されます。RDSEED/RDRANDは、それをサポートするIntelベースのMacで使用されます。シード(エントロピー)データも、その後の再起動のために保存されます。
変更前は、macOSとiOSはSHA-1に基づく160ビットのYarrowを使用していました。[27]
/dev/randomと/dev/urandomの間には違いはなく、どちらも同じように動作します。[28] [29]
/dev/randomと/dev/urandomは、Solaris、 [30] 、NetBSD、 [31] Tru64 UNIX 5.1B、 [32] AIX 5.2 [33]、 HP-UX 11i v2でも利用可能です。 [34] FreeBSDと同様に、AIXは独自のYarrowベースの設計を実装していますが、AIXは標準の/dev/random実装よりもかなり少ないエントロピーソースを使用し、十分なエントロピーが含まれていると判断するとプールの補充を停止します。 [35]
Windows NTでは、同様の機能がksecdd.sysによって提供されていますが、UNIXのように特殊ファイル\Device\KsecDDの読み取りは機能しません。暗号的にランダムなバイトを生成するための文書化された方法は、CryptGenRandomとRtlGenRandomです。Windows PowerShellは、Get-SecureRandomコマンドレットを介して、暗号的に安全な疑似乱数生成器にアクセスできます。[36]
Windows上のCygwinは/dev/randomと/dev/urandomの両方の実装を提供しており、スクリプトやプログラムで使用することができます。[37]
常に新しいエントロピーを追加することが良いことだという、真剣な議論はあるだろうか? Linuxの/dev/urandomマニュアルページには、新しいエントロピーがなければユーザーは「理論上、暗号攻撃に対して脆弱」であると主張しているが、(私が様々な場で言及してきたように)これはばかげた議論である。
用の ChaCha ベースの乱数ジェネレータ。
はOpenBSDから削除されました。
のレガシー arc4random(3) API を、ChaCha20 PRF を使用してスレッドごとの状態を持つように再実装しました。