2013-04-03 2 views
3

Я заполнение массива случайных чисел с помощью $blockhash[$i] = rand().time().rand()SHA512 для генерации случайных чисел в PHP

Тогда для каждого случайного числа в этом массиве рассчитать корреспондентском SHA512

$SecretKey = "60674ccb549f1988439774adb82ff187e63a2dfd403a0dee852e4e4eab75a0b3"; 
$sha = hash_hmac('sha512', $value, $SecretKey); 

Разделить его:

$pool = str_split($sha, 2); 

Тогда я получаю первый номер из массива пула $, конвертировать гекс в десятичную и ограничить его в пределах 1 и 50:

$dec = hexdec($pool[0]) % 50 + 1; 

Проблема в том, что цифры не являются случайными, и я не знаю почему. Я подсчитываю частоту для каждого номера от 1 до 50, но цифры 1,2,3,4,5 и 6 чаще появляются, чем другие. См график

enter image description here

Почему это происходит и как это исправить? Благодаря!

ответ

1

Вы получаете 1-6 чаще, потому что вы получаете две шестнадцатеричные цифры из хэша. Это один байт, поэтому он может хранить значения от 0 до 255. Затем вы используете modulo 50. В результате вы получаете диапазоны 0-49, 50-99, 100-149, 150-199, 200-249 и ... 250-255. Этот последний отвечает за дополнительную распространенность 1-6 в ваших результатах.

Решение: просто использовать mt_rand(1,50);

[править]

Если вам действительно нужно преобразовать число из диапазона 0-255 1-50 диапазона, то решение было бы масштабирования и округления.

$number = round(($byteValue)/(255/49))+1; 
+0

Да, я мог бы пойти простым путем, просто сделав это, но мне действительно нужно получить байт из хэша, а затем ограничить его. Итак, каков способ ограничить его до 1-50 без по модулю? – andrepcg

+1

@andrepcg: см. Обновленный answe – Mchl

1

Ни rand(), ни mt_rand() не генерируют поистине случайные значения.

В ручными состояниях:

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

См. Better Random Generating PHP для вопроса StackOverflow, который указывает ту же проблему и содержит некоторые полезные ответы.

+0

но не забывайте, что я использую SHA512 для генерации некоторых случайных символов. Случайный() должен просто заполнить массив содержимым – andrepcg

4

2 шестнадцатеричных символа, которые вы преобразуете в десятичную, будут в диапазоне 0-255. вы измените это на 50 и добавьте 1, сделав 1-6 (диапазон (0-5) +1), 6 раз по 1-256, а каждый другой номер - всего 5 раз. Это приведет к увеличению на 20% роста этих цифр.

+0

Спасибо! Таким образом, проблема - мода. Что с этим делать? Как я могу ограничить его до 1-50 без ущерба для случайности? – andrepcg

Смежные вопросы