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

2022-08-30 12:12:40

我希望创建一个可重用的函数,该函数将生成一个随机密钥,其中包含所选长度的可打印ACSII字符(从2到1000 +不等)。我认为可打印的ASCII字符将是33-126。它们的键不需要是完全唯一的,只是在完全相同的毫秒内生成的唯一(所以不起作用)。uniqid()

我正在考虑一种组合,并且可能会起作用。chr()mt_rand()

这是要走的路,还是其他方法最好?

编辑:也不起作用,因为它没有长度参数,它只是PHP给你的任何东西。uniqid()

我的想法:这就是我想到的:

function GenerateKey($length = 16) {
    $key = '';

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

    return $key;
}

这有什么问题吗?

另一个编辑:大多数其他问题涉及密码生成。我想要更多种类的角色,我不在乎vs。我希望最大数量的可能密钥是可能的。1l

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


答案 1

更新(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:我决定用 PHP 5 和 eAccelerator 在我的 Debian 机器上做一个漂亮的小测试(请原谅长代码):

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

如果你想要加密强度的随机性,这里没有一个答案是足够的(是否有一个坚定的攻击者试图猜测你的随机密钥是什么?)。散列时间是不安全的,攻击者可以通过猜测他们认为您的服务器生成密钥的时间来大大加快搜索速度,并且即使在商品笔记本电脑上(这是一个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”中读取。


推荐