Я хотел бы сделать что-то вроде этого:
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?
Спасибо,
Бен.
Анализ вашего вопроса сложнее, чем может показаться:
Вы семя мерсенна твистер с rd()
, который возвращает unsigned int
и, следовательно, (на большинстве платформ) содержит не более 32 случайных битов.
Все, что делает с этого момента твистер Мерсенна, определяется этими 32 битами.
Это означает, что value
может принимать только 2 ** 32 различных значения, что может быть проблемой, если существует какой-либо вектор атаки, который атакует все, что вы делаете с этим числом, грубой силой. На самом деле, процедура посева мерсеннового твистера может даже уменьшить количество возможных значений для первого результата, поскольку она распределяет 32 случайных бита по своему полному состоянию (чтобы убедиться, что это не тот случай, когда вам придется анализировать повышение подпрограммы посева использует).
Основная слабость мерсенного твистера (его состояние можно узнать, увидев 624 числа) даже не представляет интереса в этом случае, так как вы генерируете последовательность, которая является настолько короткой (1 значение).
При условии, что 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();
Использование случайного устройства только для заполнения не является криптографически безопасным. Затем проблема сводится к выяснению начального начального числа, что значительно уменьшает проблему. Вместо этого напрямую используйте случайное устройство.
val = dis (rd);
Для большей безопасности инициализируйте случайное устройство с помощью /dev/random
скорее, чем /dev/urandom
, /dev/random
будет блокироваться, если не хватит энтропии, пока не произойдут случайные вещи. Однако, это может быть намного, намного медленнее.
Кстати, при условии, что у вас есть высококачественная реализация C ++ 11, которая не возвращает поддельные значения для entropy
использование C ++ 11 может быть лучшей идеей, если вы пытаетесь удалить зависимости.
РЕДАКТИРОВАТЬ: Очевидно, есть некоторые споры о том, является ли / dev / random лучше, чем / dev / urandom. Я отсылаю вас к этот.