Intereting Posts
Как получить доступ к таблице внутри схемы без использования префикса схемы (Postgres + PHP)? Вызов функции в методе класса? Kohana_Exception : Требуется действительная соль cookie. Пожалуйста, установите Cookie :: $ salt как отображать имя пользователя в URL-адресе Как остановить jQuery TourBus от создания двух экземпляров при нажатии? Удаление любого существующего файла из Dropzone показывает dictDefaultMessage Можно ли проанализировать список каталогов на внешней веб-странице? Обновление страницы ajax на форме submit Важно ли проверять, является ли загруженный файл фактическим файлом изображения? PDO отправляет необработанный запрос в MySQL, в то время как Mysqli отправляет подготовленный запрос, оба дают тот же результат Доступ к закрытым переменным из закрытия Symfony вызывает сборщик мусора PHP на Ubuntu 14.04, даже если session.gc_probability установлен в 0 Переписать на красивые ссылки с nginx Как вы соответствуете одному из двух слов в регулярном выражении? Как открыть файл Excel с помощью PHPExcel для чтения и записи?

Генерировать криптографически безопасные случайные числа в php

Функция rand() PHP не дает хороших случайных чисел. Поэтому я начал использовать mt_rand() который, как говорят, дает лучшие результаты. Но насколько хороши эти результаты? Есть ли какие-то методы для их улучшения?

Моя идея:

 function rand_best($min, $max) { $generated = array(); for ($i = 0; $i < 100; $i++) { $generated[] = mt_rand($min, $max); } shuffle($generated); $position = mt_rand(0, 99); return $generated[$position]; } 

Это должно дать вам «идеальные» случайные числа, не так ли?

Генераторы псевдослучайных чисел (PRNG) – очень сложный зверь.

Нет никаких реальных «совершенных» генераторов случайных чисел – на самом деле лучшее, что можно сделать с помощью математических функций, является псевдослучайным – они кажутся случайными для большинства целей и целей.

Фактически, выполнение любых дополнительных действий из числа, возвращаемого PRNG, на самом деле не увеличивает его случайность, и на самом деле число может стать менее случайным.

Итак, мой лучший совет: не вмешивайтесь со значениями, возвращаемыми из PRNG. Используйте PRNG, который достаточно хорош для предполагаемого использования, а если нет, то найдите PRNG, который может принести лучшие результаты, если это необходимо.

И, откровенно говоря, похоже, что функция mt_rand использует Mersenne twister , что является довольно хорошим PRNG, так как это, вероятно, будет достаточно хорошим для большинства случайных целей.

Тем не менее, Mersenne Twister не предназначен для использования в любых контекстах безопасности . См. Этот ответ для решения, которое нужно использовать, когда вам нужна случайность для обеспечения безопасности.

редактировать

В комментариях был вопрос, почему выполнение операций с случайным числом может сделать его менее случайным. Например, некоторые PRNG могут возвращать более последовательные, менее случайные числа в разных частях бит – high-end может быть более случайным, чем младший.

Поэтому в операциях, в которых элитный класс отбрасывается, а нижний конец возвращается, значение может стать менее случайным, чем исходное значение, возвращенное из PRNG.

На данный момент я не могу найти хорошее объяснение, но я основывался на документации Java для Random.nextInt(int) , который предназначен для создания довольно случайного значения в указанном диапазоне. Этот метод учитывает разницу в случайности частей значения, поэтому он может возвращать лучшее случайное число по сравнению с более наивными реализациями, такими как rand() % range .

Быстрый ответ:

В новом PHP7 есть, наконец, поддержка криптографически защищенных псевдослучайных целых чисел.

 int random_int ( int $min , int $max ) 

Существует также полипол для PHP5x .

Более длинный ответ


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

Тот же совет, что и в криптографии «не изобретайте свой собственный шифр», можно перевести на генераторы случайных чисел и означать, что вы не можете просто получить множество генераторов случайных чисел, объединенных вместе, и получите возможность получить лучший генератор.


