PHP中的加密安全随机ASCII字符串

时间:2019-01-12 10:46:25

标签: php security random cryptography

我了解PHP 7中的random_bytes(),我想用它来生成加密安全(例如,难以猜测)的随机字符串,以用作一次性令牌或将其长期存储在Cookie中

不幸的是,我不知道如何将random_bytes()的输出转换为仅包含人类可读字符的字符串,因此浏览器不会感到困惑。我知道bin2hex(),但是我更喜欢使用完整的ASCII范围而不是十六进制数字,以使每个长度都有更多的位数。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

不幸的是,Peter O.在评论队列中受到负面关注后删除了他的答案,可能是因为他将其表述为问题。我相信这是合理的答案,所以我会再次提出。

一个简单的解决方案是使用base64_encode()将随机数据编码为base64字母。这不会产生您所要求的“完整ASCII范围”,但会为您提供大部分信息。合适的base85编码器可以输出更大的ASCII范围,但是php没有内置的。不过,您可能会发现很多用于php的开源base85编码器。在我看来,base85的长度比base64的减少不太值得您必须维护的额外代码。

答案 1 :(得分:1)

我个人只是使​​用一个GUID库并将两个GUID连接起来以获得一个长而唯一的令牌字符串。您还可以选择删除破折号,以使其难以得知来源,如果要使其更加复杂,可以将字符串随机最多减少10个字符,以增加其未知长度的复杂性。

我使用此库来生成我的GUID

https://packagist.org/packages/ramsey/uuid

use Ramsey\Uuid\Uuid;
$token = Uuid::uuid4() . '-' . Uuid::uuid4();

对不起,我忽略了您想使用数字范围内的26个字母字符的整个部分……不确定在这方面我是否能为您提供答案,但是您应该相信猜测UUID4的难度,特别是当您将一对夫妇加在一起并将长度混淆了10倍以使猜测变得更加复杂时。

实际上,如果可以安全地在有效的ascii字符代码范围内生成随机数数组,则可以将整个随机代码数组转换为相应的ascii字符并将它们作为单个字符串合并在一起。

function randomAsciiString($length) {
    return implode('', array_map(
        function($value) {
            return chr($value);
        },
        array_map(
            function($value) {
                return random_int(33, 126);
            },
            array_fill(0, $length - 1, null)
        )
    ));
}
echo randomAsciiString(128);                  // Normal 128 char string
echo randomAsciiString(random_int(118, 128)); // obfuscated length char string for extra complexity.

当然...但是,您应该注意,您正在使用键盘上的所有标准键,并且其中某些字符会破坏敏感内容(例如引号等)。

答案 2 :(得分:0)

让我们考虑要使用的字母。为了简单起见,我假设您只打算使用大小写的英文字母。这意味着您有26个大字母和26个小字母,以及52个不同的可能值。如果我们将n个元素的字节数组视为以256为基数的n位数字,然后将此数字转换为以52为基数的数字,其中A为0,B为1,C为2,...,a为26, ...,z为51,然后将这些数字转换为相应的字母将得到所需的文本。