如何在PHP中从0-X获得加密强整数?

如何在PHP中从0-X获得加密强整数?,php,random,Php,Random,我想在PHP中生成随机字母数字字符串。它们将用于随机数的强度很重要的地方(URL等中的公共可见ID) 据我所知,在PHP中,加密强随机性的主要来源是openssl\u random\u pseudo\u bytes()。但是,这将返回字节数组,而不是字母数字字符 要将它们转换为字母数字,我可以对它们进行散列(这将产生一个超过必要长度的有限十六进制字符集字符串),或者base64_encode()它们(这将产生一个包含+,/和=的字符串,而不是字母数字) 因此,我认为我可以使用随机字节作为熵的来源

我想在PHP中生成随机字母数字字符串。它们将用于随机数的强度很重要的地方(URL等中的公共可见ID)

据我所知,在PHP中,加密强随机性的主要来源是
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
。虽然这确实意味着你对chracters
0
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)。在这两种情况下,概率是相同的。不确定它是否仍然适用于三个骰子。我想我会问:)我也很感兴趣。:)你能给我一个你问题的链接吗?:)