乱数の基礎と実務ガイド:TRNG/PRNG/CSPRNGの違いと暗号用途での安全運用

乱数とは — 概要

乱数(らんすう、random number)とは、予測が困難で規則性がない数列の値のことを指します。IT分野では、乱数はシミュレーション、統計的モデリング、暗号、ゲーム、分散アルゴリズム、テストデータ生成など幅広い用途で使われます。乱数の「ランダム性」は用途によって求められる性質が異なり、たとえばシミュレーションでは統計的な一様分布や独立性が重視され、暗号では予測不可能性(攻撃者が将来や過去の値を推測できないこと)が最重要になります。

乱数の分類

  • 真の乱数(True Random Number, TRNG): ハードウェア的な物理現象(熱雑音、放射性崩壊、量子確率など)を測定して生成される乱数。真の物理的不確実性に基づくため、高いエントロピーを持つとされる。
  • 擬似乱数(Pseudo-Random Number, PRNG): 決定論的アルゴリズムにより生成される数列。初期値(シード)が同じなら同じ系列が再現される。高速で周期が長く、シミュレーションなどで広く使われる。
  • 暗号学的擬似乱数(CSPRNG): PRNGの一種だが、暗号学的安全性(次の出力や内部状態を推定できないこと)を満たすよう設計されている。暗号鍵生成やセッションIDなどに必要。

代表的な擬似乱数生成アルゴリズム

  • 線形合同法(Linear Congruential Generator, LCG): 実装が簡単で高速だが周期や相関の問題から高品質用途には不向き。
  • Mersenne Twister: 長い周期(2^19937−1)と高速性を備え、統計用途で広く使われるが暗号用途には不適。
  • Xorshift / Xoshiro / PCG: ビット操作ベースで高速かつ実装が簡潔。PCGは分布改善と高品質を目指した設計。
  • 暗号技術に基づく生成器(例: AES-CTR DRBG、HMAC-DRBG、Hash_DRBG、ChaCha20ベースのDRBG): NISTやRFC仕様に沿うCSPRNGの実装。

真の乱数(ハードウェアRNG)とその利用

ハードウェア乱数生成器(TRNG)は物理現象から直接エントロピーを得るため、理論上予測が困難です。具体例としては、集積回路のノイズ測定、光子検出の量子現象、放射線検出器などがあります。商用CPUではIntelのRDRAND(内部はDRBGに相当)や、より低レベルのシード供給用にRDSEEDといった命令が提供されています。またTPMやセキュアエレメント、専用QRNG(量子乱数生成器)なども普及しています。

ただし、ハードウェアRNGにも実装バグや設計上の偏りがあることがあり、生成結果から無条件に安全性を保証することはできません。そのため多くのシステムはTRNGで得たエントロピーをCSPRNGのシードに用いるなどハイブリッドな運用を行います。

乱数の評価とテスト

乱数の品質は統計的・情報理論的な観点から評価されます。代表的なテストスイートには以下があります。

  • NIST SP 800-22: 一連の統計テスト(周波数テスト、連続ビット列テストなど)を提供。
  • Diehard/Dieharder: 古典的なテスト群で広く参照される。
  • TestU01: 高度で厳密な統計テストを多数収録するライブラリ。PRNG評価の標準ツールの一つ。

ただし統計テストは「欠陥の検出」には有効でも「安全性の証明」にはならない点に注意が必要です。特に暗号用途では推定困難性(予測不可能性)を数学的または暗号解析的に評価する必要があります。

暗号用途での注意点

暗号における乱数は非常にセンシティブです。以下のポイントは必須の注意点です。

  • 暗号鍵、初期化ベクトル(IV)、トークンなどにはCSPRNGを必ず使用する。一般的な非暗号用PRNG(Mersenne Twister等)は不可。
  • シード管理に注意する。固定シードや予測可能なシードを用いると全系列が破られる。
  • OSが提供する信頼できる乱数APIを使うこと。例: getrandom()/CryptGenRandom()/Cryptography libraries(OpenSSLのRAND_bytesなど)。
  • ハードウェア命令(RDRANDなど)を直接盲信しない。生成器からの値は適切に評価・混合(whitening)して用いるのが一般的。

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

  • 暗号用途ではCSPRNGを利用:プラットフォームの推奨API(Linuxのgetrandom、WindowsのCryptGenRandom/BCryptGenRandom、各言語のセキュア乱数API)を使う。
  • 独自実装は避ける:乱数や暗号アルゴリズムは専門家によるレビューが不可欠。独自設計は脆弱性を生みやすい。
  • 初期化シーケンス(ブート時など)のエントロピーを確保:組み込み機器や仮想マシンではエントロピー不足に注意する。
  • 必要に応じてハードウェアエントロピーをミキシング:TRNGの出力をCSPRNGに投入して長期的な安全性を確保。
  • 乱数のテストと監視:運用中に統計的な偏りが検出されないか定期的にチェックする。

よくある誤解・落とし穴

  • 「長い周期=安全」ではない:周期が長くても内部状態が推測可能なら暗号的安全性は確保できない。
  • 「/dev/urandom は常に安全ではない」:古いブート時など十分な初期エントロピーが無い場合は問題になり得る。ただし現代のOSではgetrandom()やカーネルの初期化改良により多くのケースで安全に使える。
  • 「ハードウェアルネイティブ命令は絶対安全」ではない:実装ミスやバックドアの懸念が指摘された例もあるため、独立した評価や多重化が望ましい。

実用例

用途別の推奨例:

  • 暗号鍵生成:OSのCSPRNG(getrandomやCryptGenRandom等)→必要ならTRNGをシードに混合
  • 統計シミュレーション:Mersenne TwisterやPCGなど高品質で高速なPRNG
  • ゲームやUIのランダム要素:用途に応じて非暗号PRNGで十分。ただし不正操作対策が必要な場合はCSPRNGを検討

まとめ

乱数は用途により求められる性質が異なり、特に暗号用途では予測不可能性が最優先です。真の乱数(TRNG)と擬似乱数(PRNG/CSPRNG)の違いを理解し、OSやライブラリが提供する信頼できるAPIを使うこと、独自実装を避けること、エントロピー管理と定期的なテストを行うことが実務上の鍵です。

参考文献