在PHP中生成随机密钥的最佳方法是什么?

我正在寻找创build一个可重复使用的函数,将生成一个随机密钥与可打印ACSII字符的select长度(任何地方从2到1000+)。 我在想可打印的ASCII字符是33-126。 他们的关键不需要是完全唯一的,只是在完全相同的毫秒生成(所以uniqid()将不起作用)。

我在想,可以使用chr()mt_rand()的组合。

这是要走的路,还是别的什么最好的方法?

编辑: uniqid()也不会工作,因为它没有长度参数,它只是任何PHP给你。

我的想法 :这是我想出的:

 function GenerateKey($length = 16) { $key = ''; for($i = 0; $i < $length; $i ++) { $key .= chr(mt_rand(33, 126)); } return $key; } 

这有什么问题吗?

另一个编辑:其他大部分问题涉及密码生成。 我想要更多的angular色,我不关心1 vs l 。 我希望可能的键的最大数量是可能的。

注意:生成的密钥不一定必须是密码安全的。

更新(12/2015):对于PHP 7.0,您应该使用random_int()而不是mt_rand因为它提供了“密码安全值”

就个人而言,我喜欢使用sha1(microtime(true).mt_rand(10000,90000))但是您正在寻找更多的可定制的方法,所以试试这个function(这是对您的请求这个答案的修改):

 function rand_char($length) { $random = ''; for ($i = 0; $i < $length; $i++) { $random .= chr(mt_rand(33, 126)); } return $random; } 

不过,这可能会比uniqid(),md5()或sha1()慢得多。

编辑:看起来像你第一次,对不起。 :d

编辑2:我决定用PHP 5和eAccelerator在我的Debian机器上做一个很好的小testing(原谅长码):

 function rand_char($length) { $random = ''; for ($i = 0; $i < $length; $i++) { $random .= chr(mt_rand(33, 126)); } return $random; } function rand_sha1($length) { $max = ceil($length / 40); $random = ''; for ($i = 0; $i < $max; $i ++) { $random .= sha1(microtime(true).mt_rand(10000,90000)); } return substr($random, 0, $length); } function rand_md5($length) { $max = ceil($length / 32); $random = ''; for ($i = 0; $i < $max; $i ++) { $random .= md5(microtime(true).mt_rand(10000,90000)); } return substr($random, 0, $length); } $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_char(1000); echo "Rand:\t".(microtime(true) - $a)."\n"; $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_sha1(1000); echo "SHA-1:\t".(microtime(true) - $a)."\n"; $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_md5(1000); echo "MD5:\t".(microtime(true) - $a)."\n"; 

结果:

 Rand: 2.09621596336 SHA-1: 0.611464977264 MD5: 0.618473052979 

所以我的build议,如果你想速度(但不是完整的字符集),是坚持MD5,SHA-1,或Uniqid(我没有testing..)

如果你想要密码强度的随机性(有没有一个确定的攻击者试图猜测你的随机密钥是什么?),这里没有任何答案是足够的。 哈希时间不安全,攻击者可以通过猜测服务器生成密钥的时间来大大加快search速度,并且在特定年份甚至在商品笔记本电脑上search所有毫秒也很容易(这是一个35位search空间)。 此外,只是通过散列函数运行uniqid()或其他一些弱随机源的结果来“扩展”这个结果是非常危险的 – 一旦发现你做了这个,这不会使得攻击者的search变得更加困难。

如果你真的需要encryption级别的安全性,你应该阅读/ dev / random,下面的代码应该适用于任何符合POSIX标准的系统(除Windows以外):

 #Generate a random key from /dev/random function get_key($bit_length = 128){ $fp = @fopen('/dev/random','rb'); if ($fp !== FALSE) { $key = substr(base64_encode(@fread($fp,($bit_length + 7) / 8)), 0, (($bit_length + 5) / 6) - 2); @fclose($fp); return $key; } return null; } 

如果你需要更多的速度,你可以从'dev / urandom'读取。

你仍然可以使用uniqid(),只需要做一些额外的处理就可以把它的值扩展成你需要的字符数。

例如,要将其展开为32个字符,可以这样做

 $id = md5(uniqid()); 

要将其扩展为64个字符,只需附加md5的md5即可

 $first = md5(uniqid()); $id = $first . md5($first); 

然后,如果需要less于32的倍数,则根据需要trucate。

这可能会碰到碰撞,但是不太可能。 如果你对此偏执,只是使用相同的想法,但通过像AES这样的对称密码突破uniqid()而不是散列它。

为什么不使用openssl_random_pseudo_bytes http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php

我之前的回答是将uniqid()与由系统variables派生而来的salt结合起来,但是这并不会产生一个随机的密钥,只有一个很可能是唯一的。 类似地,rand()或mt_rand()的输出对于encryption目的来说也不够随机。

要生成一个随机的密钥,你需要去一个很好的随机数据源,而函数openssl_random_pseudo_bytes()被devise来做到这一点:

 $randkey = base64_encode(openssl_random_pseudo_bytes(32)); 

base64_encode()是把它变成可打印的字符。

其他答案不推荐openssl_random_pseudo_bytes()的原因可能是它在PHP 5.3中引入的,这个问题已经有近6年的历史了。

这个问题会对你感兴趣吗?

我不知道为什么uniqid()不适合你,在什么情况下,你需要一个毫秒的唯一编号,但不一定在其他方面; 你发生得如此之快,以至于在同一毫秒内你可能会发生碰撞? 我想知道多less时间uniqid()只需要生成它的号码。 如果你愿意,用一些随机字母来使用uniqid()函数的前缀参数,你应该是安全的。

如果是生成文件,你可能想看看tmpfile()tempname()

在任何情况下,取决于你想要达到什么目的,你可以循环和validation是否已经采取了唯一的id(在一个数组中,file_exists等),只是如果是这样的情况下生成另一个。


另外,因为我不确定我是否完全理解你的问题,所以我会告诉你其他一些听起来很相似的问题,而我可以区分你的问题:

  • 生成(伪)随机字母数字string
  • MD5之前有多less个随机元素产生冲突?

如果你正在寻找一个可读的独一无二的身份证,那么第一个会很有意思。 如果你想玩随机数字和md5 / sha1,第二个可能会很有用。 虽然,再次,我认为uniqid()可能已经是你在找什么。

$ key = md5(microtime()。rand());

Microtime本身并不安全,因为它只有1/1000被猜测的机会。

兰德本身也不是很安全,但将它们串联在一起产生了一个相当稳定的随机化。

您也可以生成一个随机密钥,并检查数据库中的密钥,如果该密钥退出,您可以通过此方法生成另一个密钥

  function activation($lengt=20){ $modalpage =new Modal;//you can call your modal page and check the key $characters = "1234567890abcdefghijklmnopqrstuvwxyz"; for($i=0;$i<$lengt;$i++) { $key .= $characters{rand(0,35)}; $check= array( ":key" => $key, ); $result = $modalpage->findkey($check); if($result==true){ //if the key is exits return the function and generate another key ! return activation($lengt); }else //if the key is not exits return the key return $key; } } $mykey=activation(15);