Подтвердить что ты не робот

Замените rand() на openssl_random_pseudo_bytes()

Мне нужна замена для функции PHP rand(), которая использует криптографически сильный генератор случайных чисел.

Функция openssl_random_pseudo_bytes() получает доступ к генератору сильных случайных чисел, но выводит свои данные в виде байтовой строки. Вместо этого мне нужно целое число от 0 до X.

Я полагаю, что ключ состоит в том, чтобы получить вывод openssl_random_pseudo_bytes() в целое число, тогда вы можете выполнить любую математику, в которой вы нуждаетесь. Я могу придумать несколько способов перебора из строки байтов в целое число, но я надеялся на что-то... элегантное.

4b9b3361

Ответ 1

Используя предоставленные предложения, я создал замену для rand() с помощью OpenSSL. Я включу его здесь для потомства.

Параметр $pedantic предоставляет результаты без смещения, начиная с момента, когда результаты не будут равномерно распределены в пределах возможного диапазона.

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

На странице руководства для openssl_random_pseudo_bytes() приведен пример, который, я думаю, вы хотите. Вы можете просто вызвать bin2hex() на выходе openssl_random_pseudo_bytes() для преобразования в шестнадцатеричное число, а затем hexdec() для этого значения, чтобы преобразовать в десятичный.

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

В этот момент вы можете делать любую математику, которую хотите получить, в нужном вам диапазоне. Другой вариант (мошенник), который у вас есть, - запустить системную команду для генерации случайного числа - есть несколько хороших вариантов для генераторов случайных чисел для различных операционных систем, доступных в Интернете.

Ответ 3

Вот версия вышеперечисленных решений, которая не использует рекурсивные вызовы функций:

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

Поскольку PHP 7 сейчас отсутствует, самый простой способ решить эту проблему - заменить все экземпляры mt_rand на random_int.

(Предположим, что вы обновили, то есть.)

Ответ 5

ну, просто используйте hexdec для результата openssl_random_pseudo_bytes, и вы получите свое целое число. Это так же изящно, как и получается:)

print hexdec('45261b8f');

>  1160125327

Ответ 6

Самый простой способ сделать это (и самый безопасный из всех вариантов здесь) - использовать CryptoLib, который имеет функцию randomInt, которая предоставляет замену для rand.

Сначала загрузите CryptoLib и вставьте его в свой проект: https://github.com/IcyApril/CryptoLib

Два, запустите этот код. замените путь/на/с каталогом cryptolib.php и min max с минимальным и максимальным номерами:

<?php
  require_once('path/to/cryptoLib.php');

  $min = 1;
  $max = 5;

  $randomNum = CryptoLib::randomInt($min, $max);
?>

Полная документация CryptoLib: https://cryptolib.ju.je/

Ответ 7

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;
}