擬似乱数生成(PRNG)完全ガイド:アルゴリズム選択・CSPRNGの安全性・品質評価・実装のベストプラクティス
擬似乱数生成とは — 概要
擬似乱数生成(Pseudo-Random Number Generation, PRNG)は、決定論的なアルゴリズムから「ランダムに見える」数列を生成する技術です。真の物理的乱数(TRNG:True Random Number Generator)が外部の熱雑音や量子揺らぎなど不可予測な現象に依存するのに対し、PRNGは有限の内部状態と遷移関数に基づき高速かつ再現可能な乱数を生成します。これにより、シミュレーションや統計解析、ゲーム、暗号など幅広い用途で利用されますが、用途に応じて適切な種類を選ぶ必要があります。
PRNGの基本的な仕組みと性質
PRNGは内部状態(シード)を持ち、それを次状態関数で更新しながら出力を生成します。主要な評価指標は次の通りです。
- 周期(Period): 出力列が繰り返すまでの長さ。優れたPRNGは非常に長い周期(例:Mersenne Twisterは219937−1)を持つ。
- 均一性・分布性: 出力が目的の確率分布(通常は一様分布)に従うか。
- 独立性(相関の少なさ): 時系列や高次元での相関が小さいか。
- 線形複雑度や非線形性: 将来の出力を予測しにくいか(特に暗号用途で重要)。
- 速度・メモリ消費: 実運用での性能要件。
代表的なアルゴリズム
代表的なPRNGには用途ごとに最適化されたものがあります。
- 線形合同法(LCG): 実装が非常に簡単だが低次元での相関や短い周期の問題がある。
- Mersenne Twister (MT19937): 非常に長い周期と良好な均一性で一般用途の乱数ライブラリで広く採用。ただし暗号用途には不適。
- xorshift / xoroshiro / xoshiro 系: ビット演算主体で高速。良好な統計特性を持つがCSPRNGではない。
- PCG (Permuted Congruential Generator): Melissa O’Neill による設計で、品質・速度・小規模実装のバランスが良い。
- カウンタベース(Philox / Threefry / Random123): ストリーム分割や並列処理に強い。GPUや分散計算向け。
- 暗号化ブロック/ストリーム関数ベース: AES-CTR、ChaCha20 などはCSPRNGとして用いられる安全な方法。
暗号学的に安全なPRNG(CSPRNG)
暗号用途では単に統計的に良いだけでなく、出力から内部状態や過去・未来の出力が推定できないこと(前方秘匿性・後方秘匿性)が要求されます。NIST SP 800-90A で定義された DRBG(Hash_DRBG, HMAC_DRBG, CTR_DRBG)や、libsodium の randombytes_buf(ChaCha20ベース)などが代表例です。Dual_EC_DRBG の疑念のように、設計や実装に弱点があるとバックドアや予測が可能になるリスクがあります。
統計テストと品質評価
PRNGの品質は統計的検定で評価されます。代表的なテストスイートとして以下があります。
- Diehard / Dieharder
- TestU01(SmallCrush, Crush, BigCrush) — 非常に厳密な評価を提供
- NIST SP800-22(暗号用途の基礎検定)
ただし、統計検定に合格したからといって暗号学的に安全である保証はありません。逆に暗号的安全性があればこれらの検定も通常通過します。
実装と運用上の注意点
実際の開発運用でよくある落とし穴と対策です。
- 安易なシード: 時刻のみをシードに使うと予測可能。高品質なエントロピーソースからシードを取得する(OSの /dev/random, /dev/urandom, getrandom, Windows の CryptGenRandom/BCryptGenRandom, libsodium のランダムAPI など)。
- 暗号用途にMT19937等を使用しない: Mersenne Twister は性能は良いが復元可能性や線形性の問題で暗号には不適。
- 再シード(reseed)と状態管理: 長時間稼働するサービスは定期的に追加エントロピーで再シードする。シードを外部に漏らさない。
- 複数スレッド/プロセスでの乱数: 共有状態型PRNGは競合や相関の原因に。各スレッドで独立なストリームを確保するか、カウンタベースPRNGを利用する。
- 浮動小数点での変換: 整数乱数から [0,1) の浮動小数点を作る際のビット処理に注意(均一分布の欠陥を招かないように)。
用途別の選び方(実用的ガイド)
- シミュレーション・モンテカルロ: 再現性が重要なら決定論的で良質な非暗号PRNG(PCG、xoshiro、MT19937)。並列処理ならカウンタベース(Philox/Threefry)。
- ゲーム・UIランダム: 速度優先で非暗号PRNGで可。ただしチート防止を考えるならサーバ側でCSPRNGを利用。
- 暗号・認証・鍵生成: 必ずCSPRNG(OS提供のエントロピー源、または ChaCha20/AESベースのDRBG)を使う。
- 統計検定やアルゴリズム評価: TestU01 等で事前評価。
過去の問題事例と教訓
いくつかの実例が教訓になります。
- Debian OpenSSL の RNG 脆弱性(2006-2008): シード元を削ったことで鍵生成が著しく予測可能になり、多数の秘密鍵が危険にさらされた。
- Dual_EC_DRBG の疑惑: 標準化されたDRBGに埋め込まれた可能性のあるバックドアが論争になり、標準選定や信頼性の重要性が再認識された。
まとめ — ベストプラクティス
擬似乱数生成は用途に応じた選択と安全な実装が不可欠です。暗号用途では検証済みのCSPRNGを用い、一般用途では高速で統計的に良好なPRNG(PCG、xoshiro 系など)を選ぶ。シードは信頼できるエントロピー源から取得し、並列化や長時間稼働時の再シードにも配慮してください。加えて、実運用前に適切な統計テストを行い、既知の脆弱性や設計思想(例: 線形性や周期)を理解することが重要です。
参考文献
- Pseudorandom number generator — Wikipedia
- Mersenne Twister — Original site (M. Matsumoto & T. Nishimura)
- PCG: A Family of Better Random Number Generators — pcg-random.org
- Sebastiano Vigna — xorshift / xoroshiro / xoshiro 系の解説
- Parallel Random Number Generators: Marching on (Philox / Threefry, Random123)
- NIST SP 800-90A Rev.1 — Recommendation for Random Number Generation Using Deterministic Random Bit Generators
- Dieharder: A Random Number Test Suite
- TestU01 — A Software Library in C for Empirical Testing of Random Number Generators
- Debian OpenSSL predictable RNG — Advisory and analyses
- libsodium — randombytes


