【问题标题】:Cryptographically secure random ASCII-string in PHPPHP中的加密安全随机ASCII字符串
【发布时间】:2019-01-12 10:46:24
【问题描述】:

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

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

有什么想法吗?

【问题讨论】:

  • 假设您的问题仅仅是如何将字节转换为 ASCII 表示而不一定如何生成加密安全的随机字符串:您是否考虑过 Base64 编码和 PHP 中的 base64_encode() 函数?跨度>

标签: php security random cryptography


【解决方案1】:

不幸的是,Peter O. 在审核队列中受到负面关注后删除了他的答案,可能是因为他将其表述为一个问题。我相信这是合法的答案,所以我会重复它。

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

【讨论】:

    【解决方案2】:

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

    我使用这个库来生成我的 GUID

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

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

    抱歉,我忽略了关于您希望将 26 个 alpha char 的全部范围与数字一起使用的部分...不确定我在这方面是否有答案,但您应该相信猜测 UUID4 的难度,尤其是当您将一对加在一起并将长度混淆 10 倍以使猜测更加复杂时。

    实际上,如果您可以安全地生成有效 ascii char 代码范围内的随机数数组,那么您可以将整个随机代码数组转换为相应的 ascii char 并将它们内爆为单个字符串。

    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.
    

    当然……您应该注意,您使用的是键盘上的所有标准键,其中一些字符会扰乱敏感的内容(例如引号等)

    【讨论】:

    • "...但是您应该相信猜测 UUID4 的难度..." 不,您不应该。
    • 为什么你不相信它能够生成随机的 char 字符串以及人们难以猜测的能力?
    • 我们都知道,只要有足够的时间、处理能力和机会去戳一些东西,我们最终会猜对的……所以从技术上讲,密码学中没有什么是安全的,但如果你很有可能某事不会是猜测并将其应用于精心设计的系统,在奶牛回家之前不允许有人戳它,那么你会很好地相信 UUID4 等等,所以当你将它们中的几个组合在一起形成一个超级 UUID4
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-08
      • 2012-08-24
      • 1970-01-01
      • 2017-11-20
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 2011-09-05
      相关资源
      最近更新 更多