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

   PHP



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



CSPRNGとは何ですか?



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



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



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



PHP7のCSPRNG



PHP7は、 random_bytes



に使用できる2つの新しい関数random_bytes



random_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 ランド
0 579000 579430 578179
1 347000 346927 347620
2 69000 68985 69586
3 5000 4658 4615


rand



random_int



よりよく比較するために、式 PHP



-



/ sqrt( )



を使用して結果をプロットします。



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

 test random






3つの6での貧弱な結果とテストの単純さにもかかわらず、 rand



よりもrandom_int



明らかな優位性があります。



PHP5はどうですか?



デフォルトでは、PHP5は強力な擬似乱数ジェネレーターを提供しません。 しかし、実際にはopenssl_random_pseudo_bytes()



mcrypt_create_iv()



または直接/dev/random



または/dev/urandom



fread()



を使用するなど、いくつかのオプションがあります。 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_bytes



random_int



してrandom_bytes







関連リンク






All Articles