【问题标题】:Audit my PHP function to generate cryptography secure passwords [closed]审核我的 PHP 函数以生成加密安全密码 [关闭]
【发布时间】:2013-06-16 19:39:36
【问题描述】:

我在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;
    }

谢谢。

【问题讨论】:

  • '只有 0-9a-zA-Z' - 为什么?
  • 只是规范的一部分。可以添加特殊字符,但让我们忽略这方面。
  • 使用这种方法,你仍然会有某些字母彼此相邻吗?
  • codereview.stackexchange.com 可能是解决此类问题的更好网站。
  • str_shuffle 在内部使用rand。

标签: php security random passwords cryptography


【解决方案1】:

要生成真正随机的东西,您必须使用操作系统的随机源。从该源读取后,您需要将字节编码为您选择的字母表。

一个简单的转换是 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()。

【讨论】:

    【解决方案2】:

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

    可能重复:Secure random number generation in PHP

    【讨论】:

      【解决方案3】:

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

      但是,您一开始就不应该这样做。如果您确实需要一个人类可读的字符串,该字符串映射到可用作加密密钥的内容,请使用 PBKDF2 之类的内容。

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

      【讨论】:

        【解决方案4】:

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

        $password = base64_encode(openssl_random_pseudo_bytes(20, $strong));
        $newstr = preg_replace('/[^a-zA-Z0-9\']/', '', $password);
        echo $newstr;
        

        【讨论】:

        • 这将只包含0–9、a–f。
        • @Gumbo 是的。实际上,当用户注册并单击忘记密码时,我在我的应用程序中使用它来生成随机密码或一次性密码。
        • 检查我的编辑这应该可以工作..
        猜你喜欢
        • 2012-10-07
        • 2017-12-26
        • 1970-01-01
        • 2011-12-22
        • 1970-01-01
        • 1970-01-01
        • 2017-08-11
        • 1970-01-01
        • 2021-06-18
        相关资源
        最近更新 更多