我在PHP
中编写了一个功能,为我的应用生成随机密码(仅限0-9a-zA-Z)。生成的密码必须是加密安全的,并且尽可能随机。 I.E.密码很敏感。
我所做的一个重要工作就是每次都会混淆$possible
个字符,所以即使mt_rand()
不是真正随机的,也不应该是可预测的。
我的功能中有任何建议的更改或安全问题吗?使用openssl_random_pseudo_bytes()
代替mt_rand()
真的会使算法更强大,更安全吗?
public function generate_random($length = 15) {
$random = "";
$possible = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$possible = str_shuffle($possible);
$maxlength = strlen($possible);
if ($length > $maxlength) {
$length = $maxlength;
}
$i = 0;
while ($i < $length) {
$random .= substr($possible, mt_rand(0, $maxlength-1), 1);
$i++;
}
return $random;
}
感谢。
答案 0 :(得分:2)
要生成非常随机的内容,您必须使用操作系统的随机源。从这个源读取后,您需要将字节编码为您选择的字母。
一个简单的转换是base64编码,但这将包括'+'和'/'字符。要仅从字母和数字中获取字符,您需要base62编码,或者只需将这些字符替换为其他字符。
/**
* Generates a random string of a given length, using the random source of
* the operating system. The string contains only characters of this
* alphabet: +/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
* @param int $length Number of characters the string should have.
* @return string A random base64 encoded string.
*/
function generateRandomBase64String($length)
{
if (!defined('MCRYPT_DEV_URANDOM')) die('The MCRYPT_DEV_URANDOM source is required (PHP 5.3).');
// Generate random bytes, using the operating system's random source.
// Since PHP 5.3 this also uses the random source on a Windows server.
// Unlike /dev/random, the /dev/urandom does not block the server, if
// there is not enough entropy available.
$binaryLength = (int)($length * 3 / 4 + 1);
$randomBinaryString = mcrypt_create_iv($binaryLength, MCRYPT_DEV_URANDOM);
$randomBase64String = base64_encode($randomBinaryString);
return substr($randomBase64String, 0, $length);
}
代码是此class的一部分,请查看函数generateRandomBase62String()
以获取完整示例。
答案 1 :(得分:1)
将伪随机性添加到伪随机字符串将不会增加熵。唯一的方法是使用更好的随机数生成器。
答案 2 :(得分:1)
如果通过加密安全,你的意思是你打算在某个地方使用密码作为密钥,重要的是要意识到你的空间不够大。每个有62个可能性的15个字符小于90位,这与RSA-1024一样强,并且今天被认为是不安全的。
但是,你应该首先不做这样的事情。如果您确实需要一个人类可读的字符串,该字符串映射到可用作加密密钥的内容,请使用类似PBKDF2的内容。最后,改变字符串并不会增加有效的随机性。只要您不直接使用它作为键,您的功能就可以了 - 记得首先根据常用密码字典检查输出 (如密码破解者的密码列表)并拒绝这些。
答案 3 :(得分:0)
这不是您的问题的答案,但使用此函数生成仅包含(0-9a-z,A-Z)的随机随机密码似乎是可行的
$password = base64_encode(openssl_random_pseudo_bytes(20, $strong));
$newstr = preg_replace('/[^a-zA-Z0-9\']/', '', $password);
echo $newstr;