Одним из подмножеств генераторов случайных чисел являются криптографически защищенные генераторы случайных чисел :

Требования обычного PRNG также удовлетворяются криптографически защищенным PRNG, но обратное неверно. Требования CSPRNG делятся на две группы: во-первых, они проходят статистические тесты случайности; во-вторых, что они находятся под серьезной атакой, даже когда часть их начального или запущенного состояния становится доступной для злоумышленника

Так что это довольно близко к вашему определению « совершенный ». Еще один раз без каких-либо условий (кроме обучения криптографии) вы должны попытаться реализовать один из этих алгоритмов и использовать его в своей системе.


Но, к счастью, PHP7 реализовал его,

 int random_int ( int $min , int $max ) 

Генерирует криптографические случайные целые числа, которые подходят для использования, когда критические (непредсказуемые) результаты имеют решающее значение (т. Е. Перетасовка колоды покера).

Источниками случайных являются следующие:

  • В Windows CryptGenRandom () используется исключительно
  • arc4random_buf () используется, если он доступен (как правило, BSD)
  • / dev / arandom используется, если доступно
  • Сценарий getrandom(2) (на новых ядрах Linux)
  • / dev / urandom используется там, где ни одно из указанных выше не доступно

Это приводит к тому, что все предыдущие ответы устарели (и некоторые устарели).

Я не уверен, что вы сделали «улучшает» случайность. Из того, что я могу понять, вы генерируете 100 случайных чисел, а затем произвольно выбираете один из них.

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

Каким образом mt_rand () «плохой»?

Например: если он поддерживает определенное число. Допустим, mt_rand (1, 10) поддерживает низкие числа в диапазоне, то есть «1» и «2» происходит в среднем более 10% каждый. Тогда ваше «улучшение» по-прежнему будет страдать от одной и той же проблемы.

