暗号学的安全な乱数を、バイアスなしで生成します
ブラウザの crypto.getRandomValues() を使います。
これは OS が収集した物理的なエントロピー(CPU のタイミングジッター、
割り込みタイミング、ハードウェアノイズなど)を元に生成されており、
Math.random() のような単純な線形合同法や Xorshift と異なり、
予測が計算量的に不可能です(NIST SP 800-90A 準拠)。
範囲 [min, max] の幅を range とするとき、
バイト列を整数に変換した値をそのまま % range すると、
乱数空間 256n が range で割り切れない場合に
小さい値が出やすくなる モジュロバイアス が生じます。
このサイトでは 棄却サンプリング で解決します:
バイアスが発生しない上限値 maxValid を計算し、
その範囲外の値が出たら再抽選します。
// バイアスのない [min, max] の整数を返す function secureRandom(min, max) { const range = max - min + 1; const byteLen = Math.ceil(Math.log2(range) / 8) || 1; const maxValid = Math.floor(256 ** byteLen / range) * range; let value; do { const bytes = new Uint8Array(byteLen); crypto.getRandomValues(bytes); value = [...bytes].reduce((acc, b, i) => acc + b * 256 ** i, 0); } while (value >= maxValid); // バイアス域を棄却 return min + (value % range); }
マウス移動・タッチ・キー入力のタイミング(performance.now() の
高精度タイムスタンプ)をリングバッファに蓄積し、XOR で内部状態に混合します。
これは CSPRNG を置き換えるのではなく、
OS エントロピーに上乗せする 追加の撹乱 です。
エントロピーバーはこの蓄積量を視覚化しています。
| 手法 | 予測耐性 | バイアスなし | 用途 |
|---|---|---|---|
| Math.random() | ✗ 低い | ✗ あり | ゲーム・UI |
| 線形合同法 | ✗ 低い | ✗ あり | シミュレーション |
| Mersenne Twister | △ 中程度 | ○ ほぼなし | 統計・科学計算 |
| このサイト (CSPRNG) | ✓ 非常に高い | ✓ 棄却法で排除 | 暗号・抽選・セキュリティ |