我了解PHP 7中的random_bytes()
,我想用它来生成加密安全(例如,难以猜测)的随机字符串,以用作一次性令牌或将其长期存储在Cookie中
不幸的是,我不知道如何将random_bytes()
的输出转换为仅包含人类可读字符的字符串,因此浏览器不会感到困惑。我知道bin2hex()
,但是我更喜欢使用完整的ASCII范围而不是十六进制数字,以使每个长度都有更多的位数。
有什么想法吗?
答案 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,然后将这些数字转换为相应的字母将得到所需的文本。