在PHP中使用SHA512生成随机数

3

我正在使用$blockhash[$i] = rand().time().rand()填充一个随机数数组。

然后,针对该数组中的每个随机数,我计算相应的SHA512。

$SecretKey = "60674ccb549f1988439774adb82ff187e63a2dfd403a0dee852e4e4eab75a0b3";
$sha = hash_hmac('sha512', $value, $SecretKey);

拆分它:

$pool  = str_split($sha, 2);

然后我从$pool数组中获取第一个数字,将十六进制转换为十进制,并将其限制在1和50之间:

$dec = hexdec($pool[0]) % 50 + 1;

问题在于这些数字并不是那么随机,但我不知道原因。我正在统计从1到50的每个数字出现的频率,但数字1、2、3、4、5和6比其他数字更常见。请参见图表。为什么会出现这种情况,如何解决?谢谢!
3个回答

4

你要转换为十进制的两个十六进制字符将在0-255范围内。 你可以对50取模并加1,使得1-6(range(0-5)+1)在1-256中出现6次,而其他数字只出现5次。这将导致这些数字出现的频率增加约20%。


谢谢!问题在于模块。该怎么办?如何在不影响随机性的情况下将其限制在1-50之间? - andrepcg

2
你经常获得1-6,因为你从哈希中获取两个十六进制数字。这是一个字节,所以它可以存储0到255之间的值。然后使用模50。结果是范围0-49、50-99、100-149、150-199、200-249和250-255。最后一个范围导致了1-6在结果中的额外普遍性。
解决方案:只需使用mt_rand(1,50)。
[编辑]
如果你真的需要将0-255范围内的数字转换为1-50范围内的数字,解决方案是进行缩放和四舍五入。
$number = round(($byteValue)/(255/49))+1; 

是的,我可以采取简单的方式,只需这样做,但我真的需要从哈希中获取字节,然后对其进行限制。那么不用模运算,如何将它限制在1-50之间呢? - andrepcg

1

无论是rand()还是mt_rand()都不能生成真正的随机值。

正如手册所述:

此函数不会生成加密安全的值,因此不应用于加密目的。如果您需要加密安全的值,请考虑使用openssl_random_pseudo_bytes()

请参见Better Random Generating PHP,这是一个StackOverflow问题,指出了相同的问题并提供了一些很好的答案。


但不要忘记我正在使用SHA512来生成一些随机字符。random()只是用来填充数组内容的。 - andrepcg

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