代码之家  ›  专栏  ›  技术社区  ›  tylerl

用openssl_random_pseudo_bytes()替换rand()

  •  15
  • tylerl  · 技术社区  · 16 年前

    我需要一个PHP的替代品 rand() 使用加密强随机数生成器的函数。

    openssl_random_pseudo_bytes() 函数使您可以访问强随机数生成器,但它将其数据作为字节字符串输出。相反,我需要一个介于0和之间的整数 X .

    我想关键是要得到 变成一个整数,然后你可以对它做任何你需要的数学运算。我可以想出一些“蛮力”的方法将字节字符串转换成整数,但我希望有一些东西。。。优雅的

    7 回复  |  直到 12 年前
        1
  •  12
  •   tylerl    11 年前

    根据提供的建议,我使用OpenSSL创建了一个替代rand()的插件。我将把它写在这里供子孙后代使用。

    这个 当结果不能均匀分布在可能的范围内时,选项会重新开始,从而提供无偏差的结果。

    function crypto_rand($min,$max,$pedantic=True) {
        $diff = $max - $min;
        if ($diff <= 0) return $min; // not so random...
        $range = $diff + 1; // because $max is inclusive
        $bits = ceil(log(($range),2));
        $bytes = ceil($bits/8.0);
        $bits_max = 1 << $bits;
        // e.g. if $range = 3000 (bin: 101110111000)
        //  +--------+--------+
        //  |....1011|10111000|
        //  +--------+--------+
        //  bits=12, bytes=2, bits_max=2^12=4096
        $num = 0;
        do {
            $num = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes))) % $bits_max;
            if ($num >= $range) {
                if ($pedantic) continue; // start over instead of accepting bias
                // else
                $num = $num % $range;  // to hell with security
            }
            break;
        } while (True);  // because goto attracts velociraptors
        return $num + $min;
    }
    
        2
  •  8
  •   angrychimp    16 年前

    的手册页 openssl_random_pseudo_bytes() 我想你有一个例子。你可以打个电话 bin2hex() 关于 openssl_随机_伪_字节() hexdec() 在该值上转换为十进制。

    $rand_num = hexdec(bin2hex(openssl_random_pseudo_bytes($length, $strong)));
    

    在这一点上,你可以做任何你想得到的数值在你需要的范围内的数学运算。另一个(作弊者)选项是运行一个系统命令来生成一个随机数——对于各种在线操作系统的随机数生成器,有一些不错的选项。

        3
  •  2
  •   Andrew Calder    12 年前

    下面是上述解决方案的一个版本,它不使用递归函数调用:

    function secure_rand($min,$max) {
        $range = $max - $min + 1;
        if ($range == 0) return $min;
        $length = (int) (log($range,2) / 8) + 1;
        $max = pow(2, 8 * $length);
        $num = $max + 1; // Hackish, I know..
        while ($num > $max) {
            $num = hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s)));
        }
        return ($num  % $range) + $min;
    }
    
        4
  •  2
  •   Scott Arciszewski    10 年前

    由于PHP7现已推出,解决此问题的最简单方法是替换 mt_rand 具有 random_int .

    (假设您已升级,也就是说。)

        5
  •  1
  •   Anti Veeranna    16 年前

    好的,只要在openssl的结果上使用hexdec\u random\u pseudo\u字节,就可以得到整数。它非常优雅:)

    print hexdec('45261b8f');
    
    >  1160125327
    
        6
  •  0
  •   mjsa    11 年前

    做到这一点最简单的方法(也是这里所有选项中最安全的)是使用CryptoLib,它有一个randomInt函数,可以替换rand。

    首先从下载CryptoLib并将其粘贴到项目中: https://github.com/IcyApril/CryptoLib

    <?php
      require_once('path/to/cryptoLib.php');
    
      $min = 1;
      $max = 5;
    
      $randomNum = CryptoLib::randomInt($min, $max);
    ?>
    

    CryptoLib完整文档位于: https://cryptolib.ju.je/

        7
  •  -1
  •   The Surrican    11 年前
    function ($min,$max){
        $range = $max-$min+1;
        do{
            $result = floor($range*(hexdec(bin2hex(openssl_random_pseudo_bytes(4)))/0xffffffff));
        } while($result == $range);    
        return $result + $min;
    }