type=module
superclass=
included=
extended=
dynamically_included=
dynamically_extended=
library=openssl
aliases=
aliasof=

OpenSSL が利用する疑似乱数生成器関連のモジュールです。

  * [[RFC:4086]]

=== 暗号と乱数
OpenSSL では、鍵を生成するためなどに乱数を用いています。例えば RSA では
巨大(512bitや1024bitなど)な素数の組を乱数で生成し、そこから公開鍵、秘密鍵の
ペアを計算します。鍵は他人に知られてはならないため、
その乱数は外部からの推論が不可能な良い性質を持っている必要があります。
このようなメソッドには以下のものがあります。
  * [[m:OpenSSL::PKey::RSA.generate]]
  * [[m:OpenSSL::PKey::DSA.generate]]
  * [[m:OpenSSL::PKey::DH.generate]]
  * [[m:OpenSSL::Cipher#random_key]]
そのような乱数は適切な実装を持つ疑似乱数生成器に適切なシードを渡す
ことによって実現できます。

OpenSSL にはそのような疑似乱数生成器が実装されています。
そして、この疑似乱数生成器は OpenSSL の様々なモジュールから利用されています。
上に挙げた鍵生成メソッドの他に、
  * [[m:OpenSSL::BN.rand]]
  * [[m:OpenSSL::BN.rand_range]]
  * [[m:OpenSSL::BN.generate_prime]]
  * [[m:OpenSSL::Cipher#random_iv]]
などでも利用されます。

疑似乱数生成器は適切なシードを与えられなければ正しく動作しません。
OpenSSL にはそのための API 
  * [[m:OpenSSL::Random.#random_add]]
  * [[m:OpenSSL::Random.#seed]]
  * [[m:OpenSSL::Random.#load_random_file]]
が存在します。これらの API を模式的に説明すると、以下のようになります。
  * シードの各ビットは統計的な乱雑さ、予測不可能性を持ち、ビット列の
    乱雑さはエントロピーという量(単位は bit, 8bit = 1byte)
    で量ることができる。
  * 特にシードのすべてのビットが完全にランダムである場合には、
    エントロピーの大きさとシードのビット数は一致する。逆に
    シードのすべてのビットがある意味で既知ならば、
    エントロピーは 0 である。
  * 疑似乱数生成器にエントロピーを追加することによって
    乱数生成器から得られる乱数がより予測不可能になる。

エントロピー源には良いものと悪いものがあります。例えば現在時刻(Unix time)は
エントロピー源としては悪いです。なぜなら予測不可能なのは
せいぜい秒の部分のみであり、上位のビットは予測可能だからです。
そこに含まれるエントロピー量を適切に評価できるならばシードとして利用できますが、
通常はもっと良いエントロピー源があるはずです。
Linux であれば /dev/random が適当なエントロピー源となるでしょう。

OpenSSL では EGD(Entropy Gathering Daemon)からエントロピーを取得すること
もできます。適切なエントロピー源を提供していない OS ではこのような
方法でエントロピー源を用意する必要があるかもしれません。

実際のところ、OpenSSL バージョンによっては OS が提供するエントロピー源から
必要な量のエントロピーを得るよう実装してあるため、これらの API を使って
エントロピーを追加する必要はない場合が多いでしょう。ただし、 OS によっては
OpenSSL が利用可能なエントロピー源を見つけられない場合があり、
その場合はこれらのメソッドで明示的にエントロピーを追加する必要があるでしょう。
