疑似乱数と本物の乱数の違いの知識マップ(知識グラフ)
疑似乱数(PRNG)
seedと内部状態から、決定論的な手順で数列を生成する乱数。同じseedと同じアルゴリズムで同じ回数だけ取り出せば、同じ値列が出る。
擬似乱数
通常のPRNG
本物の乱数(NRBG/TRNG)
熱雑音や発振器のジッタのような物理的な不確定性からエントロピーを取り出す乱数。常にエントロピー源へアクセスし、正常時にはfull entropyの出力を持つとNISTでは説明される。
真性乱数
物理乱数
暗号学的疑似乱数(CSPRNG/DRBG)
ハッシュ関数やブロック暗号を基盤にした、予測困難性を重視する決定論的な乱数生成器。疑似乱数の一種だが、内部状態が分からない前提で出力を予測しにくいように設計される。
cryptographically secure pseudorandom number generator
エントロピー源
物理的な不確定性から乱数のseed・reseedとなる予測不能性を取り出す源。min-entropyの評価やhealth testingの対象になる。
ノイズ源
統計検定(NIST SP 800-22)
0と1の偏りや周期性、相関などから乱数列に明らかな欠陥がないかを調べる検定群。生成器の妥当性を証明するものではなく、あくまで欠陥検出の第一歩と位置づけられる。
予測可能なseed(時刻・PIDなど)
現在時刻やプロセスID、連番程度の、外部から絞り込みやすい値だけでPRNGをseedする実装上の弱点。
時刻seed
seed推測攻撃
予測可能な値でseedされたPRNGに対し、攻撃者がseedの候補範囲を絞り込み、同じアルゴリズムを手元で再現して狙った出力を探し当てる攻撃。
seed列挙攻撃
アカウント乗っ取り
第三者が正規利用者になりすましてアカウントを制御できるようになること。
BCryptGenRandom
Windowsネイティブの乱数生成API。既定プロバイダはNIST SP800-90が定めるCTR_DRBGに準拠する。
.NET RandomNumberGenerator
.NETが提供する暗号強度の高い乱数生成APIのクラス。鍵やトークンの生成に使う静的メソッド(GetInt32・GetBytesなど)を持つ。
getrandom()
Linuxが提供する、暗号用途に使える乱数バイトを取得するシステムコール。
Pythonのsecretsモジュール
Pythonでセキュリティ用途の乱数(トークンなど)を安全に生成するための標準ライブラリモジュール。公式ドキュメントは秘密の管理にはrandomより優先して使うよう案内している。
Java SecureRandom
Javaが提供する暗号用途の乱数生成クラス。
鍵・トークン・nonce・セッションIDの生成
認証情報として使われる鍵・トークン・nonce・セッションIDなど、攻撃者に予測されると実害につながる値を生成する用途。
セキュリティ用途の乱数生成
シミュレーション・テストの再現性
同じseedを入れれば同じ結果が得られることを利用し、シミュレーションやテスト・デバッグで結果を再現・比較できるようにすること。
再現可能なテスト
セッションID
ログイン後にサーバーが払い出す、以後の要求を同一利用者として扱うための識別子。多くの実装でcookieに格納される。
実務で使われる安全な乱数APIの多くは、物理エントロピー源でseed・reseedしたDRBG/CSPRNGを返すハイブリッド構成であり、DRBGはseedの供給元としてエントロピー源を必要とする
本物の乱数(NRBG)は常にエントロピー源へアクセスし、正常時にはそこから得たfull entropyの出力を持つことを前提とする
CSPRNG/DRBGに明らかな欠陥がないかは統計検定で確認できるが、通過は生成器の妥当性を証明するものではない
物理乱数源でも統計検定で偏りや構造上の欠陥を検出できるが、通れば本物の乱数だと証明できるわけではなく、センサーの偏りや故障で検定に落ちることもある
現在時刻やプロセスID程度の予測可能な値でPRNGをseedすると、攻撃者がトークンと要求時刻からseed候補を絞り込み、同じアルゴリズムを手元で再現して出力を予測できてしまう
予測されたパスワード再発行トークンやセッションIDが第三者に使われると、アカウント乗っ取りにつながり得る
OS・言語標準のsecure RNG APIが提供するCSPRNG/DRBGは、予測困難なエントロピー源でseedされるよう設計されており、seedの候補を数え上げるseed推測攻撃を防ぐ
既定プロバイダを使う場合、BCryptGenRandomはNIST SP800-90が定めるCTR_DRBGというCSPRNG/DRBGの実装を担う。BCryptOpenAlgorithmProviderで別のアルゴリズムプロバイダを明示的に開いて使った場合、実装は指定したプロバイダに依存しCTR_DRBGとは限らない
.NETのRandomNumberGeneratorは暗号強度の高いCSPRNG/DRBGを利用して鍵やトークン用のバイト列・整数を返す
Linuxのgetrandom()はcryptographic purposesに使える乱数バイトを返すAPIとして文書化されている
Pythonのsecretsモジュールは、OSが提供する暗号学的に安全な乱数源を利用してトークンを生成する
JavaのSecureRandomは暗号用途を意識したCSPRNG/DRBGを利用する乱数生成クラスである
鍵・トークン・nonce・セッションIDのような、攻撃者に予測されると困る用途にはCSPRNG/DRBGおよびOS・言語標準のsecure RNG APIを使うことが推奨される
再現性重視の通常PRNGは内部状態やseedが漏れる・推測されると先が読まれやすいため、鍵・トークン・nonce・セッションIDのような用途には推奨されない
疑似乱数は同じseedなら同じ列が再現できるため、シミュレーションやテスト・デバッグでの再現比較に向いている
Pythonのrandomモジュールのような再現性重視の通常PRNGをセッションIDの生成に流用することは推奨されず、公式ドキュメントも秘密の管理にはsecretsを優先するよう案内している