目标:找到最加密安全的随机字符串生成器。
使用字母、数字和可能的特殊字符。我一直在这里和其他地方阅读,但我仍然听到很多不同的答案/意见。那些对安全和密码学有最新知识的人可以在这里插话吗?
下面的函数将用于生成8个字符的随机密码和128个字符的随机令牌。
功能1:
/**
* Used for generating a random string.
*
* @param int $_Length The lengtyh of the random string.
* @return string The random string.
*/
function gfRandomString($_Length) {
$alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
$pass = array(); //remember to declare $pass as an array
$alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < $_Length; $i++) {
$n = rand(0, $alphaLength);
$pass[] = $alphabet[$n];
}
return implode($pass); //turn the array into a string
}
功能2:
PHP.net文档说: crypto_strong :如果传递到函数中,这将保存一个布尔值,该值确定所使用的算法是否"加密强",例如,对于GPG,密码等使用是安全的。如果是,则为TRUE,否则为FALSE
那是基于服务器的吗?如果我测试它一次,它是能够生成一个crypto_strong字符串,它总是能够吗?或者我需要每次检查并创建一个循环,直到它生成一个crypto_strong字符串。
/**
* Used for generating a random string.
*
* @param int $_Length The length of bits.
* @return string The random string.
*/
function gfSecureString($_Length) {
$Str = bin2hex(openssl_random_pseudo_bytes($_Length));
return $Str;
}
我欢迎任何提高加密强度的建议
所以你想在PHP中安全地生成随机字符串。问题中的两个函数都不能满足你的要求,但是rand()
的解是两个中最差的。rand()
是不安全的,而bin2hex(openssl_random_pseudo_bytes())
限制你的输出字符集。
此外,openssl_random_pseudo_bytes()
在极端条件或特殊设置下可能不可靠。
据我所知,如果RAND_pseudo_bytes()
未能返回任何数据,crypto_strong
只会被设置为false
。如果在调用OpenSSL时没有播种,它将静默地返回弱(可能是可预测的)伪随机字节。在PHP中,您也没有办法确定它是否是随机的。
如何生成安全的随机字符串
如果您想要一个已经在PHP 5中得到大量审查的解决方案。
$factory = new RandomLib'Factory;
$generator = $factory->getMediumStrengthGenerator();
$randomPassword = $generator->generateString(20, $alphabet);
替代解决方案如果你不想使用RandomLib(即使,纯粹是因为你想有其他可用的选项),你也可以在PHP 7发布时使用random_int()
。如果你等不及的话,可以看看我们的random_compat项目。
如果您碰巧使用的是加密库libsodium,您可以生成如下的随机数:
/**
* Depends on the PECL extension libsodium
*
* @link https://stackoverflow.com/a/31498051/2224584
*
* @param int $length How long should the string be?
* @param string $alphabet Contains all of the allowed characters
*
* @return string
*/
function sodium_random_str($length, $alphabet = 'abcdefghijklmnopqrstuvwxyz')
{
$buf = '';
$alphabetSize = strlen($alphabet);
for ($i = 0; $i < $length; ++$i) {
$buf .= $alphabet['Sodium'randombytes_uniform($alphabetSize)];
}
return $buf;
}
请参阅此答案,以获取使用random_int()
的示例代码。如果将来需要的话,我宁愿不重复更新代码的工作。
openssl_random_pseudo_bytes
有相当大的机会成为加密安全的生成器,而rand
肯定不是。但是,它将只返回二进制数据,您可以将其还原为十六进制。十六进制不足以生成密码字符串。这两个函数似乎都不包含您所要求的特殊字符。
所以这两个代码片段都不符合您的目的。