DeepRand
Авторский алгоритм генерации (псевдо)случайных чисел.
Автор: Д.Н. Трунов
Краткое описание
Генератор DeepRand основан на авторском блочном шифре ESCK-7 и состоит из идентичного ключа шифрования (256 чисел по 64 бита) и функции GFunc() для его генерации/изменения. Генерация чисел в алгоритме напоминает шифрование блока в ESCK-7 с той разницей, что в данном случае блок состоит всего из одного 64-битного числа, шифруется необратимым способом, а результат возвращается в виде очередного «случайного» числа. Каждое такое шифрование постепенно меняет и сам ключ, что призвано обеспечить непредсказуемость генерируемых чисел и снизить риски зацикливания (повторения серии чисел).
Алгоритм реализован в виде объектного класса DeepRand, каждый экземпляр которого содержит свой собственный ключ и своё состояние. Основная рандомизация выполняется в момент создания экземпляра класса, но дополнительные возможны позднее с помощью вызова функции Randomize(), причём все последующие рандомизации дополняют предыдущие, накапливая случайность.
Функция Randomize() может принимать 64-битное число или байтовый массив длиной до 2048 байт с начальными случайными данными для инициализации алгоритма. Вариант с 64-битным инициализирующим числом может выполнять быструю рандомизацию с изменением лишь части ключа или полноценную с изменением всего ключа функцией GFunc(). Во втором случае кроме инициализирующего числа необходимо указать количество циклов изменения ключа.
Генерация очередного числа выполняется функциями Generate() или GenerateFast(). Вторая работает быстрее и по скорости превосходит даже Mersenne Twister (std::mt19937), генерируя числа приемлемого качества. Первая же функция рекомендуется для более требовательных задач, в том числе в криптографии. Впрочем, результаты генераций обеими функциями довольно неплохо проходят тесты на случайность (NIST SP 800-22).
Примеры работы с алгоритмом
random_device r_d; // источник начальной случайности
DeepRand Rand(r_d()); // создание экземпляра и инициализация по r_d
// или с циклами: DeepRand Rand(r_d(), 5);
uint64_t R = Rand.Generate(); // медленная генерация
R = Rand.GenerateFast(); // быстрая генерация
R = Rand(); // равнозначно GenerateFast()
Rand.Randomize(r_d()); // быстрая дополнительная рандомизация
Rand.Randomize(r_d(), 10); // полноценная рандомизация, 10 циклов
uint8_t RandomData[32];
Rand.Randomize(RandomData, 32); // рандомизация байтовым массивом
// или с циклами:
Rand.Randomize(RandomData, 32, 10);
Особенности и замечания
Быстрая рандомизация меняет только часть ключа и это изменение со временем распространится на весь ключ по мере новых рандомизаций или запусков Generate(), но GenerateFast() может довольно медленно реагировать на такие изменения ключа. Рекомендуется выполнять быстрые рандомизации только для частого добавления в алгоритм случайности, но перед любой генерацией необходимо выполнить полноценную рандомизацию с изменением всего ключа, указав в Randomzie() циклы.
PassGen
Программа PassGen является примером применения алгоритма DeepRand для генерации паролей (строк случайных символов). Программа предлагает пользователю вводить желаемую длину пароля (1..256, 0 - для выхода из программы) и генерирует пароль указанной длины. Реализована рандомизация по std::random_device и часам std::chrono::high_resolution_clock как в момент запуска программы, так и перед каждой генерацией пароля.
Numbers
Программа Numbers - ещё один пример применения алгоритма. Генерирует ряд чисел заданной длины. Байтовый размер чисел, длину ряда и формат отображения (hex/dec) можно указать в параметрах при запуске. В программе реализована рандомизация по std::random_device, локальному Seed-файлу и часам std::chrono::high_resolution_clock.