加密安全随机字符串函数


Cryptographically Secure Random String Function

目标:找到最加密安全的随机字符串生成器。

使用字母、数字和可能的特殊字符。

我一直在这里和其他地方阅读,但我仍然听到很多不同的答案/意见。那些对安全和密码学有最新知识的人可以在这里插话吗?

下面的函数将用于生成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肯定不是。但是,它将只返回二进制数据,您可以将其还原为十六进制。十六进制不足以生成密码字符串。这两个函数似乎都不包含您所要求的特殊字符。

所以这两个代码片段都不符合您的目的。