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 や公開シード方式を組み合わせる必要がある。