什么时候apache中的mod_php播种随机数生成器?

时间:2014-10-23 23:01:02

标签: php apache random

我正在使用php rand()函数为我的电子商务系统生成优惠券代码。 它工作正常一段时间,但现在我收到很多错误,代码已经存在于系统中。

这是我使用的功能:

function generateRandomString($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}   

我的代码长度为32个字符。

我做了大约150次尝试的样本,发现超过50%的生成代码已经存在于系统中。

我在系统中有4212个代码。具有36个不同符号产生碰撞的32个字符随机字符串的几率基本为零,并且我得到50%的碰撞。

当我通过调用srand();在我的函数中重新播种随机数生成器时,我没有再发生任何冲突。

但是在php的手册页上,它很清楚地说:

  

注意:从PHP 4.2.0开始,无需为随机数播种   生成器使用srand()或mt_srand(),因为现在已经完成了   自动。

我正在运行php版PHP 5.5.9

所以我的想法就像播种那样,但每个网络服务器工作者只做一次,然后当进程分叉时,它不会重新播种或类似的东西。 但这显然是apache中的一个错误......

我在apache版本Apache/2.4.7 (Ubuntu)mpm_prefork_module模块中运行php作为apache模块

所以我仍然需要在每个脚本的顶部调用srand(),这些联系人会说明其他明智的内容,为什么?是apach错误还是PHP?

是的,我知道我不应该为此目的使用此功能,我将更新它以使用加密安全号码。但我认为这不应该发生,我仍然对正在发生的事情感兴趣!

3 个答案:

答案 0 :(得分:3)

如果您的代码长度为32个字符,那么为什么不简单地用md5加密当前的microtime?

  $coupon = md5( microtime() );

一行简单。如果你想要一点随机性,那就抛出一个

   $coupon = md5( microtime() . mt_rand( 0, 10000) );

就像盐一样。这几乎可以保证你永远不会复制。至于为什么它不是随机的。

PHP的随机数生成器每个进程只播种一次。

看到这个帖子......

http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html

顺便说一句,我认为你不需要加密安全的哈希,只有足够随机的,不容易被猜到的。即使使用加密哈希,用户也会将所述哈希输入到优惠券的购物车中,即使是加密安全哈希也是一件简单的事情,那么,你最好只投入时间和# 34; N&#34;尝试,或&#34; n&#34;每秒尝试次数等。为了降低率,可以进行强力攻击。

例如,我会尝试32个字符哈希的所有组合。因此,最终并不重要,因为您没有使用明文条目(如密码),然后隐藏您的salting和加密方法。激活的优惠券数量将决定我的成功率和两种情况下的时间......如果你跟随。

在我的答案中暗示是这个

PHP的随机数生成器每个进程只播种一次。分叉不会创建新进程,但会复制当前进程状态。

请参阅
Calling rand/mt_rand on forked children yields identical results

http://wiki.openssl.org/index.php/Random_fork-safety

http://www.reddit.com/r/shittyprogramming/comments/2jvzgq/sometimes_it_takes_real_shitty_code_to_expose_an/

此外,这不是特定于php的问题,但对于一般的伪随机数生成更是如此。

答案 1 :(得分:2)

请参阅:https://github.com/php/php-src/blob/d0cb715373c3fbe9dc095378ec5ed8c71f799f67/ext/standard/rand.c#L66-L68

显然RNG正在重新接种第一次致电至<{1}}(或明确呼叫rand())。

由于srand()复制了父母的记忆,孩子也会得到父母的种子 - 永远不会重新接种。

答案 2 :(得分:0)

function generateRandomString($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return substr(time().$randomString,0,$length);
}