乱数生成の基礎から実務まで:TRNG/PRNG/CSPRNGの違いと安全な運用ガイド

乱数生成とは何か

乱数生成(random number generation)は、予測不能な数値列を作り出す技術全般を指します。IT分野では乱数はシミュレーション、統計解析、暗号、ゲーム、乱択アルゴリズムなど幅広い用途で不可欠です。用途に応じて要求される性質(可再現性、統計的均一性、予測困難性、周期の長さなど)が異なるため、「乱数」と一口に言っても実装や評価基準は多様です。

真性乱数(TRNG)と疑似乱数(PRNG)の違い

  • TRNG(True Random Number Generator): 自然現象やハードウェアノイズ(熱雑音、電子ノイズ、ジャンプ振動、放射線検知など)の物理的不確定性に基づく乱数。出力は非決定的で再現不能。例:ノイズ検出器、リングオシレータベースの乱数回路。

  • PRNG(Pseudo-Random Number Generator): 決定論的なアルゴリズムにより生成される乱数列。内部状態(シード)から復元可能であり、同じシードからは同じ系列が得られる。高速で長い周期を持つが、暗号用途には追加の安全性要件が必要。

代表的なPRNGアルゴリズム

用途別に多くのPRNGが存在します。代表的なものを挙げます。

  • 線形合同法(LCG):単純で計算量が小さいが、周期や下位ビットの相関など統計的弱点があるため暗号や高精度シミュレーションには不適切。

  • Mersenne Twister(MT19937):1997年に松本・西村が提案。非常に長い周期(2^19937−1)と良好な統計特性を持つが、状態復元が容易であるため暗号用には不適合。

  • Xorshift系 / xorshift+:高速で実装が簡単。統計性能は改良により向上しているが、暗号用途には不十分。

  • PCG(Permuted Congruential Generator):O'Neillらにより提案。速度と統計性のバランスが良く、一般用途のPRNGとして有力。

  • 暗号ブロック関数・ストリーム暗号ベース(例:ChaCha20):暗号的な性質を持ち、CSPRNGの実装に使われる。均一性と予測困難性の両方を満たす設計が可能。

暗号用擬似乱数器(CSPRNG)と安全性要件

暗号用途では「予測不可能性」が必須です。CSPRNG(Cryptographically Secure PRNG)は以下の性質を満たすことが求められます。

  • 次の出力ビットを効率的に予測できない(forward secrecy/forward unpredictability)。
  • 内部状態が一部漏洩しても過去の出力を復元できない(backward secrecy/ backward unpredictability、あるいは逆に「後方安全性」)。
  • 十分なエントロピーで初期化され、定期的に再シード(補強)できる。

歴史的にNISTが標準として示したDRBG(Deterministic Random Bit Generator)群や、Fortuna、およびChaCha20やAESベースのCSPRNGが一般的に利用されます。ただし、設計やパラメータ選定の誤り、あるいは外部からのバックドアの混入(例:Dual_EC_DRBG)には注意が必要です。

OSとハードウェアによる乱数提供

実務ではOS提供の乱数APIやハードウェア乱数を利用するのが現実的です。

  • UNIX/Linux:/dev/random(ブロッキング、エントロピー不足時に待機)および /dev/urandom(非ブロッキング)。近年は syscall の getrandom() や getentropy() を使うことが推奨され、カーネルの初期化後は安全に乱数を取得できます。

  • Windows:CryptGenRandom(古い)、BCryptGenRandom(CNG API)や RtlGenRandom が使われます。最新の推奨APIを利用することが重要です。

  • CPU命令 / ハードウェアRNG:Intel の RDRAND / RDSEED、ARM の True Random Number Generator(TRNG)など。RDRAND は暗号的に使用可能な乱数を直接生成する命令で、RDSEED はシード用途に向くとされますが、ハードウェア実装への信頼性・検証が課題です。ベンダーは出力の検査やソフトウェアによるミキシングを推奨しています。

乱数の評価と統計試験

乱数列の品質評価には多数の統計試験が存在します。代表的なもの:

  • Diehard / Dieharder
  • TestU01(非常に包括的で研究用途で広く使われる)
  • NIST Statistical Test Suite(NIST SP 800-22)

ただし「全ての統計試験に合格すること=暗号的に安全である」ではありません。統計的検定は特定の偏りや相関を検出するが、アルゴリズムの予測可能性や内部状態の復元可能性など暗号学的性質は別途の安全解析が必要です。

脆弱性と過去の事例

乱数に関する問題は実世界で重大な被害を生みます。よく知られた事例:

  • 不適切なシード(例えば低エントロピーな初期化)による鍵の推定。
  • 暗号標準の問題:Dual_EC_DRBG はメーカーとNSAの関係で疑惑が生じ、実装するとバックドアにつながる可能性が指摘されました。これにより標準選定と検査の重要性が再認識されました。
  • 組み込み系での脆弱性:適切なTRNGがない、あるいはPRNGをそのまま暗号用に流用したことで鍵が破られた例が複数報告されています。

実務でのベストプラクティス

  • 暗号用途ではOSや信頼できるライブラリが提供するCSPRNGを利用する(例:getrandom、BCryptGenRandom、libsodium の randombytes_buf など)。
  • 標準の rand() や単純なLCGは暗号用途・セキュリティ用途には使わない。
  • ハードウェアRNGを使う場合でも、出力を直接盲信せずOSやソフトウェアのCSPRNGへ取り込み、適切に混ぜ合わせる(ホワイトニング)こと。
  • 初期化(シード)を十分なエントロピーで行う。仮想環境や組み込み初期化直後などエントロピー不足になりやすい状況に注意。
  • 標準・ライブラリやアルゴリズムの脆弱性情報に注意し、推奨実装/APIを継続的に使い続ける。可能ならセキュリティ監査済みのライブラリを利用する。
  • 乱数品質を検査する自動テストを導入する(運用中に異常検知)。

まとめ

乱数生成は一見単純に見えますが、用途により求められる要件が大きく異なります。一般的なシミュレーションやゲームでは高速で周期の長いPRNGが適し、暗号や鍵生成では予測不能性を保証するCSPRNGと適切なエントロピー管理が必須です。OS提供APIや信頼できるライブラリを利用し、ハードウェア乱数を取り込む場合はミキシングや再シードの設計を行うなど、実務上の注意を怠らないことが重要です。

参考文献