656

Я никогда не совсем понял это. Просто скажите, что вы пишете небольшую программу на любом языке, которая бросает несколько кубиков (просто на примере кости). После 600 000 бросков каждое число будет свернуто примерно 100 000 раз, что я и ожидал.

Почему существуют сайты, посвященные «истинной случайности»? Конечно, с учетом вышеприведенного наблюдения, шансы получить любое число почти точно равны 1 из всех возможных чисел.

Я попробовал это на Python: вот результат 60 миллионов бросков. Наибольшее отклонение составляет 0,15. Разве это не так случайно, как получится?

1 - 9997653 2347.0
2 - 9997789 2211.0
3 - 9996853 3147.0
4 - 10006533 -6533.0
5 - 10002774 -2774.0
6 - 9998398 1602.0

18 ответов18

1378

Давайте поиграем в компьютерный покер, только вы, я и сервер, которому мы оба доверяем. Сервер использует генератор псевдослучайных чисел, который инициализируется 32-битным начальным числом непосредственно перед началом игры. Таким образом, существует около четырех миллиардов возможных колод.

У меня в руке пять карт - очевидно, мы не играем в Техасский Холдем. Предположим, карты раздаются одному мне, одному вам, одному мне, одному вам и так далее. Итак, у меня в колоде первая, третья, пятая, седьмая и девятая карты.

Ранее я запускал генератор псевдослучайных чисел четыре миллиарда раз, по одному разу с каждым начальным числом, и записывал первую карту, сгенерированную для каждого, в базу данных. Предположим, моя первая карта - Пиковая дама. Это показывает только одну карту как первую в каждой из 52 возможных колод, поэтому мы сократили количество возможных колод с четырех миллиардов до примерно 80 миллионов или около того.

Предположим, моя вторая карта - это три сердца. Теперь я использую свой RNG еще 80 миллионов раз, используя 80 миллионов семян, которые в качестве первого числа дают пиковую даму. Это займет у меня пару секунд. Я записываю все колоды, которые производят три червы, в качестве третьей карты - второй карты в моей руке. Это опять-таки только около 2% колод, так что теперь мы сократили до 2 миллионов колод.

Предположим, что третья карта в моей руке - это 7 треф. У меня есть база данных с 2 миллионами семян, которые раздают мои две карты; Я провожу свой RNG еще 2 миллиона раз, чтобы найти 2% из тех колод, которые производят 7 треф в качестве третьей карты, и у нас осталось всего 40 тысяч колод.

Вы видите, как это происходит. Я запускаю свой RNG 40000 больше раз, чтобы найти все семена, которые производят мою четвертую карту, и это приводит нас к 800 колодам, а затем запускаю его еще 800 раз, чтобы получить ~ 20 семян, которые дают мою пятую карту, и теперь я просто сгенерируйте эти двадцать колод карт, и я знаю, что у вас есть одна из двадцати возможных рук. Более того, я очень хорошо представляю, что буду рисовать дальше.

Теперь вы понимаете, почему важна истинная случайность? Как вы описываете это, вы думаете, что распределение важно, но распределение не делает процесс случайным. Непредсказуемость - это то, что делает процесс случайным.

ОБНОВИТЬ

Исходя из (в настоящее время удаленных из-за их неконструктивного характера) комментариев, по крайней мере 0,3% людей, которые читали это, смущены моей точкой зрения. Когда люди выступают против точек я не сделал, или хуже, утверждают , для точек , которые я сделал на том , что я не делал их, то я знаю , что мне нужно более четко и тщательно объяснить.

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

Вопросы под рукой:

  • Чем отличаются псевдослучайные числа и действительно случайные числа?
  • Почему разница важна?
  • Различия имеют какое-то отношение к распределению выхода PRNG?

Давайте начнем с рассмотрения идеального способа создания случайной колоды карт для игры в покер. Затем мы увидим, как другие методы генерирования колод различны, и если возможно, использовать эту разницу.

Давайте начнем с предположения, что у нас есть волшебная коробка с надписью TRNG . В качестве входных данных мы даем ему целое число n, большее или равное единице, а в качестве выходных данных оно дает нам действительно случайное число от одного до n включительно. Вывод поля совершенно непредсказуем (если ему дано число, отличное от одного), и любое число от одного до n столь же вероятно, как и другое; то есть распределение равномерное . (Существуют и другие более сложные статистические проверки случайности, которые мы могли бы выполнить; я игнорирую этот пункт, поскольку он не соответствует моему аргументу. ТРНГ является совершенно статистически случайным по предположению.)

