最初に述べておく必要があるのは、コンピューターは完全な乱数を生成するのではなく、コンピューターは「疑似乱数」しか生成できないということです。 -乱数」。実際、絶対乱数は理想的な乱数にすぎません。コンピュータがどのように発達しても、完全に乱数の列は生成されません。コンピュータは比較的ランダムな数、つまり擬似乱数しか生成できません。
擬似乱数は擬似乱数ではありません。ここでの「擬似」とは規則的なという意味で、コンピューターが生成する擬似乱数はランダムであり規則的であるという意味です。どのように理解すればよいでしょうか?生成された擬似乱数は、特定のルールに従う場合もあれば、どのルールにも従わない場合もあります。一部の疑似乱数は、特定のルールに従いません。例えば、「世界に同じ形の葉は二つとない」ということは、物事の性質、つまりランダム性を指しますが、どの木の葉も同じような形をしている、つまり物事の共通性を指します。 、規則性。この観点から見ると、コンピュータは疑似乱数しか生成できず、完全な乱数を生成することはできないという事実をおそらく受け入れるでしょう。
まず、真の乱数と擬似乱数の概念を理解しましょう。
真の乱数発生器: 英語: true Random Number Generator、略称: TRNG は、予測不可能な物理的方法によって生成される乱数です。
擬似乱数ジェネレーター: 英語: pseudo-randomnumbergenerators、略称: PRNG は、特定のアルゴリズムを使用してコンピューターによって生成されます。
2 つの方法で生成された乱数の画像を比較してください。
Random.org (空中の雷雨によって生成される大気ノイズを使用して乱数を生成する) によって生成されたランダム ビットマップ:
Windows で PHP の rand() 関数によって生成されたランダムな画像:
明らかに、後者の疑似乱数発生器によって生成された画像には、これらの明らかな縞模様があります。
PHP の rand ランダム関数を使用してこの画像を生成するコードは次のとおりです:
コードをコピーします コードは次のとおりです:
// gd ライブラリを有効にする必要があります
header("コンテンツタイプ: image/png");
$im = imagecreatetruecolor(512, 512)
または die("新しい GD イメージ ストリームを初期化できません");
$white = imagecolorallocate($im, 255, 255, 255);
for ($y=0; $y
for ($x=0; $x
if (rand(0,1) === 1) {
imagesetpixel($im, $x, $y, $white);
}
}
}
imagepng($im);
imagedestroy($im);
実際、すべての擬似乱数ジェネレーター (PRNG) がそれほど悪いわけではなく、Windows 上の PHP の rand() 関数がたまたまこのようなものであるだけです。同じコードを Linux でテストすると、結果の画像には明らかな縞模様が表示されません。 Windows では、rand() 関数の代わりに mt_rand() 関数を使用すると、効果が大幅に向上します。これは、mt_rand() がメルセンヌ ツイスター アルゴリズムを使用して乱数を生成するためです。 PHP のドキュメントには、「mt_rand() は、libc が提供する rand() よりも平均 4 倍の速さでランダムな値を生成できる」とも記載されています。
さらに、Linux カーネル (1.3.30 以降) には、多くのセキュリティ目的に十分な乱数ジェネレーター /dev/random が含まれています。
以下は Linux 乱数ジェネレーターの原理の紹介です:
Linux オペレーティング システムは、本質的にランダムな (または少なくとも強いランダム性を持つコンポーネントを含む) ライブラリ データを提供します。通常、このデータはデバイス ドライバーから取得されます。たとえば、キーボード ドライバーは 2 つのキーを押す間の時間に関する情報を収集し、この周囲のノイズを乱数生成ライブラリに入力します。
ランダム データはエントロピー プールに保存されます (Linux カーネルは、デバイス ドライバーやその他のソースから環境ノイズを収集するためにエントロピー プールを維持します。理論的には、エントロピー プール内のデータは完全にランダムであり、真の乱数シーケンスを生成できます。エントロピー プール内のデータのランダム性。このプロセスは、エントロピー推定と呼ばれます。エントロピー推定は、値が大きいほど、データがプールに含まれる乱数を表します。 、データがよりランダムであるほど、プールはより良くなります。) 新しいデータが入ってくるたびに「撹拌」されます。この撹拌は、実際にはランダム性を改善するのに役立つ数学的変換です。データがエントロピー プールに追加されると、システムは取得した真にランダムなビットの数を推定します。
ランダム性の量を測定することが重要です。問題は、一部の量が最初に考えたときよりもランダムではないことがよくあることです。たとえば、最後のキーストロークからの秒数を表す 32 ビットの数値を追加しても、ほとんどのキーストロークは互いに近接しているため、実際には新しい 32 ビットのランダム情報は提供されません。
/dev/random からバイトが読み取られると、エントロピー プールは MD5 アルゴリズムを使用して暗号化ハッシュを実行し、ハッシュ内の個々のバイトが数値に変換されて返されます。
エントロピー プールに利用可能なランダム性ビットがない場合、/dev/random はプールに十分なランダム性が得られるまで、結果を返さずに待機します。つまり、/dev/random を使用して多数の乱数を生成すると、速度が遅すぎて実用的ではないことがわかります。 /dev/random が数十バイトのデータを生成した後、何秒も結果が得られないことがよくあります。
幸いなことに、この制限を回避できるエントロピー プールへの別のインターフェイス、/dev/urandom があります。この代替デバイスは、エントロピー プールに乱数が利用できない場合でも、常に乱数を返します。エントロピー プールを再充填するのに十分な時間を与えずに多くの数値を取り出すと、すべてのソースからエントロピーを組み合わせた利点が得られなくなりますが、エントロピー プールの MD5 ハッシュから非常に優れた乱数を取得することはできます。このアプローチの問題は、誰かが MD5 アルゴリズムを解読し、出力を見てハッシュされた入力について何かを学んだ場合、数値がすぐに完全に予測可能になってしまうことです。ほとんどの専門家は、そのような分析は計算的に実行不可能であることに同意しています。ただし、/dev/urandom は依然として /dev/random よりも「安全性が低い」(そして一般に疑わしい) と考えられています。
Windows では使用できる /dev/random はありませんが、Microsoft の「capicom.dll」によって提供される CAPICOM.Utilities オブジェクトを使用できます。
以下は、PHP を使用して mt_rand() 関数よりも優れた擬似乱数を生成するコード例です。
コードをコピーします コードは次のとおりです:
// 16 バイトの文字列内の 128 個の擬似乱数ビットを取得します
// Unix/Linux プラットフォーム?
$fp = @fopen('/dev/urandom','rb');
if ($fp !== FALSE) {
$pr_bits .= @fread($fp,16);
@fclose($fp);
}
if (@class_exists('COM')) {
試してみてください{
$CAPI_Util = 新しい COM('CAPICOM.Utilities.1');
$pr_bits .= $CAPI_Util->GetRandom(16,0);
// Base64 の戻り値をリクエストします
// ハッシュ化による冗長性と無駄 ==CRLF...
if ($pr_bits) { $pr_bits = md5($pr_bits,TRUE) }
} catch (例外 $ex) {
// エコー '例外: ' $ex->getMessage();
}
}