Как использовать boost :: random_device для генерации криптографически безопасного 64-битного целого числа?

Я хотел бы сделать что-то вроде этого:

boost::random_device rd;
boost::random::mt19937_64 gen(rd());
boost::random::uniform_int_distribution<unsigned long long> dis;
uint64_t value = dis(gen);

Но я читал, что твистер Мерсенна не криптографически безопасен. Тем не менее, я также читал, что random_device может быть, если он извлекает данные из / dev / urandom, который, вероятно, на платформе Linux (моя основная платформа). Так что, если random_device не является детерминистически случайным и используется для заполнения мерсенового твистера (как показано выше), разве это не делает криптографически безопасным твистер мерсенна (хотя само по себе это не так)?

Я немного новичок в этой области, поэтому любые советы приветствуются.

Итак, как я могу сгенерировать криптографически защищенное 64-битное число, которое может быть сохранено в uint64_t?

Спасибо,

Бен.

5

Решение

Анализ вашего вопроса сложнее, чем может показаться:

Вы семя мерсенна твистер с rd(), который возвращает unsigned intи, следовательно, (на большинстве платформ) содержит не более 32 случайных битов.

Все, что делает с этого момента твистер Мерсенна, определяется этими 32 битами.

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

Основная слабость мерсенного твистера (его состояние можно узнать, увидев 624 числа) даже не представляет интереса в этом случае, так как вы генерируете последовательность, которая является настолько короткой (1 значение).

Генерация 64 криптографически безопасных битов

При условии, что unsigned int эквивалентно uint32_t на вашей платформе вы можете легко сгенерировать 64 криптографически безопасных случайных бита, используя boost::random_device:

boost::random_device rd;
std::uint64_t value = rd();
value = (value << 32) | rd();

Это довольно безопасно, так как реализации для Linux и Windows использовать собственные криптографически защищенные источники случайности операционной системы.

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

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

boost::random_device rd;
boost::random::uniform_int_distribution<std::uint64_t> dis;
std::uint64_t value = dis(rd);

(Хотя теоретически это может также обеспечить более надежное решение, если предыдущее фактически не содержит числа в [0, 2 ** 32), на практике это не является проблемой.)

Распределение привязки к генератору

Для повышения удобства использования вы часто найдете использование boost::bind связать распределение и генератор вместе. поскольку boost::bind копирует свои аргументы, и копия ctor удаляется для boost::random_device, вам нужно использовать небольшую хитрость:

boost::random_device rd;
boost::random::uniform_int_distribution<std::uint64_t> dis;
boost::function<std::uint64_t()> gen = boost::bind(dis, boost::ref(rd));
std::uint64_t value = gen();
7

Другие решения

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

val = dis (rd);

Для большей безопасности инициализируйте случайное устройство с помощью /dev/random скорее, чем /dev/urandom, /dev/random будет блокироваться, если не хватит энтропии, пока не произойдут случайные вещи. Однако, это может быть намного, намного медленнее.

Кстати, при условии, что у вас есть высококачественная реализация C ++ 11, которая не возвращает поддельные значения для entropy использование C ++ 11 может быть лучшей идеей, если вы пытаетесь удалить зависимости.

РЕДАКТИРОВАТЬ: Очевидно, есть некоторые споры о том, является ли / dev / random лучше, чем / dev / urandom. Я отсылаю вас к этот.

-1

По вопросам рекламы [email protected]