Начнем с колоды карт без перетасовки. Мы просим в графе число от одного до 52, то есть TRNG(52) . Какое бы число оно не вернуло, мы отсчитываем столько карт из нашей отсортированной колоды и удаляем эту карту. Он становится первой картой в перетасованной колоде. Затем мы просим TRNG(51) и делаем то же самое, чтобы выбрать вторую карту, и так далее.

Еще один способ взглянуть на это: есть 52! = 52 x 51 x 50 ... x 2 x 1 возможных колод, что примерно равно 2 226. Мы выбрали один из них поистине наугад.

Теперь мы сдаем карты. Когда я смотрю на свои карты, я понятия не имею, какие у вас карты. (Помимо очевидного факта, что у вас нет ни одной из моих карт.) Это могут быть любые карты с равной вероятностью.

Итак, позвольте мне убедиться, что я объясню это ясно. У нас есть равномерное распределение каждого отдельного выхода TRNG(n) ; каждый выбирает число от 1 до n с вероятностью 1/n. Кроме того, результатом этого процесса является то, что мы выбрали один из 52! возможные колоды с вероятностью 1/52 !, поэтому распределение по множеству возможных колод также равномерно.

Отлично.

Теперь давайте предположим, что у нас есть менее волшебная коробка с надписью PRNG . Прежде чем вы сможете использовать его, он должен быть заполнен 32-битным беззнаковым номером.

В сторону: почему 32? Разве это не может быть заполнено с 64 или 256 или 10000 бит? Конечно. Но (1) на практике большинство готовых PRNG сеяно с 32-битным числом, и (2) если у вас есть 10000 бит случайности для создания начального числа, тогда зачем вообще использовать PRNG? У вас уже есть источник 10000 бит случайности!

В любом случае, вернемся к тому, как работает PRNG: после того, как он посеян, вы можете использовать его так же, как и TRNG . То есть вы передаете ему число n, и оно возвращает вам число от 1 до n включительно. Кроме того, распределение этого выхода более или менее равномерно . То есть, когда мы просим PRNG число от 1 до 6, мы получаем 1, 2, 3, 4, 5 или 6 примерно одну шестую часть времени, независимо от того, каким было семя.

Я хочу подчеркнуть этот момент несколько раз, потому что он, похоже, сбивает с толку некоторых комментаторов. Распределение PRNG является равномерным, по крайней мере, двумя способами. Сначала предположим, что мы выбрали какое-то конкретное семя. Мы ожидаем, что последовательности PRNG(6), PRNG(6), PRNG(6)... миллион раз дадут равномерное распределение чисел между 1 и 6. И, во-вторых, если мы выбрали миллион различных семян и назвали PRNG(6) один раз для каждого семени, мы снова ожидаем равномерного распределения чисел от 1 до 6. Однородность PRNG в любой из этих операций не имеет отношения к описываемой мной атаке.

Этот процесс называется псевдослучайным, поскольку поведение блока на самом деле полностью детерминировано; он выбирает один из 2 32 возможных вариантов поведения на основе начального числа. То есть, после того, как он будет посеян, PRNG(6), PRNG(6), PRNG(6), ... создает последовательность чисел с равномерным распределением, но эта последовательность полностью определяется начальным числом. Для данной последовательности вызовов, скажем, PRNG(52), PRNG(51) ... и т.д., Существует только 2 32 возможных последовательности. Семя по сути выбирает, какое мы получим.

Для создания колоды сервер теперь генерирует начальное число. (Как? Мы вернемся к этому вопросу.) Затем они вызывают PRNG(52) , PRNG(51) и так далее, чтобы сгенерировать колоду, аналогично предыдущему.

Эта система подвержена атаке, которую я описал. Чтобы атаковать сервер, мы сначала заблаговременно заполняем нашу собственную копию поля 0, запрашиваем PRNG(52) и записываем это. Затем мы снова посеем 1, попросим PRNG(52) и запишем это до 2 32 -1.

Теперь покерный сервер, который использует PRNG для генерации колод, должен каким-то образом генерировать начальное число. Неважно, как они это делают. Они могли бы вызвать TRNG(2^32) чтобы получить действительно случайное семя. Или они могли бы взять текущее время как семя, которое вряд ли случайно; Я знаю, сколько сейчас времени, столько же, сколько и тебе. Суть моей атаки в том, что это не имеет значения, потому что у меня есть база данных. Когда я вижу свою первую карту, я могу уничтожить 98% возможных семян. Когда я вижу свою вторую карту, я могу убрать на 98% больше и так далее, пока в конечном итоге не смогу добраться до горстки возможных семян и с высокой вероятностью узнать, что находится в вашей руке.

