私はこれを持ったことがない。サイコロを転がす小さなプログラムをあらゆる言語で書くとしましょう(単にサイコロを例にして)。 60万回ロールした後は、それぞれの番号がおよそ10万回ロールされていたはずです。これが私の予想です。
なぜ「真の乱数性」に特化したWebサイトがあるのですか?確かに、上記の観察を与えられて、どんな数でも得ることの可能性はそれが選ぶことができるどれほど多くの数の上にほぼ正確に1です。
私は Pythonで試してみました :これは6000万ロールの結果です。最も高い変化は0.15のようです。それは得るのと同じくらいランダムではないですか?
1 - 9997653 2347.0
2 - 9997789 2211.0
3 - 9996853 3147.0
4 - 10006533 -6533.0
5 - 10002774 -2774.0
6 - 9998398 1602.0
Eric Lippertが言うように、それは単なる配布ではありません。ランダムネスを測定する他の方法があります。
初期の乱数発生器の1つは最下位ビットにシーケンスがあります - それは0と1を交互にします。したがって、LSBは100%予測可能でした。しかし、それ以上のことを心配する必要があります。各ビットは予測不能でなければなりません。
これは問題について考えるよい方法です。 64ビットのランダムネスを生成しているとしましょう。それぞれの結果について、最初の32ビット(A)と最後の32ビット(B)を取り、インデックスを配列x [A、B]にします。テストを100万回実行し、それぞれの結果について、その数、すなわちX [A、B] ++で配列をインクリメントします。
2次元図を描きます。数字が大きいほど、その位置のピクセルは明るくなります。
それが本当にランダムであるならば、色は一様な灰色であるべきです。しかし、あなたはパターンを得るかもしれません。たとえば、Windows NTシステムのTCPシーケンス番号の「ランダムさ」の図を見てください。
あるいはWindows 98からのものでさえ:
そしてこれはCiscoルータ(IOS)実装のランダム性です。
これらの図は、 MichałZalewskiの論文 によるものです。この特定の場合、TCPシーケンス番号がシステムのものになることを予測できれば、他のシステムに接続するときにそのシステムを偽装できます。これにより、接続のハイジャック、通信の傍受が可能になります。そして、次の数を100%予測することができなくても、新しい接続を作成させることができればを私たちの制御下でにすれば、増やすことができます。成功のチャンスそして、コンピュータが数秒で10万の接続を生成できる場合、攻撃が成功する可能性は、天文学的なものから可能なもの、さらにはありそうなものまであります。
コンピュータによって生成された疑似乱数は、コンピュータユーザが遭遇するユースケースの大部分には適していますが、 完全に 予測不可能な乱数が必要なシナリオがあります。
暗号化などのセキュリティに注意を要するアプリケーションでは、擬似乱数生成器(PRNG)が、外観上はランダムではあるが実際に攻撃者によって予測可能な値を生成する可能性があります。 PRNGが使用され、攻撃者がPRNGの状態に関する情報を持っている場合、暗号化システムを解読しようとしている誰かが暗号化キーを推測できるかもしれません。したがって、そのようなアプリケーションでは、本当に推測できない値を生成する乱数発生器が必要です。 PRNGの中には暗号的に安全な になるように設計されているものがあり、そのようなセキュリティに敏感なアプリケーションに使用できることに注意してください。
RNG攻撃に関するさらなる情報は このWikipediaの記事 にあります。
Pythonで試してみました:6,000万回のロールの結果です。最も高い変動は0.15のようなものです。それは手に入れるほどランダムではありませんか?
実際、それはとても「良い」それは悪いです...すべての既存の答えは予測可能性初期値の小さなシーケンスを指定します。別の問題を提起したい:
あなたの分布は、ランダムロールがすべきよりもはるかに小さい標準偏差を持っています
真のランダム性はまったく得られませんthat品質の指標として使用している「選択できる数字の数に対してほぼ正確に1」の平均に近い。
このStack複数のサイコロロールの確率分布に関するExchangeの質問 を見ると、N個のサイコロロールの標準偏差の式が表示されます(真にランダムな結果と仮定):
sqrt(N * 35.0 / 12.0).
その式を使用すると、標準偏差:
結果を見ると:
有限サンプルの標準偏差が式と完全に一致するとは期待できませんが、かなり近い値になるはずです。しかし、100万のロールでは、適切なstddevの半分以下であり、6000万では3分の1未満です-悪化しつつあり、それは偶然ではありません。
疑似RNGは、シードから始まり、特定の期間元の数値を再訪せずに、一連の個別の数値を移動する傾向があります。たとえば、古いCライブラリRand()
関数の実装は通常2 ^ 32の期間を持ち、シードを繰り返す前に0から2 ^ 32-1までのすべての数値を正確に1回訪問します。したがって、2 ^ 32のサイコロをシミュレートすると、モジュラス(%
)の結果には0から2 ^ 32までの各数値が含まれ、1-6の結果ごとのカウントは715827883または715827882(2 ^ 32上記の式を使用すると、2 ^ 32ロールの正しい標準偏差は111924です。とにかく、擬似ランダムロールの数が増えるにつれて、 0標準偏差。ロールの数が期間のかなりの部分である場合、この問題は重大であると予想されますが、一部の疑似RNGは他のものよりも悪い問題、またはサンプルが少ない場合でも問題を示す場合があります。
そのため、暗号の脆弱性を気にしなくても、一部のアプリケーションでは、結果が過度に、人工的にさえない分布を気にする場合があります。いくつかのタイプのシミュレーションは、個別にランダムな結果の大きなサンプルで自然に発生するneven結果の結果をうまく処理しようとしていますが、一部のpRNGの結果では不十分です。巨大な人口が何らかのイベントにどのように反応するかをシミュレートしようとしている場合、この問題はradically結果を変更し、非常に不正確な結論を導きます。
具体例を挙げると、数学者がポーカーマシンプログラマーに、6000万回のシミュレートされたロールの後、数学者が予想する10,013,229以上の6があった場合、画面の周りに何百もの小さな「ライト」を点滅させると言います平均から1 stddev、少額の支払いが必要です。 68–95–99.7ルール(Wikipedia) ごとに、これは16%の時間(〜68%低下)について発生するはずです標準偏差内/外部の半分のみが上)。乱数ジェネレーターの場合、これは平均を上回る約3.5標準偏差から得られます。アンダー0.025%チャンス-このメリットを得る顧客はほとんどいません。具体的には、前述のページの高偏差の表を参照してください。
| Range | In range | Outside range | Approx. freq. for daily event |
| µ ± 1σ | 0.68268... | 1 in 3 | Twice a week |
| µ ± 3.5σ | 0.99953... | 1 in 2149 | Every six years |
私はただダイスロールを生成するためにこの乱数ジェネレータを書いた
def get_generator():
next = 1
def generator():
next += 1
if next > 6:
next = 1
return next
return generator
あなたはこのようにそれを使います
>> generator = get_generator()
>> generator()
1
>> generator()
2
>> generator()
3
>> generator()
4
>> generator()
5
>> generator()
6
>> generator()
1
あなたはダイスゲームを実行したプログラムのためにこのジェネレータを使用して幸せですか?覚えておいて、その分布はまさにあなたが "真にランダムな"ジェネレータから期待するものである!
疑似乱数生成器は本質的に同じことをします - それらは正しい分布で予測可能な数を生成します。上記の単純化された乱数ジェネレータが悪いのと同じ理由で、これらは良くありません - 正しい分布だけではなく、本物の予測不可能性が必要な状況には適していません。
あなたのコンピュータが実行できる乱数生成はほとんどのニーズに適しています、そしてあなたが本当に乱数を必要とする時に遭遇することはまずありません。
真の乱数生成には目的があります。コンピュータセキュリティ、ギャンブル、大規模統計サンプリングなど.
乱数のアプリケーションに興味があるなら、 ウィキペディアの記事 をチェックしてください。
ほとんどのプログラミング言語の典型的な関数によって生成される乱数は、純粋な乱数ではありません。それらは疑似乱数です。それらは純粋に乱数ではないので、それらは以前に生成された数に関する十分な情報で推測することができます。そのため、これは暗号化におけるセキュリティ上の災害になります。
例として、glibc
で使用されている次の乱数生成関数は純粋に乱数を生成しません。これにより生成された擬似乱数が推測できる。セキュリティの問題では間違いです。これが悲惨になる歴史があります。これは暗号化では使用しないでください。
glibc random():
r[i] ← ( r[i-3] + r[i-31] ) % (2^32)
output r[i] >> 1
このタイプの疑似乱数ジェネレータは、統計的にはるかに重要であっても、セキュリティに敏感な場所では決して使用されるべきではありません。
擬似ランダムキーに対する有名な攻撃の1つは、802.11b WEPに対する攻撃です。 WEPには104ビットの長期キーがあり、24ビットのIV(カウンタ)と連結して128ビットのキーになります。これをRC4アルゴリズムに適用して擬似ランダムキーを生成します。
( RC4( IV + Key ) ) XOR (message)
鍵は互いに密接に関連していました。ここでは、各ステップでIVが1だけ増加し、他はすべて同じままでした。これは純粋にランダムではなかったので、それは悲惨であり、そして容易に分解されました。鍵は、約40000フレームを分析することで回復できます。これは数分の問題です。 WEPが純粋にランダムな24ビットIVを使用した場合、それは約2 ^ 24(ほぼ1680万)フレームまで安全です。
そのため、セキュリティが重要な問題では、可能な限り純粋な乱数ジェネレータを使用する必要があります。
違いは、擬似乱数が実際の乱数ではない場合、しばらくすると予測可能になる(繰り返す)ことです。繰り返すのにかかる長さは、その生成に使用されるシードの長さによって異なります。
これはそのトピックについてのかなりいいビデオです: http://www.youtube.com/watch?v=itaMNuWLzJo
私が今までに使った最初の乱数は、任意の2つの連続した乱数のうち、2番目のものは0.6の確率でもっと大きいという優れた性質を持っていました。 0.5ではありません。そして3番目は確率0.6で2番目より大きかった、という具合です。あなたはそれがシミュレーションでいかに破壊的な役割を果たすか想像することができます。
乱数が均等に分布していてもこれは可能だとは思わない人もいましたが、順序を見れば明らかに可能です(1、3、5、2、4、1、3、5、2、4、 ...)2つの数値のうち2番目の数値は、確率0.6で大きくなります。
一方、シミュレーションでは、乱数を再現できることが重要です。あなたが交通シミュレーションをしていて、あなたが取るかもしれないある行動が交通を改善することができる方法を見つけたいとしましょう。その場合は、トラフィックを改善するためにさまざまなアクションを実行して、まったく同じトラフィックデータ(町に入ろうとしている人々のように)を再作成できるようにする必要があります。
疑似乱数は、生成される前にだれでも推測できると仮定します。
あなたの例のように、些細なアプリケーションでは、擬似乱数性は問題ありません、あなたは(あなたがあなたが600kのダイスを振るべきであったかどうかわかるでしょう)若干の小さな変化でおよそ正しいパーセンテージ(全結果セットのおよそ1/6)を得るでしょう回);
しかし、コンピュータセキュリティのようなことになると。真のランダム性が必要です。
たとえば、RSAアルゴリズムは、コンピュータが2つの乱数(PとQ)を選択してから、それらの数にいくつかの手順を実行して、公開鍵と秘密鍵として知られる特別な番号を生成します。 (秘密鍵の重要な部分は、それが秘密鍵であるということです。他に誰もそれを知りません!)
攻撃者があなたのコンピュータが選択しようとしている2つの「乱数」を知ることができれば、彼らはあなたの秘密鍵を計算するために同じステップを実行することができます。
あなたの秘密鍵を使って攻撃者は次のようなことをすることができます。b)あなたのふりをしてあなたの銀行に話しかける、b)あなたの「安全な」インターネットトラフィックを聞いてそれを解読できる、c)あなたとインターネット上の他者との間のなりすまし。
それが、真の無作為性(つまり、推測/計算できないこと)が必要な場合です。
簡単な答えは、通常人々は悪い理由で「真の乱数性」を必要とする、すなわち彼らは暗号化について理解していないということです。
ストリーム暗号 や CSPRNG などの暗号化プリミティブは、巨大なストリームを生成するために使用されます。いくつかの予測不可能なビットが供給された後の予測不可能なビットの数。
注意深い読者は、ここでブートストラップの問題があることに気付いたでしょう。それから、それらをa CSPRNG に送ることができます。これにより、必要なすべての予測不可能なビットが順調に提供されます。したがって、ハードウェアRNGはCSPRNGをシードするために必要です。エントロピーが真実で必要とされる唯一のケースです。
(私はこれはセキュリティまたは暗号化で掲示されるべきだったと思います。)
編集:最後に、想定されるタスクに十分な乱数ジェネレータを選択する必要があります。乱数生成に関する限り、ハードウェアは必ずしも同等とは限りません。悪いPRNGと同じように、ハードウェアランダムソースには通常バイアスがあります。
編集:ここにいる何人かの人々は、攻撃者がCSPRNGの内部状態を読み取ることができ、そこからCSPRNGは安全な解決策ではないという結論に至る脅威モデルを想定しています。これは貧弱なスレッドモデリングの例です。攻撃者があなたのシステムを所有していれば、ゲームは終わり、わかりやすく単純です。この時点でTRNGとCSPRNGのどちらを使用しても、違いはありません。
編集:だから、これらすべてをまとめるには... CSPRNGをシードするにはエントロピーが必要です。これが行われると、CSPRNGは、(通常)エントロピーを収集するよりもはるかに高速に、セキュリティアプリケーションに必要な予測不可能なビットをすべて提供します。シミュレーションのように予測不可能性が要求されない場合、Mersenne Twisterははるかに高い割合で優れた統計的性質を持つ数を提供します。
編集:安全な乱数生成の問題を理解して喜んで誰でもこれを読む必要があります。 http://www.cigital.com/whitepapers/dl/The_Importance_of_Reliable_Randomness.pdf
すべてのPRNGがすべての用途に適しているわけではありません。たとえば、Java.util.SecureRandomは、出力サイズが160ビットのSHA1ハッシュを使用します。それは2があることを意味します160 そこから来る可能性がある乱数の可能なストリーム。そのような単純な。 2以上になることはできません160 内部状態の値したがって、あなたは2を超えることはできません160 あなたの種がどこから来たかにかかわらず、単一の種からの乱数のユニークな流れ。 Windows CryptGenRandomは40バイトの状態を使用すると考えられています、それは2を持っています320 乱数の可能なストリーム.
標準の52カードデッキをシャッフルする方法の数は52です、それはおよそ2です226。したがって、シードに関係なく、Java.util.SecureRandomを使用してカードのデッキをシャッフルすることはできません。約2つあります66 それが作り出すことができない可能性のあるシャッフル。もちろん、我々は彼らがどれであるかわかりません...
したがって、たとえば256ビットの真のランダム性(たとえば、Quantis RNGカードから)のソースがある場合は、CryptGenRandom()のようなPRNGをそのシードで使用してから_を使用できます。PRNGカードのデッキをシャッフルする。各シャッフルを真のランダムさで再シードすると、これは問題ありません。予測不可能で統計的にランダムです。私がJava.util.SecureRandomで同じことをした場合、256ビットのエントロピーを蒔くことができず、その内部状態がすべての可能なシャッフルを表すことができないため、おそらく生成できないシャッフルがあるでしょう。
Java.util.SecureRandomの結果は予測不可能であり、統計的にランダムでもあることに注意してください。統計的テストで問題を特定することはできません。しかし、RNGの出力は、カードのデッキをシミュレートするために必要なすべての可能な出力の全領域をカバーするのに十分な大きさではありません。
ジョーカーを追加した場合、それは54です。あなたがカバーしなければならないこと、それは約2が必要です238 可能性.
「真の」乱数と「疑似」乱数の違いは予測可能性です。この答えはすでに提供されています。
しかし、ほとんどの例が示しているように、予測可能性は必ずしも悪いことではありません。予測可能性が良好であるまれなケースの1つの実用的な例はここにあります:全地球測位システム。
各衛星は、測定に必要な自己相関または相互相関に適した個別のPRNコード( ゴールドコード )を使用します。信号伝搬時間これらのゴールドコードについては、互いの間の相関は特に弱く、衛星の明確な識別を可能にするが、放射されたシーケンスと受信機との間の相関による距離計算を可能にする。
擬似乱数は、数学関数と初期値(シードと呼ばれる)を使用して生成されますが、乱数は生成されません。あなたは種とプレイヤーの入力を保存するだけでよいので、それらの予測可能性はそれらを信じられないほどゲームリプレイに有用にします - AIは全く同じように反応する毎回ランダム」.
ランダム性をすばやくチェックするには、[0; 1)にランダムな座標を持つ点を取り、それらをk次元の立方体に配置します。次に、この立方体をサブキューブにスライスする手順を実行します。サブキューブ(またはサブスフィア)の各ボリュームは、よく知られた定理に従って、この手順で正しく測定する必要があります。
ランダム性の質はあなたが出会うところで重要です...
セキュリティ目的あなたがあなたのキー生成のためのパラメータとして使用するための数を生成するとき、そしてそれはよく予測可能です - 敵は100%の確率でそれを見つけ出し、そして検索のためのフィールドをずっと小さくします。
科学的な目的科学では、平均値が良い状態であるだけでなく、さまざまな乱数間の相関も排除されなければなりません。したがって、(a_i - a)(a_ {i + 1} -a)を求めてその分布を見つけた場合、それは統計量に対応していなければなりません。
対相関は、いわゆる「弱いランダムネス」です。あなたが本当の無作為性を望むならば、あなたは2つ以上の分散と高次相関を持たなければなりません。
今日では、量子力学ジェネレータだけが真のランダム性を提供しています。
なぜ真のランダム性が重要なのでしょうか。
真の乱数が必要なのには、基本的に2つの主な理由があります。
これらの分野以外では、それは重要ではありません。警告:あなたのPRNGが非常に、非常に悪い場合でも、それはまだ不適切であるかもしれません - あなたはサイコロが常に出てくるクラップスゲームを作りたくない、あなたのプレイヤーはそれを好きではないでしょう。
PythonのPRNGはどうして十分ではないのでしょうか。
そのような単純な方法論を使用することで、実際のPRNGの落とし穴を検出できる可能性はほとんどありません。 RNGの統計分析はそれ自体が科学の分野であり、アルゴリズムの「ランダム性」をベンチマークするためにいくつかの非常に洗練されたテストが利用可能です。これらはあなたの単純な試みよりもはるかに高度です。
Python開発者のような実世界のライブラリを作成するすべてのソフトウェア開発者は、それらのPRNG実装が十分に良いかどうかを確認するための基準としてこれらの統計的検定を使います。そのため、実際の開発者による監視を除いて、現実のPRNGでパターンを簡単に検出できる可能性はほとんどありません。それはパターンがないという意味ではありません - PRNGは定義上パターンを持ちます。
基本的に、あなたはソースが出力の数学分析によってランダムであることを証明することはできません、あなたは必要とします。線源がランダムであると言う物理モデル(放射能崩壊のように)。
バッチテストを実行するだけで、出力データの統計的相関を見つけることができます。その場合、データはランダムではないことが証明されます(ただし、ランダムソースはランダムでない出力を持つことができます。出力)。そうでなければテストに合格すれば、データは疑似乱数であると言えます。
いくつかの乱数性テストに合格することはあなたが良いPRNG(擬似乱数生成器)を持っていることを意味するだけであり、それはセキュリティが関与していないアプリケーションに役に立ちます。
セキュリティが必要な場合(暗号化、キーソルトの生成、ギャンブルのための乱数生成など)は、PRNGを有効にするだけでは十分ではありません。前の出力から容易に推測できるように、関数は望ましい計算コスト(使用可能に制限されていますが、ブルートフォースの試みを打ち負かすには十分に高い)を持っている必要があります。アナログ機器 - 簡単に改ざんされるべきではない、など。
良いPRNGを持つことは、新しい予測不可能なパターンを作成するゲームや暗号化に役立ちます。単一の記事で説明するのは面倒すぎます。ランダムで、以前の暗号化データを次の暗号化データに関連付けることも、プレーンテキストデータを暗号化データに関連付けることも、2つの異なる暗号テキストを互いに関連付けることもできません(したがって、プレーンテキストに対して推測できます)。