ランダムジェネレーター:仕組みと使用タイミング

· 13分で読めます

ランダムジェネレーターはどこにでもあります。プレイリストをシャッフルしたり、パスワードを生成したり、シミュレーションを実行したり、ビデオゲームをプレイしたりするたびに、乱数生成器が裏で動いています。しかし、正確な指示に従う決定論的なマシンであるコンピューターが、どのようにランダム性を生み出すのか疑問に思ったことはありませんか?その答えは、あなたが予想するよりも魅力的で(そしてより微妙で)す。

このガイドでは、ランダムジェネレーターの背後にある科学と工学を探ります。真の乱数と疑似乱数の違い、一般的なアルゴリズムの仕組み、暗号グレードのランダム性が必要な場合、そして日常生活に影響を与える実用的なアプリケーションについて説明します。適切なランダム関数を選択する開発者、確率について学ぶ学生、または単に物事の仕組みに興味がある方、このガイドはあなたをカバーします。

ランダム性とは?より深い考察

ランダム性は直感的に思えます — それは予測不可能性、混沌、パターンの欠如です。しかし、ランダム性を正確に定義することは驚くほど難しく、数学者たちは何世紀にもわたってそれについて議論してきました。

最も厳密な意味では、すべての以前の値を完全に知っていても、どのアルゴリズムも推測よりも次の値を予測できない場合、シーケンスは真にランダムです。これはコルモゴロフランダム性と呼ばれます — シーケンスがより短い記述に圧縮できない場合、それはランダムです。例えば、円周率の桁はランダム性のすべての統計的テストに合格しますが、完全に決定論的です(十分な計算があれば任意の桁を計算できます)。

実用的な目的では、ランダム性の3つの特性を気にします:

異なるアプリケーションには、これらの特性の異なるレベルが必要です。サイコロを振るゲームには一様性と独立性が必要ですが、必ずしも予測不可能性は必要ありません。パスワードジェネレーターには3つすべてが必要です。アプリケーションが必要とするランダム性の種類を理解することが、適切なジェネレーターを選択する最初のステップです。

真の乱数と疑似乱数:根本的な違い

すべてのランダムジェネレーターは2つのカテゴリーに分類され、その区別は正確性とセキュリティの両方にとって非常に重要です。

真の乱数生成器(TRNG)

真の乱数生成器は、根本的に予測不可能な物理現象からランダム性を導き出します:

TRNGの重要な特性は、その出力が再現不可能であることです。同一の機器と条件でも、毎回異なるシーケンスが得られます。これは、再現性が致命的な欠陥となる暗号アプリケーションにとって不可欠です。

疑似乱数生成器(PRNG)

PRNGはアルゴリズムです — ランダムに見える数値のシーケンスを生成する決定論的な数学的公式ですが、初期状態(シードと呼ばれる)が与えられれば完全に予測可能です。PRNGに同じシードを与えると、毎回まったく同じシーケンスが生成されます。

これは弱点のように聞こえるかもしれませんが、実際には多くのアプリケーションにとって機能です:

課題は、出力が真のランダム性と統計的に区別できないPRNGを設計することです — 一様性、独立性、パターンの欠如に関するすべての既知の統計的テストに合格することです。

🎲 ジェネレーターを試す

乱数ジェネレーター → パスワードジェネレーター →

疑似乱数生成器(PRNG)の仕組み

その核心において、PRNGは内部状態を維持し、各呼び出しでそれを変換し、出力を生成し、次回のために状態を更新します。PRNGの品質は、その変換がパターンと相関をどれだけうまく回避するかに依存します。

線形合同法(LCG)

最もシンプルで最も古いPRNGファミリーであるLCGは、次の式を使用します:

state = (a × state + c) mod m
output = state

ここで、a(乗数)、c(増分)、m(法)は慎重に選択された定数です。例えば、古典的なMINSTDジェネレーターはa = 16807c = 0m = 2³¹ - 1を使用します。LCGは非常に高速(乗算と剰余演算)ですが、よく知られた弱点があります:連続する値は高次元でプロットするとパターンを示し、下位ビットは短い周期でサイクルします。ほとんどの最新アプリケーションはLCGを超えて進化しています。