Теперь, опять же, я хочу подчеркнуть, что предположение здесь состоит в том, что если бы мы вызывали PRNG(6) миллион раз, мы получали бы каждое число примерно одну шестую времени. Это распределение (более или менее) равномерное, и если однородность этого распределения - это все, что вас волнует, это нормально. Суть вопроса заключалась в том, есть ли что-то еще, кроме распределения PRNG(6) о котором мы заботимся? и ответ да. Мы также заботимся о непредсказуемости.

Другой способ взглянуть на проблему состоит в том, что, хотя распределение миллиона вызовов в PRNG(6) может быть хорошим, поскольку PRNG выбирает только из 32 возможных вариантов поведения, он не может генерировать все возможные колоды. Он может генерировать только 2 32 из 2 226 возможных колод; крошечная фракция. Так что распределение по множеству всех колод очень плохое. Но опять же, фундаментальная атака здесь основана на том, что мы можем успешно предсказать прошлое и будущее поведение PRNG на основе небольшой выборки его результатов.

Позвольте мне сказать это в третий или четыре раза, чтобы убедиться, что это впитывается. Здесь есть три распределения. Во-первых, распределение процесса, который производит случайное 32-разрядное начальное число. Это может быть совершенно случайно, непредсказуемо и равномерно, и атака все равно будет работать. Во-вторых, раздача миллиона звонков в PRNG(6) . Это может быть совершенно одинаково, и атака все равно будет работать. В-третьих, распределение колод, выбранных псевдослучайным процессом, который я описал. Это распределение крайне плохое; только небольшая часть возможных колод IRL может быть выбрана. Атака зависит от предсказуемости поведения PRNG, основанного на частичном знании его выхода.

ASIDE: эта атака требует, чтобы злоумышленник знал или мог угадать, какой именно алгоритм используется PRNG. Реалистично это или нет, остается открытым вопросом. Однако при разработке системы безопасности вы должны спроектировать ее защищенной от атак, даже если злоумышленник знает все алгоритмы в программе. Другими словами, часть системы безопасности, которая должна оставаться секретной, чтобы система была защищенной, называется "ключом". Если ваша система в своей безопасности зависит от алгоритмов, которые вы используете в качестве секрета, тогда ваш ключ содержит эти алгоритмы. Это чрезвычайно слабая позиция, чтобы быть в!

Двигаемся дальше.

Теперь давайте предположим, что у нас есть третий волшебный ящик, помеченный CPRNG . Это крипто-версия PRNG . Требуется 256-разрядное начальное число, а не 32-разрядное. Он разделяет с PRNG свойство, которое семя выбирает из одного из 2 256 возможных вариантов поведения. И, как и у других наших машин, он обладает тем свойством, что большое количество вызовов CPRNG(n) приводит к равномерному распределению результатов между 1 и n: каждый происходит 1/n времени. Можем ли мы провести нашу атаку против него?

Наша первоначальная атака требует, чтобы мы сохранили 2 32 отображения из семян в PRNG(52) . Но 2 256 - намного большее число; совершенно невозможно запускать CPRNG(52) столько раз и сохранять результаты.

Но предположим, что есть какой-то другой способ получить значение CPRNG(52) и из этого вывести факт о семени? До сих пор мы были довольно глупы, просто перебирая все возможные комбинации. Можем ли мы заглянуть внутрь волшебной коробки, выяснить, как она работает, и вывести факты о семени на основе результатов?

Нет. Детали слишком сложны для объяснения, но CPRNG разработаны с умом, так что невозможно вывести какой-либо полезный факт о начальном значении из первого выхода CPRNG(52) или из любого подмножества выходных данных, независимо от их размера.

Хорошо, теперь давайте предположим, что сервер использует CPRNG для генерации колод. Это нуждается в 256-битном семени. Как он выбирает это семя? Если он выбирает какое-либо значение, которое злоумышленник может предсказать, то внезапно атака снова становится жизнеспособной. Если мы сможем определить, что из 2 256 возможных семян, только четыре миллиарда из них будут выбраны сервером, то мы вернемся к делу. Мы можем провести эту атаку снова, обращая внимание только на небольшое количество семян, которые могут быть получены.

