当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在PHP中生成随机密钥的最佳方法是什么?》经验,为你挑选了3个好方法。

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

这有什么问题吗?

另一个编辑:大多数其他问题涉及密码生成.我希望有一个更广泛的角色,我不关心1VS l.我想要可能的最大数量的键.

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



1> St. John Joh..:

更新(12/2015):对于PHP 7.0,您应该使用random_int()而不是mt_rand提供"加密安全值"

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

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(我还没有测试..)


打了几个月就好了;)

2> SecurityJoe..:

如果你想要加密强度随机性(确定的攻击者试图猜测你的随机密钥是什么?),这里的答案都不够.散布时间并不安全,攻击者可以通过猜测他们认为您的服务器生成密钥的时间来大大加快搜索速度,并且即使在商用笔记本电脑上也可以轻松搜索给定年份内的所有毫秒数(它是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'中读取.


只是想注意 - 我有一个脚本需要额外50多个加载,事实证明使用/ dev/random而不是/ dev/urandom.在我的本地测试环境中,这从未发生过.
`/ dev/urandom`应该是默认值,使用`/ dev/random /`会过早耗尽随机熵池(在没有链接到`/ dev/random`的专用随机数生成器的系统上).实际上,因为这对于攻击者执行DoS攻击是一种很好的方式,我认为该功能根本不应该公开,它只对具有自己的PRNG的应用程序/库有用.

3> Bob Somers..:

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

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

$id = md5(uniqid());

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

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

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

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

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有