メルセンヌ・ツイスター(MT19937)

メルセンヌ・ツイスターは、1997年の導入以来、多くの言語とシステムでデフォルトのPRNGとなっています。624個の32ビット整数の状態を維持し、2¹⁹⁹³⁷ - 1(メルセンヌ素数、したがってこの名前)の周期を持ちます。その周期は天文学的に長く — 観測可能な宇宙の原子の数をはるかに超えています。

アルゴリズムは次のように動作します:

  1. シードから624個の状態値を初期化
  2. 各乱数について、ビットシフトとXOR演算を通じて状態値を抽出し「テンパリング」
  3. ツイスト変換を使用して状態配列全体を定期的に再生成

メルセンヌ・ツイスターはほとんどの統計的テストに合格し、シミュレーション、ゲーム、汎用用途に優れています。ただし、暗号学的に安全ではありません — 624個の出力を観察すると、完全な内部状態を再構築し、すべての将来の値を予測できます。

Xoshiro256**と最新のPRNG

xoshiro256**(多くの最新言語で使用)やPCG(Permuted Congruential Generator)などの新しいPRNGは、古いジェネレーターの欠点に対処します。それらは以下を提供します:

JavaScriptのMath.random()

JavaScriptでMath.random()を呼び出すと、最新のエンジン(V8、SpiderMonkey、JavaScriptCore)はxorshift128+を使用します。これは優れた統計的特性を持つ高速なPRNGです。0(含む)から1(含まない)の間の浮動小数点数を生成します。ゲーム、シャッフル、ランダム選択には完全に適していますが、セキュリティに敏感な目的には決して使用すべきではありません。

// minとmaxの間の基本的な乱数(両端を含む)
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 配列からランダムな要素
function randomChoice(array) {
  return array[Math.floor(Math.random() * array.length)];
}

// 配列をシャッフル(フィッシャー・イェーツアルゴリズム)
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

暗号学的ランダム性:セキュリティが重要な場合

セキュリティアプリケーション — パスワード、暗号化キー、セッショントークン、ノンス — では、通常のPRNGは危険なほど不十分です。攻撃者があなたの乱数を予測できれば、セキュリティモデル全体を危険にさらす可能性があります。

CSPRNGを異なるものにするものは何ですか?

暗号学的に安全な疑似乱数生成器(CSPRNG)は、重要な特性を追加します:前方および後方秘匿性。攻撃者が現在の内部状態を発見しても、以前の出力を決定できません(後方秘匿性)。そして、状態を知らずに過去の出力から将来の出力を予測することは計算上実行不可能です。

CSPRNGは次の方法でこれを達成します:

一般的なCSPRNG

実際に暗号学的ランダム性を使用する

ブラウザでは、Web Crypto APIが暗号グレードのランダム性を提供します:

// 暗号学的に安全な乱数整数を生成
function secureRandomInt(min, max) {
  const range = max - min + 1;
  const bytesNeeded = Math.ceil(Math.log2(range) / 8);
  const maxValid = Math.floor(256 ** bytesNeeded / range) * range - 1;

  let value;
  do {
    const array = new Uint8Array(bytesNeeded);
    crypto.getRandomValues(array);
    value = array.reduce((acc, byte, i) => acc + byte * (256 ** i), 0);
  } while (value > maxValid); // 偏った値を拒否

  return min + (value % range);
}

// 安全なランダムパスワードを生成
function generatePassword(length = 16) {
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
  const array = new Uint32Array(length);
  crypto.getRandomValues(array);
  return Array.from(array, x => chars[x % chars.length]).join('');
}

暗号グレードのランダム性にWeb Crypto APIを使用するパスワードジェネレーターで安全なパスワードを生成してみてください。

エントロピー:ランダム性の燃料

ランダム性の文脈におけるエントロピーは、システム内の真の予測不可能性の量を測定します。ビット単位で測定されます — 1ビットのエントロピーは、攻撃者が予測できない1つのバイナリ選択を意味します。

エントロピーはどこから来るのですか?

オペレーティングシステムは複数のソースから継続的にエントロピーを収集します:

We use cookies for analytics. By continuing, you agree to our Privacy Policy.