Поэтому сервер должен выполнить работу, чтобы обеспечить равномерное распределение 256-битного числа, то есть каждое возможное начальное число выбирается с вероятностью 1/2 256. По сути, сервер должен вызывать TRNG(2^256)-1 для генерации начального числа для CPRNG .

Что если я смогу взломать сервер и заглянуть в него, чтобы увидеть, какое семя было выбрано? В этом случае атакующий знает полное прошлое и будущее CPRNG. Автор сервера должен остерегаться этой атаки! (Конечно, если я смогу успешно провести эту атаку, то, возможно, я также могу просто перевести деньги на свой банковский счет напрямую, так что, возможно, это не так интересно. Дело в том, что начальное число должно быть трудно угадываемым секретом, а действительно случайное 256-битное число чертовски трудно угадать.)

Возвращаясь к моему предыдущему замечанию о глубокой защите: 256-битное начальное число является ключом к этой системе безопасности. Идея CPRNG заключается в том, что система защищена, пока ключ защищен; даже если все остальные факты об алгоритме известны, пока вы можете держать ключ в секрете, карты противника непредсказуемы.

Итак, зерно должно быть как секретным, так и равномерно распределенным, потому что, если это не так, мы можем провести атаку. Предполагается, что распределение выходов CPRNG(n) является равномерным. Как насчет распределения по множеству всех возможных колод?

Вы можете сказать: есть 2 256 возможных последовательностей, выведенных CPRNG, но есть только 2 226 возможных колод. Поэтому существует больше возможных последовательностей, чем колод, так что мы в порядке; каждая возможная колода IRL теперь (с высокой вероятностью) возможна в этой системе. И это хороший аргумент, кроме ...

2 226 является всего лишь приближение 52 !. Разделите это. 2 256/52 ! не может быть целым числом, потому что, с одной стороны, 52! делится на 3, но нет степени двойки! Так как это не целое число , теперь мы имеем ситуацию , когда все палубы возможны, но некоторые палубы более вероятны, чем другие.

Если это не ясно, рассмотрите ситуацию с меньшими числами. Предположим, у нас есть три карты, A, B и C. Предположим, что мы используем PRNG с 8-битным начальным числом, поэтому существует 256 возможных начальных чисел. Есть 256 возможных выходов PRNG(3) зависимости от начального числа; невозможно, чтобы одна треть из них была A, треть из них - B, а треть - C, потому что 256 не делится поровну на 3. Должен быть небольшой уклон к одному из них.

Аналогично, 52 не делится поровну на 2 256, поэтому должен быть некоторый уклон в сторону некоторых карт в качестве первой выбранной карты и уклон в сторону от других.

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

Теперь вопрос: у нас есть атака, основанная на этом недостатке? и ответ на практике, вероятно, нет. CPRNG разработаны так, что если начальное число действительно случайное, то в вычислительном отношении невозможно определить разницу между CPRNG и TRNG .

Хорошо, давайте подведем итоги.

Чем отличаются псевдослучайные числа и действительно случайные числа?

Они отличаются уровнем предсказуемости, которую они демонстрируют.

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

Почему разница важна?

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

  • Если для выбора каждой карты используется TRNG, то система недоступна.
  • Если для выбора каждой карты используется CPRNG, то система безопасна, если начальное число непредсказуемо и неизвестно.
  • Если используется обычный PRNG с небольшим начальным пространством, то система не защищена независимо от того, является ли начальное число непредсказуемым или неизвестным; достаточно малое начальное пространство подвержено атакам грубой силы, которые я описал.

Имеет ли разница какое-то отношение к распределению выхода PRNG?

Равномерность распределения или отсутствие такового для отдельных вызовов RNG(n) не имеет отношения к описанным мною атакам.

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

Еще один вопрос:

Если TRNG намного лучше, чем CPRNG, что, в свою очередь, намного лучше, чем PRNG, почему кто-то использует CPRNG или PRNG?

Две причины.

Первый: расход. TRNG стоит дорого. Генерировать действительно случайные числа сложно. CPRNG дают хорошие результаты для произвольно большого количества вызовов с одним вызовом TRNG для начального числа. Недостатком является то, что вы должны держать это семя в секрете.

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

Я надеюсь, что теперь это намного яснее.

Наконец, если вам понравилось это, то вам может понравиться дальнейшее чтение на тему случайности и перестановок:

157

Как говорит Эрик Липперт, это не просто распространение. Есть и другие способы измерения случайности.

