PHP7の事故-私はラッキーですか?

PHP

この記事では、暗号化で使用される乱数の生成に関連する問題を分析します。 PHP5は暗号乱数を生成するための単純なメカニズムを提供しませんが、PHP7はCSPRNG関数を導入することでこの問題を解決します。

CSPRNGとは何ですか?


ウィキペディアを引用すると、暗号的に安全な擬似乱数ジェネレーター(CSPRNG)は、暗号化で使用できる特定のプロパティを持つ擬似乱数ジェネレーターです。

CSPRNGは、主に次の目的で使用されます。

高レベルのセキュリティを維持する主な側面は、高品質のランダム性です。

PHP7のCSPRNG


PHP7は、 random_bytesに使用できる2つの新しい関数random_bytesrandom_intます。

random_bytes関数は文字列を返し、入力パラメーターとして戻り値の長さ(バイト単位)を指定するintを受け取ります。

 $bytes = random_bytes(10); var_dump(bin2hex($bytes)); //possible ouput: string(20) "7dfab0af960d359388e6" 

random_intは、指定された範囲の整数を返します。

 var_dump(random_int(1, 100)); //possible output: 27 

オフスクリーン


上記の関数のランダム性の原因は、環境によって異なります。

簡単なテスト


優れた乱数生成システムは、世代の「品質」によって決まります。 それをテストするために、統計テストのセットがしばしば使用され、統計の複雑なトピックを掘り下げることなく、既知の参照動作をジェネレータの結果と比較し、その品質を評価するのに役立ちます。

最も簡単なテストの1つはサイコロです。 1つのボーンで6つが脱落する確率は6つに1つですが、3つのサイコロを100回投げると、1、2、および3つの6の予想される損失は次のようになります。

サイコロのロールを1,000,000回再生するコードは次のとおりです。

 $times = 1000000; $result = []; for ($i=0; $i < $times; $i++) { $dieRoll = array(6 => 0); //initializes just the six counting to zero $dieRoll[roll()] += 1; //first die $dieRoll[roll()] += 1; //second die $dieRoll[roll()] += 1; //third die $result[$dieRoll[6]] += 1; //counts the sixes } function roll() { return random_int(1,6); } var_dump($result); 

random_intと単純なrandを使用してrandom_intコードを実行random_int次の結果がrandom_intます。
シックス期待される結果random_intランド
0579000579430578179
1347000346927347620
2690006898569586
3500046584615

randrandom_intよりよく比較するために、式 PHP - / sqrt( )を使用して結果をプロットします。

グラフは次のようになります(ゼロに近いほど良い):
test random

3つの6での貧弱な結果とテストの単純さにもかかわらず、 randよりもrandom_int明らかな優位性があります。

PHP5はどうですか?


デフォルトでは、PHP5は強力な擬似乱数ジェネレーターを提供しません。 しかし、実際にはopenssl_random_pseudo_bytes()mcrypt_create_iv()または直接/dev/randomまたは/dev/urandomfread()を使用するなど、いくつかのオプションがあります。 RandomLiblibsodiumなどのライブラリもあります。

適切な乱数ジェネレーターの使用を開始すると同時に、PHP7に切り替える準備がまだ整っていない場合は、Paragon Initiative Enterprisesのrandom_compatライブラリを使用できます。 PHP 5.xプロジェクトでrandom_bytes()およびrandom_int()を使用できます。

ライブラリはComposerからインストールできます。

 composer require paragonie/random_compat 

 require 'vendor/autoload.php'; $string = random_bytes(32); var_dump(bin2hex($string)); // string(64) "8757a27ce421b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2aaec6f" $int = random_int(0,255); var_dump($int); // int(81) 

PHP7と比較して、 random_compatはわずかに異なる優先順位を使用します。
  1. fread() /dev/urandom利用可能な場合は/dev/urandom
  2. mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
  3. COM('CAPICOM.Utilities.1')->GetRandom()
  4. openssl_random_pseudo_bytes()


この順序がドキュメントで使用されている理由に関する詳細情報を読むことができます

ライブラリを使用してパスワードを生成する例:

 $passwordChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $passwordLength = 8; $max = strlen($passwordChar) - 1; $password = ''; for ($i = 0; $i < $passwordLength; ++$i) { $password .= $passwordChar[random_int(0, $max)]; } echo $password; //possible output: 7rgG8GHu 

簡単な要約


暗号的にrandom_compat擬似乱数ジェネレーターを常に使用する必要があり、 random_compatはこれに適したソリューションです。

信頼性の高いランダムデータのソースが必要な場合は、 random_intおよびrandom_bytesrandom_intしてrandom_bytes

関連リンク


Source: https://habr.com/ru/post/J272509/


All Articles