如何生成一个128位长的字符串?

6
基本上,我正在寻找一个函数来执行以下操作。
generateToken(128)

这将返回一个由整数或字母字符组成的128位字符串

澄清一下:根据评论,我必须修改问题。显然,如果需要128位,则我正在寻找一个长度为16个字符的字符串。


Axsuul,你的回答毫无意义。 - Artefacto
1
你的意思是想将一个128位的数字编码成字符串,还是想要一个由128位数字组成的数字?我假设你想要一个128位的数字作为我的回答。 - Cameron Skinner
@Cameron,由128位数字组成的数字与由128位比特组成的数字不同。有128位比特的数字介于0和2^128-1之间。我问他想要一个介于0和2^128-1之间的随机数还是一个由128/8=16个字符组成的字符串。 - Artefacto
1
@ Artefacto:是的,我知道。这就是为什么我要求澄清:OP想要128位还是128个十进制数字? - Cameron Skinner
是的,抱歉如果有任何混淆,但我只需要一个16个字符(或16位数字)的字符串。也就是说,不是128位数。能否有人解释一下为什么128/8 = 16个字符是128位,我会接受这个答案?我也会编辑我的问题。再次感谢。 - axsuul
显示剩余3条评论
3个回答

6
有必要限制字符串只能是整数吗?这实际上使问题更加困难,因为每个数字给你 3.3 位(因为 2^3.3 ~= 10)。通过这种方式精确生成 128 位令牌很棘手。
更容易的方法是允许十六进制编码(每个字符 4 位)。然后你可以生成 128 位的真正随机比特,然后将它们编码成十六进制以供应用程序使用。Base64 编码(每个字符 6 位)也适用于此类事情。 openssl_random_pseudo_bytes 将给出一串随机字节,你可以使用 bin2hex 进行编码,否则可以在自己的令牌生成例程中使用 mt_rand
编辑:阅读了问题的更新后,似乎你想生成一个代表 128 位数据的令牌,实际字符串长度(以字符为单位)并不那么重要。如果我猜对了你的意图(作为识别/验证目的的唯一 ID),那么我建议你使用 openssl_random_pseudo_bytes 生成解决方案所需的正确数量的比特,即 128(16 字节)。然后你可以用任何你认为合适的方式进行编码,十六进制和 Base64 是两个可能性。
请注意,十六进制编码将使用 32 个字符来编码 128 比特的数据,因为每个字符只编码 4 比特(128 / 4 = 32)。Base64 将使用 22 个字符(128 / 6 = 21.3)。每个字符占用 8 位的存储空间,但只编码了 4 或 6 位的信息
非常注意不要混淆编码后字符串长度和原始数据长度。如果你选择一个带有字母数字字符(a-z、A-Z、0-9)的 16 字符串,那么每个字符只能编码 6 位信息(62 的对数底数是近似于 6),所以你的 16 字符串只能编码 96 位信息。你应该将令牌看作不透明的字节数组,并仅在实际尝试发送到网络或放入 cookie 等时才考虑将其转换为/从字符字符串。

openssl_random_pseudo_bytes 不会给出十六进制编码表示。不管怎样,这是一个很好的解决方案。之后,只需要使用例如 bcmath 来构建以十进制字符串表示的数字即可。 - Artefacto
是的,你说得对。我误读了例子并忘记了 bin2hex 这一部分 :) - Cameron Skinner
请参见以下网址https://dev59.com/Y07Sa4cB1Zd3GeqP10Dv#3402951,了解如何将任意数据转换为10进制数字。 - Artefacto

3

从 PHP 5.3 开始:

$rand128 = bin2hex(openssl_random_pseudo_bytes(16));

而在 PHP 7.0+ 中,它只是 random_bytes 而不是 openssl_random_pseudo_bytes - caw

0

你的目的是什么?

如果你只想要一个唯一的ID,那么可以使用uniqid函数:

http://www.php.net/manual/en/function.uniqid.php

这不是随机的,而是基于微秒的十六进制字符串。如果您执行uniqid('', true),那么它将返回一个基于微秒的十六进制字符串,并在ID末尾附加一堆随机数字(因此,即使两个呼叫在同一微秒内到达,它们也不太可能共享唯一的ID)。

如果您需要确切的16个字符的字符串,那么目的是什么?您是否在处理密码?该字符串应有多随机?总而言之,您可以始终只需执行:

$toShow = array();
for($i = 0; $i<16; $i++){
    $toShow[] = chr(mt_rand(ord('a'), ord('z')));
}
return $toShow

现在这将创建一个由'a'和'z'之间的字符组成的字符串。您可以将"ord('a')"更改为0,将"ord('z')"更改为255,以获得完全随机的二进制字符串...或任何其他您需要的范围。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接