Один из ранних генераторов случайных чисел имеет последовательность в младшем значащем бите - он чередует 0 и 1. Поэтому LSB был предсказуем на 100%. Но вам нужно беспокоиться о чем-то большем. Каждый бит должен быть непредсказуемым.

Вот хороший способ подумать о проблеме. Допустим, вы генерируете 64 бита случайности. Для каждого результата возьмите первые 32 бита (A) и последние 32 бита (B) и создайте индекс в массиве x [A, B]. Теперь выполните тест миллион раз, и для каждого результата увеличьте массив на это число, то есть X [A, B]++;

Теперь нарисуйте 2D-диаграмму, где чем больше число, тем ярче пиксель в этом месте.

Если это действительно случайно, цвет должен быть равномерным серым. Но вы можете получить шаблоны. Возьмем, к примеру, эту диаграмму "случайности" в порядковом номере TCP системы Windows NT:

Windows NT

или даже этот из Windows 98:

Windows 98

А вот и случайность реализации маршрутизатора Cisco (IOS). Cisco ISO

Эти диаграммы любезно предоставлены работой Михаила Залевского. В этом конкретном случае, если можно предсказать, каким будет порядковый номер TCP для системы, можно выдать себя за эту систему при установлении соединения с другой системой, что позволит перехватить соединения, перехватить связь и т.д. И даже если мы не может предсказать следующее число в 100% случаев, если мы можем создать новое соединение под нашим контролем, мы можем увеличить вероятность успеха. И когда компьютеры могут создать 100 000 соединений за несколько секунд, вероятность успешной атаки переходит от астрономической к вероятной или даже вероятной.

93

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

В чувствительных к безопасности приложениях, таких как шифрование, генератор псевдослучайных чисел (PRNG) может выдавать значения, которые, хотя и случайны по внешнему виду, на самом деле предсказуемы злоумышленником. Кто-то, пытающийся взломать систему шифрования, может угадать ключи шифрования, если использовался PRNG, и у злоумышленника есть информация о состоянии PRNG. Следовательно, для таких приложений необходим генератор случайных чисел, который выдает действительно неподдающиеся значения. Обратите внимание, что некоторые PRNG разработаны для криптографической защиты и могут использоваться для таких чувствительных к безопасности приложений.

Больше информации о RNG-атаках можно найти в этой статье в Википедии.

76

Я попробовал это на Python: вот результат 60 миллионов бросков. Наибольшее отклонение составляет 0,15. Разве это не так случайно, как получится?

На самом деле, это так "хорошо", это плохо... Все существующие ответы сосредоточены на предсказуемости, учитывая небольшую последовательность начальных значений. Я хочу поднять еще одну проблему:

    ваше распределение имеет гораздо меньшее стандартное отклонение, чем случайные броски

Правда хаотичность просто не приходит совсем , что близко к усреднению «почти точно 1 над тем, как никогда много чисел можно выбрать из» , что вы используете в качестве показателя качества.

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

 sqrt(N * 35.0 / 12.0).

Используя эту формулу, стандартное отклонение для:

  • 1 миллион рулонов - это 1708
  • 60 миллионов рулонов - это 13229

Если мы посмотрим на ваши результаты:

  • 1 миллион рулонов: стандартное отклонение (1000066, 999666, 1001523, 999452, 999294, 999999) составляет 804
  • 60 миллионов рулонов: stddev (9997653, 9997789, 9996853, 10006533, 10002774, 9998398) - 3827

Вы не можете ожидать, что стандартное отклонение конечной выборки точно совпадет с формулой, но оно должно быть довольно близко. Тем не менее, при 1 миллионе бросков у вас меньше половины правильного стандартного значения, а при 60 миллионах вы меньше трети - становится хуже, и это не случайно ...

Псевдо-ГСЧ имеют тенденцию проходить через последовательность различных чисел, начиная с начального числа и не пересматривая исходное число в течение определенного периода. Например, реализации старой функции C библиотеки rand() обычно имеют период 2 ^ 32, и они будут посещать каждое число от 0 до 2 ^ 32-1 ровно один раз, прежде чем повторять начальное число. Таким образом, если вы смоделировали 2 ^ 32 броска костей, то результаты предварительного модуля (%) будут включать каждое число от 0 до 2 ^ 32, число для каждого результата 1-6 будет 715827883 или 715827882 (2 ^ 32 не является кратный 6), и, следовательно, стандартное отклонение только тривиально выше 0. Используя формулу выше, правильное стандартное отклонение для 2 ^ 32 бросков - 111924. В любом случае, по мере увеличения количества псевдослучайных бросков вы приближаетесь к 0 стандартному отклонению. Можно ожидать, что эта проблема будет существенной, когда число рулонов составляет значительную долю периода, но некоторые псевдо-ГСЧ могут иметь худшие проблемы - или проблемы даже с меньшим количеством образцов - чем другие.

