我正在寻找创建一个可重用的函数,它将生成一个随机密钥,其中包含所选长度的可打印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;
}
Run Code Online (Sandbox Code Playgroud)
这有什么问题吗?
另一个编辑:大多数其他问题涉及密码生成.我希望有一个更广泛的角色,我不关心1VS l.我想要可能的最大数量的键.
注意:生成的密钥不一定必须是加密安全的.
St.*_*son 57
更新(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;
}
Run Code Online (Sandbox Code Playgroud)
不过,这可能会比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";
Run Code Online (Sandbox Code Playgroud)
结果:
Rand: 2.09621596336
SHA-1: 0.611464977264
MD5: 0.618473052979
Run Code Online (Sandbox Code Playgroud)
所以我的建议,如果你想要速度(但不是完整的字符集),是坚持MD5,SHA-1或Uniqid(我还没有测试..)
Sec*_*Joe 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;
}
Run Code Online (Sandbox Code Playgroud)
如果你需要更快的速度,你可以从'dev/urandom'中读取.
您仍然可以使用uniqid(),只需执行一些额外的处理即可将其值扩展为您需要的字符数.
例如,要将其扩展为32个字符,您可以这样做
$id = md5(uniqid());
Run Code Online (Sandbox Code Playgroud)
要将其扩展为64个字符,只需附加md5的md5,就像这样
$first = md5(uniqid());
$id = $first . md5($first);
Run Code Online (Sandbox Code Playgroud)
然后,如果您需要少于32的倍数,则必要时进行trucate.
你可能遇到碰撞,但这种可能性很小.如果你对此有点偏执,只需使用相同的想法,但uniqid()通过像AES这样的对称密码而不是散列它.