ECMAScript 仕様は Math.random()
が 0 以上 1 未満の値を返すことだけを決めている。
-
一様分布に近い乱数であればよく、アルゴリズムは実装依存。
-
シードを指定する仕組みはない。
V8 の実装
-
V8 は Xorshift128+ を使っている。
-
内部状態は 128 ビット(64bit ×2)。
-
キャッシュを持っていて、一度に 64 個の乱数を生成してバッファしておく。
-
通常は OS などのエントロピーからシードを決める。
--random-seed
フラグで固定シードも可能。
Xorshift128+ の特徴
-
高速で実装が軽い。
-
周期が有限で、線形構造があるので完全にランダムではない。
-
統計的にはそこそこ良いが、暗号的に安全ではない。
-
出力列を十分観測すれば内部状態を逆算できる可能性がある。
公平性・安全性の観点
-
再現性: デフォルトでは再現できない(シードが外部依存)。デバッグ用フラグを使えば再現可能。
-
予測可能性: アルゴリズムが線形なので理論上は予測できる。
-
公平性: 一応一様に近いが、制度的な用途(選挙候補者のランダム表示など)では不十分。
問題になるケース
-
選挙や抽選など「社会的公平性」が必要なとき。
-
攻撃者が出力を観測できる状況では将来の結果を予測され得る。
-
監査・検証が必要なシーンではシードが公開されないため不透明。
推奨される代替手法
-
crypto.getRandomValues()
を使う。これは CSPRNG で予測困難。 -
公開シード付き PRNG を使って再現性を担保する方法もある。
-
公的な乱数ビコン(例: NIST Randomness Beacon)を利用して外部監査を可能にする方法もある。
まとめ
-
V8 の
Math.random()
は日常用途や UI 演出には十分。 -
しかし公平性・透明性・操作耐性が必要なケースには不適。
-
そうした場合は CSPRNG や公開シード方式を組み合わせる必要がある。