Таким образом, даже если вас не волнуют криптографические уязвимости, в некоторых приложениях вам может потребоваться дистрибутив, который не имеет чрезмерно искусственных результатов. Некоторые типы моделирования довольно конкретно пытаются выяснить последствия неравномерных результатов, которые естественным образом возникают при больших выборках индивидуально случайных результатов, но они недостаточно представлены в результатах некоторых pRNG. Если вы пытаетесь смоделировать, как огромная популяция реагирует на какое-то событие, эта проблема может радикально изменить ваши результаты, что приведет к крайне неточным выводам.


Чтобы привести конкретный пример: скажем, математик говорит программисту покерного автомата, что после 60 миллионов смоделированных бросков - мерцание сотен маленьких "огней" по экрану, если было 10 013 229 или более шестерок, что математик ожидает от 1 стандартное отклонение от среднего, должна быть небольшая выплата. Согласно правилу 68–95–99,7 (Википедия) это должно происходить примерно в 16% случаев (~ 68% попадают в стандартное отклонение / только половина снаружи выше). С вашим генератором случайных чисел это примерно на 3,5 стандартных отклонения выше среднего: вероятность менее 0,025% - почти никто не получает эту выгоду. См. Таблицу "Высокие отклонения" на только что упомянутой странице, а именно:

| Range    | In range   | Outside range | Approx. freq. for daily event  |
| µ ± 1σ   | 0.68268... | 1 in 3        | Twice a week                   |
| µ ± 3.5σ | 0.99953... | 1 in 2149     | Every six years                |
50

Я только что написал этот генератор случайных чисел, чтобы генерировать броски костей

def get_generator():
  next = 1
  def generator():
    next += 1
    if next > 6:
      next = 1
    return next
  return generator

Вы используете это так

>> generator = get_generator()
>> generator()
1
>> generator()
2
>> generator()
3
>> generator()
4
>> generator()
5
>> generator()
6
>> generator()
1

и т. д. и т. д. Будете ли вы использовать этот генератор для программы, в которой запускается игра в кости? Помните, что его распределение именно то, что вы ожидаете от "действительно случайного" генератора!

Генераторы псевдослучайных чисел делают по существу то же самое - они генерируют предсказуемые числа с правильным распределением. Они плохие по той же причине, по которой приведенный выше упрощенный генератор случайных чисел плох - они не подходят для ситуаций, когда вам нужна подлинная непредсказуемость, а не только правильное распределение.

26

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

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

Если вы заинтересованы в приложениях случайных чисел, посмотрите статью в Википедии.

26

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

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

glibc random():
    r[i] ← ( r[i-3] + r[i-31] )  % (2^32)
    output  r[i] >> 1

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

Одной из известных атак на псевдослучайный ключ является атака на WEP 802.11b. WEP имеет 104-битный долгосрочный ключ, соединенный с 24-битным IV (счетчиком) для создания 128-битного ключа, который, в свою очередь, применяется к алгоритму RC4 для генерации псевдослучайного ключа.

( RC4( IV + Key ) ) XOR (message)

Ключи были тесно связаны друг с другом. Здесь только IV увеличивается на 1 на каждом шаге, а все остальные остаются такими же. Так как это не было чисто случайным, оно было катастрофическим и легко сломалось. Ключ можно восстановить, проанализировав около 40000 кадров, что занимает считанные минуты. Если в WEP используется чисто случайный 24-битный IV, то он может быть безопасным примерно до 2 ^ 24 (почти 16,8 миллионов) кадров.

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

12

Разница в том, что сгенерированные псевдослучайными числами предсказуемы (повторяются) через некоторое время, когда истинных случайных чисел нет. Длина повторения зависит от длины семени, которое используется для его производства.

Вот довольно хорошее видео на эту тему: http://www.youtube.com/watch?v=itaMNuWLzJo

10

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

Некоторые люди не поверили бы мне, что это возможно даже при равномерном распределении случайных чисел, но это очевидно возможно, если вы посмотрите на последовательность (1, 3, 5, 2, 4, 1, 3, 5, 2, 4, ...) где второе из двух чисел больше с вероятностью 0,6.

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

