Детерминированная генерация криптографически защищенных ключей и IVEC

StackOverflow https://stackoverflow.com/questions/4303607

Вопрос

Предыстория

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

В Чем Проблема

Мне нужно сгенерировать IVEC и ключи, которые действительны в течение определенного периода времени, скажем, одной недели (текущая действительная пара).и что прошлые IVECs / ключи также действительны, скажем, в течение 2 недель (исторически действительные), и любые данные, зашифрованные исторически действительными секретами, будут просто повторно зашифрованы текущим IVEC / КЛЮЧОМ.

Что мне нужно, так это детерминированный CSPRNG, который содержит случайное число и кодовую фразу и который может создавать индексированным способом 64-битные или 128-битные блоки чисел.Если я использую weeks-since-"1 января 1970" в качестве одного из элементов индекса моего гипотетического CSPRNG, я смогу построить систему, которая автоматически меняет ключи с течением времени.

Подход, который я рассматриваю

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

RIPEMD160(randomcompregeneratedfixednonce:Кодовая фраза:UInt64SinceEpoch:128BitBlockIndexNumber);

Примечание:Номера блоков будут назначены и будут иметь регулярную структуру, так что, например, для 128-битного дайджеста первые 64 бита блока 0 будут для ivec, а весь элемент 1 - для 128-битного ключа.

Является ли это разумным подходом (т. е. криптографически безопасным)?

-- редактировать:опубликовать принять комментарий --

После некоторого размышления я решил объединить то, что я первоначально считал парольной фразой, и одноразовый номер / соль в 16-байтовый (криптографически надежный) ключ и использовать методы, описанные в PKCS # 5, для получения нескольких ключей, основанных на времени.В соли нет необходимости, так как парольные фразы не используются.

Это было полезно?

Решение

Интересный вопрос.

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

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

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

Возможно, вы также захотите ознакомиться со схемой генерации ключей, изложенной в PKCS # 5 (напримерв http://www.faqs.org/rfcs/rfc2898.html), который реализован в cryptopp как passwordbasedkeyderivationфункция.Этот механизм уже широко используется и известен как достаточно безопасный (обратите внимание, что PKCS # 5 рекомендует хэшировать данные парольной фразы не менее 1000 раз).Вы могли бы просто добавить свой срок действия и индексировать данные к парольной фразе и использовать passwordbasedkeyderivationфункцию в ее нынешнем виде.

Вы не говорите, какой алгоритм шифрования вы предлагаете использовать для шифрования данных, но я бы посоветовал вам выбрать что-то широко используемое и известное как безопасное...и, в частности, я бы посоветовал вам использовать AES.Я бы также предложил использовать одну из функций дайджеста SHA (возможно, в качестве входных данных для PasswordBasedKeyDerivationFunction).SHA-2 является текущим, но SHA-1 достаточно для целей генерации ключей.

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

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

Другие советы

То, что мне нужно, это детерминированное CSPRNG, которое семена случайного числа и пароля, и которые могут производить в индексированной моде 64-битную или 128-битные блоки чисел. Если я использую несколько недель, поскольку - «1 января 1970 года» как один из индексов моего гипотетического CSPRNG, я должен иметь возможность построить систему, которая автоматически изменяет ключи, как и время.

Ну, я считать Часть решения состоит в том, чтобы использовать невременный генератор. Таким образом, если обе стороны начинаются с того же семени, то они оба производят один и тот же случайный поток. Вы можете сломать ваши «недели с недели 1, 1970» логику сверху этого.

Сделать это, вы бы использовали OFB_mode<T>::Encryption. Анкет Он может быть использован в качестве генератора, потому что режим OFB использует AdditiveCipherTemplate<T>, что происходит от RandomNumberGenerator.

На самом деле CRPYTO ++ использует генератор в test.cpp Таким образом, результаты могут быть воспроизведены, если что -то не удается. Вот как бы вы использовали OFB_mode<T>::Encryption. Анкет Это также относится к CTR_Mode<T>::Encryption:

SecByteBlock seed(32 + 16);
OS_GenerateRandomBlock(false, seed, seed.size());

for(unsigned int i = 0; i < 10; i++)
{
    OFB_Mode<AES>::Encryption prng;
    prng.SetKeyWithIV(seed, 32, seed + 32, 16);

    SecByteBlock t(16);
    prng.GenerateBlock(t, t.size());

    string s;
    HexEncoder hex(new StringSink(s));

    hex.Put(t, t.size());
    hex.MessageEnd();

    cout << "Random: " << s << endl;
}

Призыв к OS_GenerateRandomBlock Выбирают байты из /dev/{u|s}random а затем использует это как симулированное общее семя. Каждый пробег программы будет другим. В каждом запуске программы он печатает аналогично следующим:

$ ./cryptopp-test.exe
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD

Есть еще один генератор, который делает то же самое, но он не является частью библиотеки Crypto ++. Это называется AES_RNG, и его на основе AES-256. Его заголовок только в реализации, и вы можете найти его в крипто ++ Wiki под RandomNumberGenerator.

Также см. Тема Воспроизводимость за RandomNumberGenerator Класс на крипто ++ вики.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top