0

我写了一个函数PHP来为我的应用程序生成一个随机密码(只有 0-9a-zA-Z)。生成的密码必须是加密安全的,并且尽可能随机。IE 密码很敏感。

我做的大技巧是$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;
    }

谢谢。

4

4 回答 4

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);
}

该代码是此类的一部分,查看该函数generateRandomBase62String()以获取完整示例。

于 2013-06-20T08:14:18.640 回答
1

向伪随机字符串添加伪随机性根本不会增加熵。唯一的方法是使用更好的随机数生成器。

可能重复:PHP 中的安全随机数生成

于 2013-06-20T06:35:51.287 回答
1

如果通过加密安全,您的意思是您打算在某处使用密码作为密钥,那么重要的是要意识到您的空间还不够大。15 个字符有 62 种可能性,每个字符都小于 90 位,这与 RSA-1024 差不多,并且在今天被认为是不安全的。

但是,您首先不应该做这样的事情。如果您确实需要一个人类可读的字符串来映射到可用作加密密钥的东西,请使用类似PBKDF2的东西。

最后,改组字符串不会增加有效的随机性。只要您不直接将其用作密钥,您的功能就可以了 - 请记住首先根据常用密码字典
(如密码破解者的密码列表)检查输出并拒绝这些。

于 2013-06-20T06:44:16.377 回答
0

这不是您问题的答案,但使用此函数生成仅包含 (0-9a-z,AZ) 的随机随机密码似乎是可行的

$password = base64_encode(openssl_random_pseudo_bytes(20, $strong));
$newstr = preg_replace('/[^a-zA-Z0-9\']/', '', $password);
echo $newstr;
于 2013-06-20T04:45:38.300 回答