10

Предположим, что псевдослучайное число может быть угадано любым, прежде чем оно будет сгенерировано.

Для тривиальных приложений хорошо подходит псевдослучайность, так как в вашем примере вы получите примерно правильный процент (примерно 1/6 от общего набора результатов) с небольшим изменением (которое вы увидите, если бы вы бросали кости 600 КБ). раз);

Тем не менее, когда дело доходит до таких вещей, как компьютерная безопасность; Истинная случайность обязательна.

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

Если злоумышленник может узнать, какие два «случайных» числа выберет ваш компьютер, он может сделать те же шаги, чтобы вычислить ваш закрытый ключ (тот, который никто не должен знать!)

Используя ваш закрытый ключ, злоумышленник может делать что-то вроде: а) говорить с вашим банком, притворяясь вами, б) слушать ваш «безопасный» интернет-трафик и иметь возможность его расшифровывать, в) маскироваться между вами и другими участниками в Интернете.

Вот где требуется истинная случайность (то есть невозможность угадать / рассчитать).

8

Короткий ответ заключается в том, что обычно люди требуют "истинной случайности" по плохой причине, а именно, что они не понимают криптографию.

Криптографические примитивы, такие как потоковые шифры и CSPRNG , используются для создания огромных потоков непредсказуемых битов после того, как они получили несколько непредсказуемых битов.

Внимательный читатель теперь поймет, что здесь есть проблема с начальной загрузкой: мы должны собрать несколько кусочков энтропии, чтобы начать все это. Тогда be может передать их CSPRNG, который, в свою очередь, с радостью предоставит все непредсказуемые биты, которые нам нужны. Таким образом, аппаратный RNG требуется для заполнения CSPRNG. Это единственный случай, когда в действительности требуется энтропия.

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

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

Изменить: Некоторые люди здесь предполагают модель угрозы, в которой злоумышленник может прочитать внутреннее состояние CSPRNG и оттуда прийти к выводу, что CSPRNG не являются безопасным решением. Это пример плохого моделирования потоков. Если злоумышленник владеет вашей системой, игра окончена, просто и понятно. Не имеет значения, используете ли вы TRNG или CSPRNG на данном этапе.

Редактировать: Итак, чтобы подвести итог всего этого ... Энтропия необходима для создания CSPRNG. Как только это будет сделано, CSPRNG предоставит все непредсказуемые биты, которые нам нужны для приложений безопасности, гораздо быстрее, чем мы можем (обычно) собирать энтропию. Если непредсказуемость не требуется, например для моделирования, Mersenne Twister предоставит числа с хорошими статистическими свойствами с гораздо более высокой скоростью.

Изменить: Любой, кто хочет понять проблему безопасной генерации случайных чисел, должен прочитать это: http://www.cigital.com/whitepapers/dl/The_Importance_of_Reliable_Randomness.pdf

7

Не все PRNG подходят для любого использования. Например, Java.util.SecureRandom использует хеш SHA1, который имеет размер вывода 160 бит. Это означает, что из него может быть 2 160 возможных потоков случайных чисел. Просто как тот. Вы не можете получить более 2 160 значений внутреннего состояния. Таким образом, вы не можете получить более 2 160 уникальных потоков случайных чисел из одного семени, независимо от того, откуда пришло ваше семя. Windows CryptGenRandom, как полагают, использует 40-байтовое состояние, он имеет 2 320 возможных потоков случайных чисел.

Количество способов перетасовать стандартную колоду из 52 карт составляет 52!, Что составляет примерно 2 226. Таким образом, независимо от заполнения, вы не можете использовать Java.util.SecureRandom перемешать колоду карт. Есть приблизительно 2 66 возможных тасовок, которые он не может произвести. Конечно, мы не знаем, какие они ...

Итак, если бы у меня был источник, скажем, 256-битной истинной случайности (например, с карты Quantis RNG), я мог бы посеять PRNG, такой как CryptGenRandom (), с этим начальным числом, а затем использовать PRNG, чтобы перетасовать колоду карты. Если я засею с каждой случайной случайной случайностью случайности, это будет хорошо: непредсказуемо и статистически случайно. Если бы я сделал то же самое с Java.util.SecureRandom, были бы тасования, которые невозможно было бы произвести, потому что он не может быть заполнен 256 битами энтропии, а его внутреннее состояние не может представлять все возможные тасования.

