PHP快速随机字符串功能

时间:2011-01-21 09:53:57

标签: php performance string random cryptography

我需要快速的方法在PHP中生成随机字符串a-Z0-9。我一直在做一些思考和测试,这是我到目前为止所做的:

function randStr($length) {
    $result = null;
    $replace = array('/', '+', '=');
        while(!isset($result[$length-1])) {
        $result.= str_replace($replace, NULL, base64_encode(mcrypt_create_iv($length, MCRYPT_RAND)));
        }
    return substr($result, 0, $length);
}

与为每个char迭代并选择随机ASCII值的函数相比,函数似乎工作得很快,但我关注的是我的实现的“质量”。我对密码学知之甚少,所以我想问一下这种函数是否会产生“好的”随机值。

  1. mcrypt_create_iv似乎返回某种随机二进制值,实际上用于使用mcrypt库加密/解密数据。什么是base64_encode对这种二进制数据的影响,当我base64_encode它时,我实际上是否减少了熵?

  2. mcrypt_create_iv的第二个参数如何影响我的结果? php.net手册指出MCRYPT_RAND是'系统随机数生成器'。它是特定于操作系统的,如果是,那么创建了多少好的值?

5 个答案:

答案 0 :(得分:5)

这应该在大多数系统上安全且快速:

bin2hex(openssl_random_pseudo_bytes($length / 2));

基准测试(1000000条记录,字符串长度为100个字符)

rstr1: 198.93383002281
rstr2: 35.5827729702
rstr3: 6.8811790943146
rstr4: 5.4545040130615
this:: 3.9310231208801

答案 1 :(得分:3)

  1. base64_encoding不会降低熵,它只是相同数据的不同表示。

  2. 这是特定于操作系统的,但我认为使用此功能创建的随机值足够好。在PHP 5.3下,您必须事先为生成器播种,如果您在不同的服务器上使用此代码,则可能会出现问题。

答案 2 :(得分:3)

任何寻找"最佳"的最新版本的人算法:

function randomString($length) {
   $result = null;
   $replace = array('/', '+', '=');
   while(!isset($result[$length-1])) {
      $result.= str_replace($replace, NULL, base64_encode(random_bytes($length)));
   }
   return substr($result, 0, $length);
}

我用的是“#34; best"因为它比rstr1rstr2的随机字符串操作更快,并且与其他解决方案相比,它提供了完整范围的字母(低层和高层)。

答案 3 :(得分:2)

从我的测试中,你的功能已经非常快,但我设法得到一个更快的,即使它减少了熵

fcn     time  
rstr1:  1.074s (slowest)
rstr2:  0.917s
rstr3:  0.028s (yours)
rstr4:  0.022s (mine)

在我的场景中,我需要尽可能快的1k字符串。

function rstr1($length)
{
    // @see http://stackoverflow.com/a/853846/11301
    $alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alphabet, $length)), 0, $length);
}

function rstr2($length)
{
    // @see http://stackoverflow.com/a/853870/11301
    $alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $str = '';
    $count = strlen($alphabet);
    while ($length--) {
        $str .= $alphabet[mt_rand(0, $count-1)];
    }
    return $str;
}

function rstr3($length) {
    // @see http://stackoverflow.com/q/4757392/11301
    $result = null;
    $replace = array('/', '+', '=');
    while(!isset($result[$length-1])) {
        $result.= str_replace($replace, NULL, base64_encode(mcrypt_create_iv($length, MCRYPT_RAND)));
    }
    return substr($result, 0, $length);
}

function rstr4($length)
{
    // uses md5 & mt_rand. Not as "random" as it could be, but it works, and its fastest from my tests
    return str_shuffle(substr(str_repeat(md5(mt_rand()), 2+$length/32), 0, $length));
}


// test the functions
for($i=0; $i<1000; $i++){
    #$x = rstr1(1024); # 
    #$x = rstr2(1024);  # 0.917s
    #$x = rstr3(1024);  # 0.028s
    #$x = rstr4(1024);  # 0.022s

    #dlog($x); return;
}

答案 4 :(得分:-1)

这就是我这样做的方式,虽然它并不完全是加密的; Mersenne Twister快速可靠,但不是最安全的。

function str_rand($chars, $len)
  {
  $str = '';
  for ($max = strlen($chars) - 1, $i = 0; $i < $len; ++$i)
       {
       $str .= $chars[mt_rand(0, $max)];
       }
  return $str;
  }

$strRand = str_rand('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 40);