Выбор случайного числа из неисправной последовательности будет по-прежнему неисправен.

 <?php function random_number(){ return 4; // return generated number // guaranteed to be random } ?> 

Все шутя в сторону, вы начинаете философский вопрос о том, что такое «случайный» или «лучший». В идеале вы хотели бы, чтобы ваши случайные числа имели несколько шаблонов в них в ходе вашей процедуры. Обычно в качестве семени используется системное время, но я также использовал предыдущее случайное число как семя, предыдущее случайное число – как семя. Проблема в том, что с достаточно мощным компьютером и полным знанием работающего оборудования и функции генератора вы сможете предсказать весь набор генерируемых чисел. Таким образом, если бы у вас был достаточно мощный компьютер (некоторые люди поместили Бога в эту категорию), который знал все возможные переменные и функции вселенной, вы могли бы предсказать каждое событие, которое произошло или произойдет. Большинство генераторов случайных чисел прекрасно себя чувствуют, но если вы знаете кого-то, кто может видеть шаблоны, более вероятно, что они похожи на парня в Beautiful Mind, и вы должны проверить их в клинике.

По популярному запросу : D

Я написал cronjob, который периодически получает 1000 чисел из random.org (скажем, один раз в час) и добавляет их в массив PHP. Всякий раз, когда я хочу случайные числа в моем сценарии, я использую mt_rand (0,1000), чтобы вызвать номер из этого. Несколько дополнительных микросекунд накладных расходов, но я получаю действительно случайные числа, основанные на естественном атмосферном шуме.

Все зависит от того, для чего вам нужно это случайное число 🙂 Для меня ShuffleBag – лучший! 🙂

Изменить: Мой комментарий больше не действителен. См. Следующий ответ: https://stackoverflow.com/a/31443898/109561


Я предполагаю, что вы беспокоитесь о распространении mt_rand (). Я протестировал его, и он очень ровный, и обе границы включены.

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

Если вам не нравится PHP, встроенный в rand() , вы, вероятно, не должны использовать их встроенный shuffle() , поскольку он, похоже, построен на их rand() .

Я на полпути уверен, что «промышленный стандарт» перетасовки теперь – перетасовка Фишера- Йейта.

Нет такого понятия, как «идеальное» случайное число. Независимо от того, какое субъективное определение «совершенного» у вас есть. Вы можете достигать псевдослучайного.

Я просто пытался указать вам в правильном направлении. Вы задали вопрос о идеальных случайных числах, даже если совершенные были в кавычках. И да, вы можете улучшить случайность. Вы даже можете реализовать эвристические или «естественные» алгоритмы, такие идеи, как «атмосферный шум», – но тем не менее вы не идеальны, никоим образом.

использовать / dev / ramdom (генератор случайных чисел реального устройства linux) для семян mt_rand

 <? $rnd_dev=mcrypt_create_iv(4, MCRYPT_DEV_RANDOM); //need "apt-get install php5-mcrypt" $seed=ord(substr($rnd_dev, 0, 1))<<24 | ord(substr($rnd_dev, 1, 1))<<16 | ord(substr($rnd_dev, 2, 1))<<8 | ord(substr($rnd_dev, 3, 1)); mt_srand($seed); echo mt_rand(); ?> 

Я создал класс PHP для генерации случайных чисел и строк PHPRandomValue

Он использует «mcrypt_create_iv (4, MCRYPT_DEV_URANDOM)» для генерации случайных чисел и значений. Я сделал это, работая над криптопроектом, потому что мне нужен безопасный генератор случайных значений. Вот пример использования

 $randomValue = new RandomValue; $randomValue->randomNumber(): = -3880998 $randomValue->randomNumberBetween(1,10): = 2 $randomValue->randomTextString(): = CfCkKDHRgUULdGWcSqP4 $randomValue->randomTextString(10): = LorPIxaeEY $randomValue->randomKey(): = C7al8tX9.gqYLf2ImVt/!$NOY79T5sNCT/6Q.$!.6Gf/Q5zpa3 $randomValue->randomKey(10): = RDV.dc6Ai/ 

Невозможно генерировать истинные случайные числа, лучшее, на что вы можете надеяться, является псевдослучайным, что обеспечивает rand (), ваша функция не ближе к случайному, а затем к rand (). Взгляните на этот http://en.wikipedia.org/wiki/Random_number_generator

Случайные числа Tru

 <?php for ($i = -1; $i <= 4; $i++) { $bytes = openssl_random_pseudo_bytes($i, $cstrong); $hex = bin2hex($bytes); echo "Lengths: Bytes: $i and Hex: " . strlen($hex) . PHP_EOL; var_dump($hex); var_dump($cstrong); echo PHP_EOL; } ?> 

а также криптозащита;)

Хотя ответ был принят много лет назад, я снова его открою.

Так как вся эта случайность зависит от системного времени, давайте также испортить системное время! Количество времени, которое занимает операция на компьютере, на самом деле довольно изменчиво (особенно, если на этом сервере происходит что-то другое), поэтому, если мы воспользуемся этим с помощью microtime … (не удалось найти какие-либо переносные команды nanotime)

 $a=''; for (int $i=0; $i<9001; $i++) { usleep(mt_rand(1000,10000));//Also eliminates timing attacks... possibly? $a=hash('SHA512',$a.uniqid(mt_rand().microtime(),true)); } echo $a; 

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

Вы знаете о каких-либо операциях на PHP, которые занимают действительно случайное количество времени? Как … HTTP-запрос на некоторый сайт (кроме RANDOM.org) и измерение времени, которое требуется?

Используя random.org, вы можете использовать это:

 function getToken($length, $min, $max){ $r = explode(' ',file_get_contents('http://www.random.org/integers/num='.$length.'&min='.$min.'&max='.$max.'&col=1&base=10&format=plain')); $string = ''; foreach ( $r as $char ) $string.=$char; return $string; } 

это должно давать реальные случайные числа