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

时间:2009-03-12 03:41:29

标签: php random

我正在寻找创建一个可重复使用的函数,该函数将生成一个随机密钥,其中包含所选长度的可打印ACSII字符(从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;
}

这有什么问题吗?

另一个编辑:其他大多数问题都涉及密码生成。我想要更多种类的角色,我不关心1 vs l。我想要可能的最大键数。

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

8 个答案:

答案 0 :(得分:56)

更新(2015年12月):对于PHP 7.0,您应使用random_int()代替mt_rand,因为它提供“加密安全值”

就个人而言,我喜欢使用sha1(microtime(true).mt_rand(10000,90000)),但您正在寻找更多可自定义的方法,因此请尝试此功能(这是对this answer请求的修改):

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

尽管如此,这可能会比uniqid(),md5()或sha1()慢得多。

编辑:看起来你先得到它,抱歉。 :d

编辑2:我决定在我的Debian机器上用PHP 5和eAccelerator进行一个不错的小测试(原谅长代码):

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

所以我的建议,如果你想要速度(但不是完整的字符集),就要坚持使用MD5,SHA-1或Uniqid(我还没有测试......)

答案 1 :(得分:28)

如果您想要加密强度随机性(确定的攻击者试图猜测您的随机密钥是什么?),这里的答案都不够。散布时间并不安全,攻击者可以通过猜测他们认为您的服务器生成密钥的时间来大大加快搜索速度,并且即使在商用笔记本电脑上也可以轻松搜索给定年份内的所有毫秒数(它是35位搜索空间)。此外,建议只通过哈希函数运行uniqid()或其他弱随机源的结果来“扩展它”是危险的 - 一旦发现你做了这个,这并不会使攻击者的搜索变得更难

如果你真的需要加密级安全性,你应该从/ 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'中读取。

答案 2 :(得分:8)

您仍然可以使用uniqid(),只需进行一些额外的处理即可将其值扩展为您需要的字符数。

例如,要将其扩展为32个字符,您可以执行

$id = md5(uniqid());

要将其扩展为64个字符,只需附加md5的md5,就像这样

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

然后,如果您需要少于32的倍数,则必要时进行trucate。

你可能遇到碰撞,但这种可能性很小。如果你对此感到妄想,只需使用相同的想法,但通过像AES这样的对称密码来突变uniqid()而不是散列它。

答案 3 :(得分:3)

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

答案 4 :(得分:1)

我之前的回答采用了uniqid()的哈希结合从系统变量派生的盐,但是它没有生成随机键,只有一个非常可能是唯一的。类似地,rand()或mt_rand()的输出对于加密目的而言不够随机。

要生成随机密钥,您需要转到一个好的随机数据源,并且函数openssl_random_pseudo_bytes()旨在实现这一目的:

$randkey = base64_encode(openssl_random_pseudo_bytes(32));

base64_encode()是使其成为可打印的字符。

其他答案不建议使用openssl_random_pseudo_bytes()可能是因为它是在PHP 5.3中引入的,这个问题已接近6年了。

答案 5 :(得分:0)

你会感兴趣that question吗?

我不确定为什么uniqid()对你不起作用,在什么情况下你需要一个同一毫秒的唯一数字,但不一定如此;你生成的速度如此之快,以至于在同一毫秒内你可能发生碰撞?我想知道uniqid()生成数字需要多长时间。如果需要,可以使用uniqid()函数的前缀参数和几个随机字母,这样你就应该是安全的。

如果是用于生成文件,您可能需要查看tmpfile()tempname()

在任何情况下,根据您要实现的目标,您可以循环并验证是否已经采用了唯一ID(在数组中,使用file_exists等),如果是这种情况,则只生成另一个。


另外,由于我不确定我是否完全理解你的问题,我会指出那些听起来非常相似的问题,而我会得到你的不同之处:

如果您想要创建一个人类可读的唯一ID,那么第一个将是您感兴趣的。如果你想使用随机数和md5 / sha1,第二个可能很有用。虽然我再次认为uniqid()可能已经是您正在寻找的东西。

答案 6 :(得分:0)

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

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

兰德本身也不是很安全,但是将它们连接在一起会产生非常可靠的随机化。

答案 7 :(得分:-1)

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

        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);