乱数生成の完全ガイド:TRNGとPRNGの違いから暗号要件・評価テスト・実務ベストプラクティスまで
序論 — 「乱数」とは何か
ITにおける乱数は、単に「ランダムに見える数列」ではなく、用途に応じて「予測不可能性」や「統計的性質」が求められる重要なリソースです。暗号、セキュリティ、シミュレーション、ゲーム、統計的検定など、幅広い分野で乱数が使われます。本稿では乱数生成の基本原理、主要技術(擬似乱数/真性乱数)、暗号で必要となる要件、実装上の注意点やテスト方法、実務でのベストプラクティスまでを詳しく解説します。
乱数の分類:真性乱数(TRNG)と擬似乱数(PRNG)
真性乱数(TRNG, True Random Number Generator):物理現象の不確定性(熱雑音、ショットノイズ、発振器ジッタ、放射性崩壊、光子到来時間など)を直接測定して得られる乱数。理論上は非決定性で、同じ初期条件でも再現不能。ハードウェアノイズを取り出すためにアナログ→デジタル変換や整流・条件付け(whitening)を行う。
擬似乱数(PRNG, Pseudo-Random Number Generator):決定論的なアルゴリズムで内部状態から出力を生成する。内部状態とアルゴリズムが既知なら出力は再現可能。高速でメモリ消費が小さいためシミュレーション等に適する。代表例:線形合同法(LCG)、Mersenne Twister、xorshift、PCGなど。
暗号学的擬似乱数(CSPRNG / DRBG):PRNGのうち、出力の予測耐性や内部状態回復耐性など暗号的な安全性を満たすもの。NISTや各種仕様で定義されたDRBG(Hash‑DRBG、HMAC‑DRBG、CTR‑DRBG)や、AES/ChaChaベースのストリームが代表。セキュアな鍵生成・プロトコルに必須。
真性乱数(TRNG)の仕組みと実務上の注意
TRNGは典型的に次の要素を持ちます:物理ノイズ源 → センシング(ADC等) → 前処理(フィルタ、振幅整形) → ホワイトニング(抽出器) → 健康チェック。ノイズ源の例:
- 半導体ダイオードやZenerダイオードのアバランチ(アバランチ雑音)
- リングオシレータの位相ジッタやクロックジッタ
- 光子到来時間や光強度の揺らぎ(フォトン検出器)
- 放射性崩壊(特殊用途)
重要な点は「生の信号はバイアスや相関を含む」ため、単に生データを出力するのではなく、一方向ハッシュや専用の抽出器(例えばハッシュベースの抽出、XORとマトリクス演算等)でホワイトニングを行い、さらに健康チェックで出力の分布変化や故障を検出することです。ハードウェアの欠陥や外部干渉による劣化は深刻な脆弱性になります。
CPU・チップ内乱数命令(RDRAND / RDSEED 等)
近年のCPU(Intel, AMD など)はオンチップDRNG機能を持ち、RDRANDやRDSEED命令を提供します。一般に:
- RDRAND:内部DRNGが生成し、条件付け(conditioning)された出力を返す。OSやアプリケーションのAPIで直接用いられることが多い。
- RDSEED:シードマテリアル(生のエントロピーに近い値)を取得するための命令で、PRNGの初期化に適するよう設計されている。
これらは利便性が高い一方で「単独での信頼」に対する懸念(実装の欠陥や疑惑)もあり、重要システムでは複数ソースをミックスすることが推奨されます。
OSとエントロピープール
多くのOSはカーネルレベルでエントロピープールを管理し、ユーザ空間に対して乱数を提供します。Linuxでは /dev/random と /dev/urandom、そして getrandom() システムコールが主要なインターフェースです。
- /dev/random:伝統的にはエントロピー推定値が枯渇するとブロックする(高い「真の乱数」保証を重視)。
- /dev/urandom:非ブロッキングで、カーネルのCSPRNGから生成した値を返す。モダンなカーネルでは初期シードが確保された後は安全とされる。getrandom() は初期起動時のブロッキング制御などを扱いやすくするため推奨される。
実装依存の挙動やカーネルバージョンによる差異があるため、暗号用途ではOS標準API(例えば Linux の getrandom、Windows の BCryptGenRandom / CryptGenRandom、BSD の arc4random_buf 等)を利用するのが最も安全です。
PRNG の内部構造と代表的アルゴリズム
擬似乱数アルゴリズムは主に「状態遷移関数」と「出力関数」から成ります。代表的なもの:
- 線形合同法(LCG):実装が簡単だが周期や低次元部分空間に弱点がある。
- Mersenne Twister:非常に長い周期と高速性で科学計算に人気。ただし暗号用途には不適。初期化(シード)や状態回復に弱い。
- xorshift / xorshift+ / xoshiro:ビット操作ベースで高速。用途により注意が必要。
- PCG:良好な統計特性と高速性を兼ね備え、近年注目。
- CSPRNG(AES-CTR, ChaCha20):暗号アルゴリズムを内部に用いることで予測耐性を確保。ChaCha20は速度と安全性のバランスが良く、libsodium等で広く採用。
暗号学的要件と標準(NIST等)
暗号で使う乱数には「将来の出力予測不可能性」「過去出力の復元耐性」「状態コラプト時の緩和策(リシードやキー更新)」などが要求されます。NISTのSP 800-90シリーズはDRBGの設計と実装指針を示しています(Hash‑DRBG、HMAC‑DRBG、CTR‑DRBG)。注意点として、過去にDual_EC_DRBGという疑惑のあった方式が存在し、信頼性・透明性の重要性が再確認されました。
乱数の評価とテスト
乱数生成器を評価するために複数の統計テストスイートが使われます:
- NIST SP 800-22:ビット列の統計的性質を検査する一連のテスト。
- Dieharder:George Marsaglia の Diehard テスト群を拡張したツール。
- TestU01:Simon L'Ecuyerらによる強力なテストスイートで、詳細な統計評価が可能。
ただし、これらは「統計的異常を検出する」ためのものであり、暗号的予測不可能性を形式的に証明するものではありません。セキュリティ用途では統計テストだけで安心せず、設計・実装の評価と形式的仕様準拠が重要です。
実務でよくある落とし穴・攻撃パターン
- 弱いシード:time() や PID のような低エントロピー値でシードすると容易に予測される。暗号用途ではOS提供のCSPRNGでシードすべき。
- 状態の漏洩:プロセスダンプやログ、メモリスワップにより内部状態が漏れると将来の出力を予測される。メモリの保護・ゼロクリアが必要。
- 再利用・固定シード:同一シードを使い回すと出力列が再現され、鍵やトークンが同一になる危険。
- ハードウェア故障や外部介入:TRNGのノイズ源が外部からの信号で制御され得る場合、出力が偏ることがある。監視と健康チェックが不可欠。
- 設計上のバックドア:標準やライブラリ選定において信頼できない設計(疑わしい定数や不可解なアルゴリズム)を採用するとリスクになる。
ランダムネスの抽出と混合(Entropy Extraction / Conditioning)
TRNGの生データを直接使うのは危険で、エントロピー抽出器(例えばハッシュ関数や専用の抽出アルゴリズム)を用いてバイアスを除去し、均一分布に近づけます。また、複数のエントロピーソースをXORやハッシュで混合することで単一ソースの失敗耐性を高めます。CSPRNGの初期化には、可能なら複数ソース(OSエントロピー、RDSEED、TPMなど)を混ぜるのが望ましいです。
実装上のベストプラクティス(開発者向け)
- 暗号用途では必ずOS提供のCSPRNG API(getrandom、CryptGenRandom/BCryptGenRandom、arc4random_buf 等)や信頼できる暗号ライブラリ(libsodium、BoringSSL/OpenSSLのCTR/DRBG等)を使う。
- 乱数生成に srand(time(NULL)) や rand() を使わない。これらは探索空間が小さく予測されやすい。
- 初期シードの収集は十分なエントロピーを確保し、必要に応じてRDSEED等のシステム命令を利用する。
- ハードウェアTRNGを利用する場合、ホワイトニング、健康チェック、定期的な自己検査を実装する。
- 内部状態が漏洩した場合の緩和(頻繁なリシード、キー更新、状態再初期化)を計画する。
- 乱数品質を定期的にテスト(統計テスト、運用中の逸脱検出)し、異常があれば即座にフェイルセーフを作動させる。
まとめ
乱数生成は「単に数字を返すだけ」の機能に見えますが、用途によって必要とされる性質(統計的均一性、予測不可能性、耐故障性)が大きく異なります。暗号用途ではCSPRNGと信頼できるエントロピー源、適切なシード管理と健康チェックが必須です。TRNGは強力なエントロピー源となり得ますが、ハードウェアの故障や外部干渉に対する対策、出力のホワイトニングと検査が欠かせません。実務ではOS/ライブラリの標準APIを活用し、既存の標準(NIST等)やテストスイートを参照して安全な実装を行ってください。
参考文献
- NIST Special Publication 800-90A Rev.1 — Recommendation for Random Number Generation Using Deterministic Random Bit Generators
- NIST Special Publication 800-90B — Recommendation for the Entropy Sources Used for Random Bit Generation
- NIST Special Publication 800-90C — Recommendation for Random Bit Generator (RBG) Construction
- RFC 4086 — Randomness Requirements for Security
- Linux kernel documentation — /dev/urandom
- getrandom(2) — Linux manual
- Intel Digital Random Number Generator (DRNG) Software Implementation Guide
- TestU01 — A Software Library in ANSI C for the Empirical Testing of Random Number Generators
- Dieharder — A Random Number Test Suite
- Dual_EC_DRBG — (解説・歴史的背景)


