如何从PHP中获取0-X的加密强整数?

时间:2013-11-01 17:25:33

标签: php random

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

据我所知,在PHP中,密码强随机性的主要来源是openssl_random_pseudo_bytes()。然而,这会返回一个字节数组,而不是字母数字字符。

要将它们转换为字母数字,我可以将它们哈希(这将产生一个有限的十六进制字符集的长度超过必需的字符串),或base64_encode()它们(这将生成一个{{1}的字符串}},+/在其中 - 不是字母数字)。

所以我认为相反,我可以使用随机字节作为熵源,并生成我自己的字符串,仅包含字符=

然后问题变成了 - 如何从256个不同的值(输入的一个字节)转换为62个不同的值(输出的一个字符)。在某种程度上,所有62个角色的可能性相同。 (否则会有8个字符比其余字符更频繁出现。)

或许我应该完全使用另一种方法?我希望我的字符串尽可能短(例如,20个字符左右 - 更短的URL更好),并且只包含字母数字字符(因此不需要在任何地方进行特殊转义)。

3 个答案:

答案 0 :(得分:2)

您可以实现自己的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。虽然这确实意味着您对字符07的偏差较小,但我认为这并不足以让您担心。

答案 1 :(得分:0)

我在用户评论中在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
  }

或类似。

答案 2 :(得分:0)

注意:这是错的!我留下这个尝试的答案仅供参考。

(31 * 256)%62 = 0

对于每个输出字母数字字符,生成31个随机值。对这31个值求和并取模62。

有点残酷,但这是我能想到的唯一“数学上正确”选项:)