2

This is a long question to read so Question in short is, is it secure to depend on PHP's rand function for generating first time password?

In my free time, I was just thinking of a logic to make very difficult custom password generator (only digits), a feature that I might need in my next project.

First thing that come in mind is PHP's rand() method. I tried few test around rand method to test its random behaviour. As general, it first come to mind that generating more than one random number and doing some operation on that will make random number more difficult to guess. I was surprised to see that average of random numbers is very near to its half using following program:

$minAvg=$maxAvg=50;
for($i=1;$i<=1000;$i++){
    //Random average
    $sum=0;
    for($j=0;$j<1000;$j++){
        $sum=$sum+rand(1,100);
    }
    $avg=$sum/1000;
    ///

    if($avg<$minAvg){
        $minAvg=$avg;
    }
    if($avg>$maxAvg){
        $maxAvg=$avg;
    }
    if($i%100==0)
    {
        echo "at i=$i, Min Avg = $minAvg and Max Avg = $maxAvg <br/>";
    }
}

One output of above code was:

at i=100, Min Avg = 47.174 and Max Avg = 53.003
at i=200, Min Avg = 47.174 and Max Avg = 53.003
at i=300, Min Avg = 47.174 and Max Avg = 53.003
at i=400, Min Avg = 47.174 and Max Avg = 53.003
at i=500, Min Avg = 47.174 and Max Avg = 53.192
at i=600, Min Avg = 47.174 and Max Avg = 53.192
at i=700, Min Avg = 47.174 and Max Avg = 53.192
at i=800, Min Avg = 47.174 and Max Avg = 53.192
at i=900, Min Avg = 47.174 and Max Avg = 53.204
at i=1000, Min Avg = 47.174 and Max Avg = 53.204 

I run above code at least 50 times but even after 1000 iteration, average always remain between 47.xx to 53.xx (for random numbers between 1 & 100)

Although this result doesn't tells a lot as generally average of few numbers must come near middle but I didn't expected same behaviour for random numbers. I feel it show PHP's rand() use some fixed algorithm which generate numbers in a given pattern. As far as I understand, this is only justified reason for average to remain near middle.

Till now I was using random numbers frequently to generate first time password (which was forcefully changed during first login). However now I'm little worried if it is safe to use random numbers for generating first time passwords of sites which involve financial transaction and sensitive info like credit card numbers (although encrypted). Is there any possibility for hackers (not amateur but professional hackers) to break such passwords with easy? Most important, is there any algorithm to detect (or at least estimate) next random number.

Edit Well to make it more sensible, user will be registered offline for example like opening bank account and printed first time password will be sent through Post, not by email. So password must remain under 10 characters which rules out any encryption.

4

4 に答える 4

3

rand()は暗号強度のRNGではありませんが、ここでは重要ではありません。

ランダムなパスワードから必要なのは、ランダムな推測が実行できないほど予測不可能である必要があるということだけです。このプロパティは、パスワードの長さと許可された文字プールと関係がありますrand()

さらに、ブルートフォースに対する最善の防御策は、ログイン試行の間に意図的な遅延を導入することです。これを行い、「合理的にランダムな」パスワードを使用している場合、ブルートフォース攻撃を受ける方法はまったくありません。

そして最後に、内部では線形合同rand()法を使用して実装されます。サーバーがほとんどの時間をパスワードの生成に費やす場合を除いて(非常に疑わしい) 、メルセンヌツイスターの実装であるに切り替えることで「より良い」ランダム性を得ることができます(まだ暗号強度ではありません)。mt_rand()

于 2012-10-31T10:05:31.933 に答える
1

One relatively simple way to generate secure random numbers in php is mcrypt_create_iv with MCRYPT_DEV_URANDOM as $source. i.e. mcrypt_create_iv(size, MCRYPT_DEV_URANDOM). Then transform the resulting random bytes into whatever form you need.

于 2012-11-01T15:21:16.490 に答える
1

PHP uniqidはあなたが探しているものです。使用例:

$code = uniqid(rand(), true);

より安全な関数openssl_random_pseudo_bytes()があることに注意してください。ただし、PHP>5.3 でのみ使用できます。

于 2012-10-31T09:59:55.177 に答える
0

反対票を投じる前に、質問を読んでから、問題の解決策として以下を読んでください。ありがとうございます。

電子メールを使用して「初めて」のパスワードを送信するなど、パスワードの予測可能性よりもはるかに安全でないことをしているのです。

パスワードの生成に固執する場合でも、初めて自動ログインURLを送信する別の方法を使用する場合でも(私がお勧めします)、URLのパスワードまたは秘密鍵の予測可能性を防ぐ必要があります。

あなたはこのような非常に長い秘密の塩を持っている必要があります(キーボードランダムは問題ありません) $salt="aslkfhaqoiey19836y9qasdhkasjdhbknmxcbnzmbAkua089610":。

次に、rand()を使用して、URLの初回パスワードまたはキーを作成しますが、md5およびその非常に長いソルトと組み合わせます。ソルトは秘密なので、md5がどうなるかは誰にも予測できません。

$randomPassword=base64_encode(md5(rand().rand().$salt, true));

于 2012-10-31T10:01:34.397 に答える