Правильные ответы по криптографии: 2018 год
В литературе и самых сложных современных системах есть «лучшие» ответы на многие вопросы. Если вы разрабатываете встроенные приложения, то предлагают использовать STROBE и модный современный криптографический стек для аутентификации полностью из одиночных SHA-3-подобных функций губки. Советуют использовать NOISE для разработки безопасного транспортного протокола с формированием общего ключа аутентификации (AKE). Говоря об AKE, есть около 30 различных парольных AKE на выбор.
Но если вы разработчик, а не криптограф, то не должны делать ничего такого. Следует придерживаться простых и обычных решений, которые легко поддаются анализу — «скучных», как говорят люди из Google TLS.
Правильные ответы по криптографии
Шифрование данных
Percival, 2009: AES-CTR с HMAC.
Ptacek, 2015: (1) настройки по умолчанию NaCl/libsodium; (2) ChaCha20-Poly1305 или (3) AES-GCM.
Latacora, 2018: KMS или XSalsa20+Poly1305
Нужно в случае, если: вы скрываете информацию от пользователей или от сети.
Если вам удобно использовать KMS, аппаратный модуль безопасности Amazon (или Google), то используйте KMS. Если вы могли бы использовать KMS, но шифрование — забавный проект на выходные, позволяющий сэкономить деньги на KMS, то точно используйте KMS. Если вы шифруете простые секреты, вроде токенов API для вашего приложения в стартапе, используйте SSM Parameter Store, то есть KMS. Вам не нужно понимать, как работает KMS.
В противном случае вам в идеале хотелось бы получить AEAD: аутентифицированное шифрование с присоединёнными данными (опция для аутентифицированных заголовков открытым текстом).
Основной способ получить аутентифицированное шифрование — использовать потоковый шифр (обычно AES в режиме CTR) с полиномиальным MAC (код аутентификации сообщений, криптографический CRC).
Во всех этих мейнстримовых решениях вы столкнётесь с одной проблемой — это нонсы (nonce: number that can only be used once — число, которое может быть использовано один раз). Нужно, чтобы вы придумали уникальное (обычно случайное) число для каждого потока, которое никогда не будет повторно использовано. Проще всего генерировать нонсы из безопасного генератора случайных чисел, поэтому вам нужна простая схема для этого.
Нонсы особенно важны для AES-GCM, самого популярного режима шифрования. К сожалению, как раз с AES-GCM реализовать их особенно сложно: здесь мы балансируем на границе безопасного использования случайных нонсов.
Поэтому мы рекомендуем использовать XSalsa20-Poly1305. Это разновидность конструкций ChaPoly, которые в совокупности являются наиболее распространёнными конструкциями шифрования после AES-GCM. Возьмите XSalsa20-Poly1305 в libsodium или NaCl.
Преимущество XSalsa20 над ChaCha20 и Salsa20 в том, что XSalsa поддерживает расширенные нонсы. Они достаточно большие, так что вы просто создаёте большой длинный случайный нонс для каждого потока — и не беспокоитесь о том, сколько потоков нужно шифровать.
Существуют схемы NMR или MRAE, которые обещают некоторую степень безопасности даже при неправильном обращении с нонсами; к ним относятся GCM-SIV (на самом деле все SIV) и Deoxys-II, финалист конкурса CAESAR. Они интересны, но в реальности никто пока не поддерживает и не использует их, а с расширенными нонсами выигрыш в безопасности едва различим. Это не очень скучные схемы. А нам пока нужно оставаться скучными.
Избегать: AES-CBC, AES-CTR самого по себе, блочных шифров с 64-битными блоками — особенно необъяснимо популярного Blowfish, избегайте режима OFB. Никогда не используйте RC4, который комически сломан.
Длина симметричного ключа
Percival, 2009: используйте 256-битные ключи.
Ptacek, 2015: используйте 256-битные ключи.
Latacora, 2018: вперёд, используйте 256-битные ключи.
Нужно в случае, если: вы используете криптографию.
Но помните: ваш ключ AES сломают с гораздо меньшей вероятностью, чем вашу пару с открытым ключом, поэтому размер последнего должен быть больше, если вы собираетесь зацикливаться на этом.
Избегать: конструкций с огромными ключами, шифровальных «каскадов», размеров ключей до 128 бит.
Симметричные «подписи»
Percival, 2009: используйте HMAC.
Ptacek, 2015: да, используйте HMAC.
Latacora, 2018: по-прежнему HMAC.
Нужно в случае, если: вы защищаете API, шифруете сеансовые куки или шифруете пользовательские данные, но, вопреки совету доктора, не применяете конструкцию AEAD.
Если у вас аутентификация без шифрования, как с запросами API, не делайте ничего сложного. Существует класс багов криптореализации из-за того, как данные отправляются на MAC, так что если разрабатываете новую систему с нуля, погуглите «crypto canonicalization bugs». Кроме того, применяйте безопасную функцию сравнения.
Если используете HMAC, то найдутся советчики, которые укажут вам, что SHA3 (и усечённые хеши SHA2) могут делать KMAC, то есть можно просто сцепить ключ и данные, хешировать их и быть в безопасности. Это означает, что в теории HMAC выполняет ненужную дополнительную работу с SHA-3 или усечённым SHA-2. Но кого это волнует? Представьте HMAC как дешёвую страховку для вашего дизайна на случай, если кто-то переключится на неусечённый SHA-2.
Избегать: самодельных конструкций «хеша с ключом», HMAC-MD5, HMAC-SHA1, сложных полиномиальных MAC, шифрованных хешей, CRC.
Алгоритм хеширования
Percival, 2009: используйте SHA256 (SHA-2).
Ptacek, 2015: используйте SHA-2.
Latacora, 2018: по-прежнему SHA-2.
Нужно в случае, если: это всегда нужно.
Если вам подходит: используйте SHA-512/256, который усекает выходные данные и уклоняется от атак удлинением сообщения.
Мы по-прежнему думаем, что апгрейд с SHA-2 на SHA-3 менее вероятен, чем на что-то более быстрое, чем SHA-3. И поскольку SHA-2 до сих пор выглядит великолепно, чувствуйте себя комфортно и оставайтесь на SHA-2.
Избегать: SHA-1, MD5, MD6.
Случайные ID
Percival, 2009: используйте 256-битные случайные числа.
Ptacek, 2015: используйте 256-битные случайные числа.
Latacora, 2018: используйте 256-битные случайные числа.
Нужно в случае, если: это всегда нужно.
Из /dev/urandom.
Избегать: генераторов случайных чисел из пользовательского пространства, ГСЧ из OpenSSL, havaged, prngd, egd, /dev/random.
Обработка паролей
Percival, 2009: scrypt или PBKDF2.
Ptacek, 2015: в порядке предпочтения scrypt, bcrypt, а если больше ничего не доступно, то PBKDF2.
Latacora, 2018: в порядке предпочтения scrypt, argon2, bcrypt, а если больше ничего не доступно, то PBKDF2.
Нужно в случае, если: вы принимаете пароли от пользователей или где-то в системе есть человекочитаемые секретные ключи.
Нет, в самом деле: вы можете бросить дротик и выбрать наугад один из перечисленных вариантов. Технически argon2 и scrypt существенно лучше, чем bcrypt, который намного лучше, чем PBKDF2. Но на практике главное, чтобы вы использовали действительно безопасный парольный хеш, а не то, какой именно из них.
Не создавайте сложные схемы хеширования паролей.
Избегать: SHA-3, голого SHA-2, SHA-1, MD5.
Асимметричное шифрование
Percival, 2009: используйте RSAES-OAEP с SHA256 и MGF1+SHA256.
Ptacek, 2015: используйте NaCl / libsodium (box / crypto_box).
Latacora, 2018: используйте NaCl / libsodium (box / crypto_box).
Нужно в случае, если: требуется зашифровать сообщение для многих разных людей, в том числе незнакомых, и они должны быть в состоянии принять сообщение асинхронно, как в электронной почте, а затем расшифровать его в автономном режиме. Это довольно специфический случай использования.
Из всех криптографических «правильных ответов» именно этот вы вряд ли получите самостоятельно. Не используйте внештатное шифрование с открытым ключом и низкоуровневые криптографические библиотеки вроде OpenSSL или BouncyCastle.
Вот несколько причин, почему следует прекратить использовать RSA и переключиться на эллиптические кривые:
- RSA (и DH) тянут вас к «обратной совместимости» с небезопасными системами, делая возможными атаки с понижением протокола.
- RSA просит шифровать напрямую с помощью своего примитива открытого ключа, что обычно противоречит интересам пользователей.
- В RSA слишком много настроек. В современных системах на эллиптических кривых вроде Curve25519 всё заранее настроено для безопасности.
NaCl использует Curve25519 (самую популярную современную систему на эллиптических кривых, тщательно разработанную для устранения нескольких классов атак против стандартных кривых NIST) в сочетании со схемой ChaPoly AEAD. У вашего языка программирования есть привязки к NaCl (или, в случае Go, собственная реализация библиотеки) — используйте их. Не пытайтесь собрать всё самостоятельно.
Не используйте RSA.
Избегать: систем, разработанных после 2015 года с использованием RSA, RSA-PKCS1v15, RSA, ElGamal, я не знаю, ранцев Меркла — Хеллмана? Просто избегайте RSA.
Асимметричные подписи
Percival, 2009: используйте RSASSA-PSS с SHA256, затем MGF1+SHA256.
Ptacek, 2015: используйте NaCl, Ed25519 или RFC6979.
Latacora, 2018: используйте NaCl или Ed25519.
Нужно в случае, если: вы разрабатываете новую криптовалюту. Или систему подписи для Ruby Gems или картинок Vagrant, или схему DRM, где нужно в автономном режиме тем же секретным ключом проверять подлинность серии файлов, поступающих в случайные моменты времени. Или вы создаёте транспорт для зашифрованных сообщений.
Утверждения из предыдущего ответа полностью подходят и для этого пункта.
За последние 10 лет два самых главных случаев использования асимметричных подписей — это криптовалюты и протоколы согласования ключа совершенной прямой секретности, как и в ECDHE-TLS. Доминирующие алгоритмы для этих случаев основаны на эллиптических кривых. Опасайтесь новых систем, использующих подписи RSA.
В последние несколько лет произошел существенный переход от обычных подписей DSA к устойчивым против злоупотреблений «детерминированным» схемам подписей, лучшими примерами которых являются EdDSA и RFC6979. Можете думать о них как о «защищённых от пользователя» ответах на уязвимость Playstation 3 ECDSA, где повторное использование случайного числа выдавало секретные ключи. Предпочитайте детерминированные подписи любым другим схемам подписей.
Ed25519 из настроек по умолчанию NaCl/libsodium сейчас самая популярная схема подписи открытого ключа за пределами Bitcoin. Она устойчива против злоупотреблений и тщательно спроектирована в остальных отношениях. Её тоже не следует самостоятельно проектировать; возьмите реализацию из NaCl.
Избегать: RSA-PKCS1v15, RSA, ECDSA, DSA; действительно, особенно следует избегать обычных DSA и ECDSA.
Диффи — Хеллман
Percival, 2009: работайте над 2048-битной группой #14 с генератором 2.
Ptacek, 2015: вероятно, всё ещё DH-2048 или NaCl.
Latacora, 2018: вероятно, ничего. Или используйте Curve25519.
Нужно в случае, если: вы разрабатываете зашифрованный транспорт или систему обмена сообщениями, которую когда-нибудь будут использовать незнакомые люди, и поэтому статические ключи AES не подходят.
Версия этого документа 2015 года запутала всех до чёртиков.
Часть проблемы в том, что наши «правильные ответы» — ответ на «правильные ответы» Колина Персиваля, а он включил ответ про Диффи — Хеллмана, как будто это обычный протокол для разработчиков. На самом деле, разработчики просто не должны внештатно создавать собственные зашифрованные транспорты. Чтобы получить представление о сложности этой проблемы, прочитайте документацию по Noise Protocol Framework. Если вы выполняете обмен ключами по протоколу DH, то вероятно хотите формировать общие ключи аутентификации (AKE), которые противостоят атакам с компрометацией ключей путём маскировки под законного пользователя (key compromise impersonation, KCI). Так что примитив для DH — не единственная серьёзная проблема безопасности.
Но неважно.
Всё остаётся по-прежнему: если вы можете просто использовать NaCl, используйте NaCl. Вам даже не нужно заботиться о том, что делает NaCl. В этом смысл NaCl.
В противном случае используйте Curve25519. Есть библиотеки практически для каждого языка. В 2015 году мы беспокоились о том, чтобы поощрять людей писать собственные библиотеки Curve25519, размышляя о реализациях Javascript bignum. Но в реальности суть Curve25519 отчасти заключается в том, что вся кривая тщательно выбрана для минимизации ошибок реализации. Не пишите свою собственную! В самом деле, просто используйте Curve25519.
Не внедряйте ECDH с кривыми NIST, где вам придётся тщательно проверять точки эллиптических кривых перед их использованием для вычислений, чтобы избежать утечки секретов. Эта атака очень проста в реализации: проще, чем padding oracle на CBC, и гораздо разрушительнее.
Документ 2015 года содержал пункт об предпочтении DH-1024 по сравнению с поверхностными библиотекам кривых. И знаете что? Аргумент по-прежнему актуален. Он актуален и глуп. Выбор «DH-1024 или поверхностная библиотека кривых» можно сравнить с выбором «Использовать Blowfish или IDEA». Такого выбора не должно быть. Используйте Curve25519.
Избегать: обычного DH, SRP, J-PAKE, рукопожатий и согласования, сложных схем согласования ключа, использующих только блочные шифры, srand(time()).*
.
Безопасность веб-сайта
Percival, 2009: используйте OpenSSL.
Ptacek, 2015: остаётся OpenSSL или BoringSSL, если возможно. Или просто используйте AWS ELB.
Latacora, 2018: используйте AWS ALB/ELB или OpenSSL с LetsEncrypt.
Нужно в случае, если: у вас есть сайт.
Если можете заплатить AWS, чтобы не заботиться об этой проблеме, то рекомендуем сделать это.
В противном случае был тёмный период между 2010 и 2016 годами, когда OpenSSL, возможно, не был правильным ответом, но это время прошло. OpenSSL стал лучше, и, что ещё важнее, OpenSSL готов сообщать о найденных уязвимостях и реагировать на них.
Использовать что-то кроме OpenSSL — значит резко усложнить вашу систему ради небольшой, нулевой или даже отрицательной выгоды в безопасности. Так что будьте проще.
Говоря о простом: LetsEncrypt — бесплатный и автоматизированный сервис. Настройте задание хрона для регулярного забора сертификатов и тестирования.
Избегать: непривычных TLS библиотек PolarSSL, GnuTLS и MatrixSSL.
Безопасность клиент-серверных приложений
Percival, 2009: распространяйте открытый RSA-ключ сервера с клиентским кодом и не используйте SSL.
Ptacek, 2015: используйте OpenSSL или BoringSSL, если можете. Или просто используйте AWS ELB.
Latacora, 2018: используйте AWS ALB/ELB или OpenSSL с LetsEncrypt.
Нужно в случае, если: предыдущие рекомендации по криптографии с открытым ключом были актуальны для вас.
Кажется немного сумасшедшим рекомендовать TLS, учитывая последнюю историю:
- Атака Logjam DH на сессионные ключи
- Атака FREAK на RSA_EXPORT
- Атака POODLE на CBC с оракулом
- Фиаско RC4
- Атака CRIME на алгоритм сжатия
- Атака по времени Lucky13 типа padding oracle на CBC-шифры
- Атака BEAST на вектор инициализации CBC-шифра
- Heartbleed
- Пересогласование TLS
- Тройные рукопожатия
- Скомпрометированные центры сертификации
- Атака DROWN
Вот почему всё равно следует использовать TLS для собственного транспортного протокола:
- В собственных протоколах вам не придётся зависеть от сторонних центров сертификации. Даже можно вообще не использовать центры сертификации (хотя несложно установить свой собственный); вы можете просто использовать белый список самоподписанных сертификатов — примерно так SSH делает по умолчанию.
- Поскольку вы создаёте собственный протокол, то можете использовать наилучшие наборы шифров TLS: TLS 1.2+, Curve25519 и ChaPoly. Это защищает от большинства атак на TLS. Причина, по которой все этого не делают, заключается в необходимости обратной совместимости, но в собственном протоколе она не нужна.
- Многие из перечисленных атак работают только против браузеров, потому что жертва должна принять и выполнить контролируемый злоумышленником Javascript, чтобы генерировать повторяющиеся известные/подобранные тексты.
Избегать: проектировать собственный транспортный протокол шифрования, что является действительно сложной инженерной проблемой; использовать TLS в конфигурации по умолчанию (например, с curl
); использовать curl
, IPSEC.
Онлайновые бэкапы
Percival, 2009: используйте Tarsnap.
Ptacek, 2015: используйте Tarsnap.
Latacora, 2018: храните зашифрованные PMAC-SIV-файлы arc в S3 и сохраняйте отпечатки бэкапов в ERC20-совместимый блокчейн.
Нужно в случае, если: вы беспокоитесь о бэкапах.
Просто шутка. По-прежнему используйте Tarsnap.