如何在PHP中从0-X获得加密强整数?
我想在PHP中生成随机字母数字字符串。它们将用于随机数的强度很重要的地方(URL等中的公共可见ID) 据我所知,在PHP中,加密强随机性的主要来源是如何在PHP中从0-X获得加密强整数?,php,random,Php,Random,我想在PHP中生成随机字母数字字符串。它们将用于随机数的强度很重要的地方(URL等中的公共可见ID) 据我所知,在PHP中,加密强随机性的主要来源是openssl\u random\u pseudo\u bytes()。但是,这将返回字节数组,而不是字母数字字符 要将它们转换为字母数字,我可以对它们进行散列(这将产生一个超过必要长度的有限十六进制字符集字符串),或者base64_encode()它们(这将产生一个包含+,/和=的字符串,而不是字母数字) 因此,我认为我可以使用随机字节作为熵的来源
openssl\u random\u pseudo\u bytes()
。但是,这将返回字节数组,而不是字母数字字符
要将它们转换为字母数字,我可以对它们进行散列(这将产生一个超过必要长度的有限十六进制字符集字符串),或者base64_encode()
它们(这将产生一个包含+
,/
和=
的字符串,而不是字母数字)
因此,我认为我可以使用随机字节作为熵的来源,并生成我自己的字符串,该字符串只包含字符0-9a-zA-Z
然后问题就变成了-如何将256个不同的值(输入的一个字节)转换为62个不同的值(输出的一个字符)。在某种程度上,所有62个字符都是相同的。(否则将有8个字符比其他字符更频繁地出现)
或者我应该完全使用另一种方法?我希望我的字符串尽可能短(比如说,20个字符左右-更短的URL更好),并且只由字母数字字符组成(这样就不需要在任何地方进行特殊转义)。您可以实现自己的base64编码。如果您可以允许使用两个特定符号-它们可以是任何符号,例如
和-
,那么这并不重要。它甚至可以是其中一个的空间。在任何情况下,您都会这样做:
$alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-";
// using . and - for the two symbols here
$input = [123,193,21,13]; // whatever your input it, I'm assuming an array of bytes
$output = "";
foreach($input as $byte) {
$output .= $alphabet[$byte%64];
}
假设随机输入,所有字符出现的概率相等
也就是说,如果除了纯字母数字之外,您不能允许任何操作,请从
$alphabet
中剪切符号,并使用%62
而不是%64
。虽然这确实意味着你对chracters0
到7
有一点偏见,但我认为这并不值得担心。我在php.net的用户评论中找到了这个函数
function crypto_rand($min,$max) {
$range = $max - $min;
if ($range == 0) return $min; // not so random...
$length = (int) (log($range,2) / 8) + 1;
return $min + (hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s))) % $range);
}
然后做一些类似的事情
for($i=0; $i<20; $i++)
{
$string.= chr(crypto_rand(1,26)+96); //or +64 for upper case
}
for($i=0;$i注意:这是错误的!我将此尝试性答案仅供参考
(31*256)%62=0
对于每个输出的字母数字字符,生成31个随机值。将这31个值相加,取模62
有点残酷,但这是我能想到的唯一一个“数学上正确”的选项:)如果我遇到248-255范围内的字节时丢弃它们会怎么样?这在数学上也是正确的吗?@Vilx-嗯,我不能肯定,但似乎如此。这可能是更明智的选择:)现在我意识到这可能就是被删除的答案的意思……嗯,我认为这实际上是非常错误的。想想看,如果你有两个骰子(标准的六面骰子),你掷它们,最常见的总数是7。这是因为掷骰子有6种方式可以得到“7”,而掷骰子只有1种方式可以得到“2”。这里也一样。更好的类比是:一个骰子与两个骰子获得偶数的几率是多少(总和(骰子)%2=0)。在这两种情况下,概率是相同的。不确定它是否仍然适用于三个骰子。我想我会问:)我也很感兴趣。:)你能给我一个你问题的链接吗?:)