Обратите внимание, что java.util.Результаты SecureRandom будут как непредсказуемыми, так и статистически случайными. Никакой статистический тест никогда не выявит проблему! Но выход RNG недостаточно велик, чтобы охватить весь домен всех возможных выходов, необходимых для симуляции колоды карт.

И помните, если вы добавите джокеров, это 54! что вы должны покрыть, что требует около 2 238 возможностей.

6

Разница между "истинным" случайным и "псевдо" случайным числом заключается в предсказуемости. Этот ответ уже был предоставлен.

Однако предсказуемость не обязательно является плохой вещью, как показывает большинство примеров. Вот практический пример одного из редких случаев, когда предсказуемость хорошая: Глобальная система позиционирования.

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

6

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

2

Для быстрой проверки случайности вы берете точки со случайными координатами в [0; 1), а затем помещаете их в k-мерный куб. Затем вы делаете процедуру, чтобы нарезать этот куб на подкубы - каждый объем подкуба (или подсферы) должен быть правильно измерен этой процедурой с флуктуациями согласно хорошо известной теореме.

Качество случайности важно там, где вы встречаетесь ...

  1. в целях безопасности. Когда вы генерируете число для использования в качестве параметра для генерации ключа, и оно вполне предсказуемо - враг обнаружит его с вероятностью 100% и сделает поле для поиска намного меньшим.

  2. научные цели. В науке вы должны иметь не только среднее среднее значение в хорошем состоянии, но также должны быть устранены корреляции между различными случайными числами. Поэтому, если вы возьмете (a_i - a) (a_ {i+1} -a) и найдете его распределение, оно должно соответствовать статистике.

Парная корреляция - это так называемая "слабая случайность". Если вам нужна реальная случайность, вы должны иметь корреляцию высокого порядка с более чем 2 дисперсиями.

Сегодня только генераторы квантовой механики обеспечивают истинную случайность.

1

Почему важна истинная случайность?

Есть две основные причины, по которым необходима истинная случайность:

  1. Если вы используете RNG для криптографии (включая такие вещи, как азартные игры на реальные деньги и проведение лотереи), то PRNG сделает ваш шифр намного слабее, чем математический анализ (который предполагает TRNG) заставит вас поверить. PRNG на самом деле не будет случайным, но будет иметь паттерн - противники могут использовать паттерн, чтобы взломать шифр, который должен был быть не взломанным.
  2. Если вы используете RNG для имитации "случайных" входных данных, например, для тестирования ошибок или симуляции, то PRNG делает ваш подход слабым. Когда вы не обнаружите никаких ошибок, всегда будет ноющее сомнение: есть ли ошибка, которая не заметна в шаблоне моего PRNG, но появилась бы, если бы я использовал только TRNG? Точно ли мои результаты моделирования описывают реальность, или явление, которое я обнаружил, является просто артефактом модели PRNG?

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

Как PRNG Python недостаточно хорош?

Маловероятно, что вы сможете обнаружить ловушки реального PRNG, используя такую простую методологию. Статистический анализ ГСЧ является самостоятельной областью науки, и для оценки "случайности" алгоритма доступны некоторые очень сложные тесты. Это намного сложнее, чем ваша простая попытка.

Каждый разработчик программного обеспечения, который создает реальные библиотеки, такие как разработчики Python, используют эти статистические тесты в качестве критерия, чтобы убедиться, что их реализация PRNG достаточно хороша. Таким образом, за исключением случаев фактического надзора за разработчиками, очень маловероятно, что вы сможете легко обнаружить шаблон в реальном PRNG. Это не значит, что нет шаблона - у ГСЧП есть шаблон по определению.

0

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

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

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

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

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

-4

Короткий рассказ:

Создает случайное начальное число, используя текущую микросекунду системы.

Этот трюк довольно старый и все еще функционален.

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

Скажем, в качестве примера, я могу определить использованное начальное число, используя только 10 значений. Итак, зная семя, я могу угадать следующее значение.

Если бы я использовал seed = 1, я мог бы получить следующую последовательность:

1, 2, 3, 4, 5, 6, 7, 8, 9 ... (и я вычитаю, что начальное число использовало id 1 и следующее значение 10)

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

Итак, последовательность теперь такова:(seed = 1) 1, 2, 3, 4, 5, (seed = 2), 7, 9, 11, 13 ... (15?)

В этом случае:

а) Я не могу определить, какое семя было использовано.

б) Ergo, я не могу угадать следующее значение.

в) Единственное, что я могу сделать, - это вычесть, что следующим семенем может быть старшее число.

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .