Как называются модуль в котором описаны функции генерации случайных чисел
Перейти к содержимому

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

  • автор:

Линейные алгоритмы обработки числовых данных

Будьте внимательны! У Вас есть 10 минут на прохождение теста. Система оценивания — 5 балльная. Разбалловка теста — 3,4,5 баллов, в зависимости от сложности вопроса. Порядок заданий и вариантов ответов в тесте случайный. С допущенными ошибками и верными ответами можно будет ознакомиться после прохождения теста. Удачи!

Система оценки: 5 балльная

Список вопросов теста

Вопрос 1

Как называются алгоритмы, в которых команды выполняются последовательно в том порядке, в котором они записаны?

Варианты ответов
  • Линейные
  • Разветвляющиеся
  • Циклические
  • Рекурсивные
Вопрос 2

Сопоставьте значения данных и их типы.

Подробно о генераторах случайных и псевдослучайных чисел

image

На Хабре и в сети часто начали появляться статьи, посвященные уязвимостям генераторов случайных чисел. Данная тема крайне обширна и является одной из основных в криптографии. Под катом находится описание случайных чисел от A до Z. Статья является результатом свободного перевода цикла статей из одного западного блога и личных дополнений автора. Основная цель — получить feedback и поделиться знаниями.

Введение
  • Генераторы сессий (PHPSESSID)
  • Генерация текста для капчи
  • Шифрование
  • Генерация соли для хранения паролей в необратимом виде
  • Генератор паролей
  • Порядок раздачи карт в интернет казино
Как отличить случайную последовательность чисел от неслучайной?

Пусть есть последовательность чисел: 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 . Является ли она случайной? Есть строгое определение для случайной величины. Случайная величина — это величина, которая принимает в результате опыта одно из множества значений, причём появление того или иного значения этой величины до её измерения нельзя точно предсказать. Но оно не помогает ответить на наш вопрос, так как нам не хватает информации для ответа. Теперь скажем, что данные числа получились набором одной из верхних строк клавиатуры. «Конечно не случайная» — воскликните Вы и тут же назовете следующие число и будете абсолютно правы. Последовательность будет случайной только если между символами, нету зависимости. Например, если бы данные символы появились в результате вытягивания бочонков в лото, то последовательность была бы случайной.

Чуть более сложный пример или число Пи

Последовательность цифры в числе Пи считается случайной. Пусть генератор основывается на выводе бит представления числа Пи, начиная с какой-то неизвестной точки. Такой генератор, возможно и пройдет «тест на следующий бит», так как ПИ, видимо, является случайной последовательностью. Однако этот подход не является критографически надежным — если криптоаналитик определит, какой бит числа Пи используется в данный момент, он сможет вычислить и все предшествующие и последующие биты.
Данный пример накладывает ещё одно ограничение на генераторы случайных чисел. Криптоаналитик не должен иметь возможности предсказать работу генератора случайных чисел.

Отличие генератора псевдослучайных чисел (ГПСЧ) от генератора случайных чисел (ГСЧ)

Источники энтропии используются для накопления энтропии с последующим получением из неё начального значения (initial value, seed), необходимого генераторам случайных чисел (ГСЧ) для формирования случайных чисел. ГПСЧ использует единственное начальное значение, откуда и следует его псевдослучайность, а ГСЧ всегда формирует случайное число, имея в начале высококачественную случайную величину, предоставленную различными источниками энтропии.
Энтропия – это мера беспорядка. Информационная энтропия — мера неопределённости или непредсказуемости информации.
Можно сказать, что ГСЧ = ГПСЧ + источник энтропии.

Уязвимости ГПСЧ
  • Предсказуемая зависимость между числами.
  • Предсказуемое начальное значение генератора.
  • Малая длина периода генерируемой последовательности случайных чисел, после которой генератор зацикливается.
Линейный конгруэнтный ГПСЧ (LCPRNG)

Распространённый метод для генерации псевдослучайных чисел, не обладающий криптографической стойкостью. Линейный конгруэнтный метод заключается в вычислении членов линейной рекуррентной последовательности по модулю некоторого натурального числа m, задаваемой следующей формулой:

image

где a (multiplier), c (addend), m (mask) — некоторые целочисленные коэффициенты. Получаемая последовательность зависит от выбора стартового числа (seed) X0 и при разных его значениях получаются различные последовательности случайных чисел.

Для выбора коэффициентов имеются свойства позволяющие максимизировать длину периода(максимальная длина равна m), то есть момент, с которого генератор зациклится [1].

Пусть генератор выдал несколько случайных чисел X0, X1, X2, X3. Получается система уравнений

image

Решив эту систему, можно определить коэффициенты a, c, m. Как утверждает википедия [8], эта система имеет решение, но решить самостоятельно или найти решение не получилось. Буду очень признателен за любую помощь в этом направлении.

Предсказание результатов линейно-конгруэнтного метода

Основным алгоритмом предсказания чисел для линейно-конгруэнтного метода является Plumstead’s — алгоритм, реализацию, которого можно найти здесь [4](есть онлайн запуск) и здесь [5]. Описание алгоритма можно найти в [9].
Простая реализация конгруэнтного метода на Java.

public static int a = 45; public static int c = 21; public static int m = 67; public static int seed = 2; public static int getRand() < seed = (a * seed + c) % m; return seed; >public static void main(String[] args)

Отправив 20 чисел на сайт [4], можно с большой вероятностью получить следующие. Чем больше чисел, тем больше вероятность.

Взлом встроенного генератора случайных чисел в Java

Многие языки программирования, например C(rand), C++(rand) и Java используют LСPRNG. Рассмотрим, как можно провести взлом на примере java.utils.Random. Зайдя в исходный код (jdk1.7) данного класса можно увидеть используемые константы

private static final long multiplier = 0x5DEECE66DL; // 25214903917 private static final long addend = 0xBL; // 11 private static final long mask = (1L  

Метод java.utils.Randon.nextInt() выглядит следующим образом (здесь bits == 32)

protected int next(int bits) < long oldseed, nextseed; AtomicLong seed = this.seed; do < oldseed = seed.get(); nextseed = (oldseed * multiplier + addend) & mask; >while (!seed.compareAndSet(oldseed, nextseed)); return (int)(nextseed >>> (48 - bits)); > 

Результатом является nextseed сдвинутый вправо на 48-32=16 бит. Данный метод называется truncated-bits, особенно неприятен при black-box, приходится добавлять ещё один цикл в brute-force. Взлом будет происходить методом грубой силы(brute-force).

Пусть мы знаем два подряд сгенерированных числа x1 и x2. Тогда необходимо перебрать 2^16 = 65536 вариантов oldseed и применять к x1 формулу:

((x1*multiplier + addend) & mask)  

до тех пор, пока она не станет равной x2. Код для brute-force может выглядеть так

import java.lang.reflect.Field; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; public class PasswordCracking < public static final long multiplier = 0x5DEECE66DL; public static final long addend = 0xBL; public static final long mask = (1L for simplicity will use Reflection */ Field privateSeedField = Random.class.getDeclaredField("seed"); privateSeedField.setAccessible(true); AtomicLong crackingSeed = (AtomicLong)privateSeedField.get(crackingRandom); crackingSeed.set(seed); >catch(Exception e) < System.out.println(e.toString()); System.exit(1); >long cv1 = crackingRandom.nextInt(); long cv2 = crackingRandom.nextInt(); long cv3 = crackingRandom.nextInt(); long cv4 = crackingRandom.nextInt(); System.out.println("Set fiend seed and generate random numbers"); System.out.println("cv1=" + cv1 + "\ncv2=" + cv2 + "\ncv3=" + cv3 + "\ncv4 java">v1 = -1184958941 v2 = 274285127 v3 = -1566774765 v4 = 30466408 Seed found: -77657469128792 Set fiend seed and generate random numbers cv1 = 274285127 cv2 = -1566774765 cv3 = 30466408 cv4 = -803980434 

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

public static long getPreviousSeed(long prevSeed) < long seed = prevSeed; // reverse the addend from the seed seed -= addend; // reverse the addend long result = 0; // iterate through the seeds bits for (int i = 0; i < 48; i++) < long mask = 1L > System.out.println("Previous seed: " + result); return result; > 

И теперь в исходном коде заменим
crackingSeed.set(seed);
на
crackingSeed.set(getPreviousSeed(seed));

И всё, мы успешно взломали ГПСЧ в Java.

Взлом ГПСЧ Mersenne twister в PHP

Рассмотрим ещё один не криптостойкий алгоритм генерации псевдослучайных чисел Mersenne Twister. Основные преимущества алгоритма — это скорость генерации и огромный период 2^19937 − 1, На этот раз будем анализировать реализацию алгоритма mt_srand() и mt_rand() в исходном коде php версии 5.4.6.

Содержимое файла /ext/standard/basic_functions.h

#define MT_N (624) /* rand.c */ php_uint32 state[MT_N+1]; /* state vector + 1 extra to not violate ANSI C */ php_uint32 *next; /* next random value is computed from here */ int left; /* can *next++ this many times before reloading */ unsigned int rand_seed; /* Seed for rand(), in ts version */ zend_bool rand_is_seeded; /* Whether rand() has been seeded */ zend_bool mt_rand_is_seeded; /* Whether mt_rand() has been seeded */ 

Содержимое файла /ext/standard/rand.c:

#define N MT_N /* length of state vector */ #define M (397) /* a period parameter */ #define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ #define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ #define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(u))) & 0x9908b0dfU)) /* /* >>> */ /* > 30) ) + i ) & 0xffffffffU; r++; > > /* >>> */ /* /* >>> */ /* --BG(left); s1 = *BG(next)++; s1 ^= (s1 >> 11); s1 ^= (s1 > 18) ); > 

Можно заметить, что php_mt_reload вызывается при инициализации и после вызова php_mt_rand 624 раза. Начнем взлом с конца, обратим трансформации в конце функции php_mt_rand(). Рассмотрим (s1 ^ (s1 >> 18)). В бинарном представление операция выглядит так:

10110111010111100111111001110010 s1
00000000000000000010110111010111100111111001110010 s1 >> 18
10110111010111100101001110100101 s1 ^ (s1 >> 18)
Видно, что первые 18 бит (выделены жирным) остались без изменений.
Напишем две функции для инвертирования битового сдвига и xor

public static long unBitshiftRightXor(long value, long shift) < // we part of the value we are up to (with a width of shift bits) long i = 0; // we accumulate the result here long result = 0; // iterate until we've done the full 32 bits while (i * shift < 32) < // create a mask for this part long partMask = (-1 >> (shift * i); // obtain the part long part = value & partMask; // unapply the xor from the next part of the integer value ^= part >>> shift; // add the part to the result result |= part; i++; > return result; > public static long unBitshiftLeftXor(long value, long shift, long mask) < // we part of the value we are up to (with a width of shift bits) long i = 0; // we accumulate the result here long result = 0; // iterate until we've done the full 32 bits while (i * shift < 32) < // create a mask for this part long partMask = (-1 >>> (32 - shift)) return result; > 

Тогда код для инвертирования последних строк функции php_mt_rand() будет выглядеть так

long value = output; value = unBitshiftRightXor(value, 18); value = unBitshiftLeftXor(value, 15, 0xefc60000); value = unBitshiftLeftXor(value, 7, 0x9d2c5680); value = unBitshiftRightXor(value, 11); 

Если у нас есть 624 последовательных числа сгенерированных Mersenne Twister, то применив этот алгоритм для этих последовательных чисел, мы получим полное состояние Mersenne Twister, и сможем легко определить каждое последующее значение, запустив php_mt_reload для известного набора значений.

Область для взлома

Если вы думаете, что уже нечего ломать, то Вы глубоко заблуждаетесь. Одним из интересных направлений является генератор случайных чисел Adobe Flash(Action Script 3.0). Его особенностью является закрытость исходного кода и отсутствие задания seed'а. Основной интерес к нему, это использование во многих онлайн-казино и онлайн-покере.
Есть много последовательностей чисел, начиная от курса доллара и заканчивая количеством времени проведенным в пробке каждый день. И найти закономерность в таких данных очень не простая задача.

Задание распределения для генератора псевдослучайных чисел

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

Треугольное распределение

Приведем пример генерации случайной величины с треугольным распределением [7] на языке C99.

double triangular(double a, double b, double c) < double U = rand() / (double) RAND_MAX; double F = (c - a) / (b - a); if (U

В данном случае мы берем случайную величину rand() и задаем ей распределение, исходя из функции треугольного распределения. Для параметров a = -40, b = 100, c = 50 график 10000000 измерений будет выглядеть так

image

Экспоненциальное распределение

Пусть требуется получить датчик экспоненциально распределенных случайных величин. В этом случае F(x) = 1 – exp(-lambda * x). Тогда из решения уравнения y = 1 – exp(-lambda * x) получаем x = -log(1-y)/lambda.
Можно заметить, что выражение под знаком логарифма в последней формуле имеет равномерное распределение на отрезке [0,1), что позволяет получать другую, но так же распределённую последовательность по формуле: x = -log(y)/lambda, где y есть случайная величина(rand()).

Тесты ГПСЧ

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

Одним из известных тестов является тест на следующий бит — тест, служащий для проверки генераторов псевдослучайных чисел на криптостойкость. Тест гласит, что не должно существовать полиномиального алгоритма, который, зная первые k битов случайной последовательности, сможет предсказать k+1 бит с вероятностью большей ½.

В теории криптографии отдельной проблемой является определение того, насколько последовательность чисел или бит, сгенерированных генератором, является случайной. Как правило, для этой цели используются различные статистические тесты, такие как DIEHARD или NIST. Эндрю Яо в 1982 году доказал, что генератор, прошедший «тест на следующий бит», пройдет и любые другие статистические тесты на случайность, выполнимые за полиномиальное время.
В интернете [10] можно пройти тесты DIEHARD и множество других, чтобы определить критостойкость алгоритма.

Известные взломы генераторов случайных чисел
  • Ранние версии протокола шифрования SSL компании Netscape, c малой энтропией [11]
  • Уязвимость PHP сессий habrahabr.ru/company/pt/blog/149746
  • CryptGenRandom компании Microsoft [12]
  • Многие онлайн казино не раз становились объектом атаки через уязвимости в ГПСЧ

Модуль random

Модуль random предоставляет функции для генерации случайных чисел, букв, случайного выбора элементов последовательности.

random.betavariate(alpha, beta) ¶

бета-распределение. alpha > 0 , beta > 0 . Возвращает от 0 до 1.

random.choice(sequence) ¶

возвращает случайный элемент непустой последовательности

random.expovariate(lambd) ¶

экспоненциальное распределение. lambd равен 1/среднее желаемое. Lambd должен быть отличным от нуля. Возвращаемые значения от 0 до плюс бесконечности, если lambd положительно, и от минус бесконечности до 0, если lambd отрицательный.

random.gammavariate(alpha, beta) ¶

гамма-распределение. Условия на параметры alpha > 0 и beta > 0 .

random.gauss(значение, стандартное отклонение) ¶

random.getrandbits(N) ¶

возвращает N случайных бит.

random.getstate() ¶

внутреннее состояние генератора.

random.lognormvariate(mu, sigma) ¶

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

random.normalvariate (mu, sigma) ¶

нормальное распределение. mu — среднее значение, sigma — стандартное отклонение.

random.paretovariate(alpha) ¶

random.randint(A, B) ¶

случайное целое число N, A ≤ N ≤ B .

random.random() ¶

случайное число от 0 до 1.

random.randrange(start, stop, step) ¶

возвращает случайно выбранное число из последовательности.

random.sample(population, k) ¶

список длиной k из последовательности population.f

random.seed( X , version=2) ¶

инициализация генератора случайных чисел. Если X не указан, используется системное время.

random.setstate(state) ¶

восстанавливает внутреннее состояние генератора. Параметр state должен быть получен функцией getstate() .

random.shuffle(sequence, rand ) ¶

перемешивает последовательность (изменяется сама последовательность). Поэтому функция не работает для неизменяемых объектов.

random.triangular(low, high, mode) ¶

случайное число с плавающей точкой, low ≤ N ≤ high . Mode — распределение.

random.uniform(A, B) ¶

случайное число с плавающей точкой, A ≤ N ≤ B (или B ≤ N ≤ A ).

random.vonmisesvariate(mu, kappa) ¶

mu — средний угол, выраженный в радианах от 0 до 2π, и kappa — параметр концентрации, который должен быть больше или равен нулю. Если каппа равна нулю, это распределение сводится к случайному углу в диапазоне от 0 до 2π.

random.weibullvariate((alpha, beta) ¶

Хотите выучить Python на практике?

С нуля и до создания компьютерной игры
Собственный онлайн-тренажер с проверкой практических задач
25 бесплатных уроков сразу после регистрации
10 000+ учеников
Попробовать бесплатно
©2023 Letpy

Мы используем файлы cookie

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

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

Модуль random управляет генерацией случайных чисел. Его основные функции:

  • random() : генерирует случайное число от 0.0 до 1.0
  • randint() : возвращает случайное число из определенного диапазона
  • randrange() : возвращает случайное число из определенного набора чисел
  • shuffle() : перемешивает список
  • choice() : возвращает случайный элемент списка

Функция random() возвращает случайное число с плавающей точкой в промежутке от 0.0 до 1.0. Если же нам необходимо число из большего диапазона, скажем от 0 до 100, то мы можем соответственно умножить результат функции random на 100.

import random number = random.random() # значение от 0.0 до 1.0 print(number) number = random.random() * 100 # значение от 0.0 до 100.0 print(number)

Функция randint(min, max) возвращает случайное целое число в промежутке между двумя значениями min и max.

import random number = random.randint(20, 35) # значение от 20 до 35 print(number)

Функция randrange() возвращает случайное целое число из определенного набора чисел. Она имеет три формы:

  • randrange(stop) : в качестве набора чисел, из которых происходит извлечение случайного значения, будет использоваться диапазон от 0 до числа stop
  • randrange(start, stop) : набор чисел представляет диапазон от числа start до числа stop
  • randrange(start, stop, step) : набор чисел представляет диапазон от числа start до числа stop, при этом каждое число в диапазоне отличается от предыдущего на шаг step
import random number = random.randrange(10) # значение от 0 до 10 не включая print(number) number = random.randrange(2, 10) # значение в диапазоне 2, 3, 4, 5, 6, 7, 8, 9 print(number) number = random.randrange(2, 10, 2) # значение в диапазоне 2, 4, 6, 8 print(number)

Работа со списком

Для работы со списками в модуле random определены две функции: функция shuffle() перемешивает список случайным образом, а функция choice() возвращает один случайный элемент из списка:

numbers = [1, 2, 3, 4, 5, 6, 7, 8] random.shuffle(numbers) print(numbers) random_number = random.choice(numbers) print(random_number)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *