Кратко
- RFC 3218 рассматривал текст ошибки, характер ответа и время обработки как криптографические выходы. Если неверный блок RSAES-PKCS1-v1_5 можно отличить от правильного по форме блока с неверным ключом содержимого, эту разницу можно многократно использовать в адаптивной атаке.
- Random filling заменял неудачное развёртывание новым случайным CEK ожидаемой длины и продолжал расшифрование и проверку целостности. Подставной ключ намеренно был неправильным: он переносил ранний отказ на обычный путь отказа из-за неверного ключа.
Злоумышленнику не требовалось видеть открытый текст. Достаточно было узнать, имеет ли скрытый открытый текст ожидаемую форму.
В 1998 году Daniel Bleichenbacher показал, что одного такого бита хватает для адаптивной атаки с выбранным шифртекстом на PKCS #1 v1.5. Атакующий перехватывал RSA-шифртекст, математически преобразовывал его, отправлял владельцу закрытого ключа и по поведению получателя выяснял, соответствует ли расшифрованный блок формату. Каждый ответ сужал числовой интервал, в котором мог находиться секрет. Закрытый ключ не покидал систему, но последовательность решений системы выполняла часть расшифрования для внешнего наблюдателя.
RFC 3218 перенёс эту угрозу в Cryptographic Message Syntax. Документ вышел в январе 2002 года со статусом Informational. Он не создавал новый формат и не объявлял все применения RSA одинаковыми. Он решал переходную задачу: развёрнутые системы CMS уже переносили симметричный ключ содержимого через RSA PKCS #1 v1.5, и немедленно заменить этот формат без потери совместимости было невозможно.
Блок v1.5 имел строгую грамматику: 00 02, не менее восьми случайных ненулевых октетов, разделитель 00, затем переносимое значение. В CMS последним значением был content-encryption key, CEK. Операция с закрытым ключом RSA могла завершиться и выдать байты, которые всё равно не образовывали допустимый транспортный блок.
Здесь существовало несколько разных фактов. Завершилась ли операция RSA? Допустим ли формат PKCS #1? Соответствуют ли алгоритм и длина CEK ожиданиям? Это тот же ключ, который использовал отправитель? Выдал ли расшифровщик содержимого байты? Приняли ли padding, MAC, подпись и приложение результат? Внутри системе нужны эти различия. Снаружи они не должны становиться интерфейсом запросов.
Название Million Message Attack описывало эксплуатационный масштаб. Имея перехваченный шифртекст C, атакующий выбирал множитель S и отправлял C' = C * S^e mod n. RFC 3218 оценивал, что примерно одно преобразование из 2^16 даст открытый текст, начинающийся с 00 02, а полный процесс в рассмотренных условиях CMS может потребовать порядка 2^20 сообщений и ответов.
«Миллион» не был точным числом для каждого ключа и сервера. Он показывал, как автоматизация меняет стоимость атаки. Миллион обращений к человеку заметен и дорог. Почтовый агент, шлюз или другой автоматический получатель может расшифровывать, классифицировать и отвечать без ручного просмотра. Злоумышленник приносит трафик, получатель обеспечивает повторяемость.
После запроса блок PKCS #1 мог оказаться испорченным. Он мог иметь верную форму, но содержать ложный CEK. Ложный CEK мог привести к ошибке целостности. Без аутентифицированной целостности случайный открытый текст иногда случайно заканчивался правдоподобным CBC-padding. Получить настоящий CEK случайной трансформацией было крайне маловероятно.
Атаке не требовалось различать все результаты. Нужно было отделить первый — ошибку формата — от более поздних отказов при правильной форме и неправильном ключе. Разный текст ошибки давал бит. Ответ вместо молчания, разрыв соединения, возврат письма, уведомление о подписи или воспроизводимая задержка давали тот же эффект.
Главная мера RFC 3218 называлась random filling. Если декодирование PKCS #1 обнаруживало неправильный формат, получатель не прекращал обработку. Он создавал криптографически случайный CEK длины, требуемой алгоритмом содержимого, и действовал так, словно RSA-развёртывание вернуло это значение.
Получатель пытался расшифровать содержимое вымышленным ключом, выполнял обычные проверки padding, MAC, подписи и приложения. Случайный CEK почти наверняка приводил к более позднему штатному отказу. Видимая ошибка и время до неё должны были напоминать путь корректно закодированного блока с просто неверным CEK.
Поэтому случайный CEK не был ключом восстановления. Он не воссоздавал секрет отправителя, не спасал содержимое и не разрешал сообщение. Это было одноразовое состояние, позволяющее дойти до обычной точки отказа и не раскрыть более раннюю причину. Его функциональная правильность состояла в непредсказуемости и почти гарантированной неправильности.
Фиксированный резервный CEK разрушил бы защиту. Константа удобна для повторяемых тестов и экономит вызов генератора при ошибке. Но знающий её атакующий может зашифровать содержимое CMS этим ключом, присоединить намеренно испорченный RSA-транспорт и отправить пакет. Если получатель выберет резервную ветвь, содержимое успешно пройдёт; иначе нет. Механизм сокрытия создаст более ясный оракул.
Подставное значение должно быть новым, криптографически непредсказуемым и иметь правильную длину при каждом использовании. Повторное применение придало бы скрываемой ветви устойчивую идентичность, распознаваемую специально подготовленным содержимым.
Момент генерации случайности тоже мог выдавать ветвь. Если генератор медленный и вызывается только после ошибки, задержка становится меткой. RFC 3218 предлагал создавать случайного кандидата для каждого сообщения и отбрасывать его после успешного развёртывания. Тогда оба пути несут сходную стоимость.
Это не доказывало постоянное время всей программы. Доступ к памяти, парсер, журналы, очереди, сеть и действия приложения могли различаться. Рекомендация не позволяла принять одинаковую строку ошибки за безопасность при явно разном вычислительном пути.
Длина CEK создавала ещё одну границу. Универсальная библиотека RSA могла знать, что блок синтаксически допустим, но не знать, нужны ли приложению 8, 16, 24 или 32 байта. Если она возвращала значение, а слой CMS отвергал неверную длину особым исключением, оракул просто перемещался вверх.
Слой, знающий алгоритм содержимого, тоже должен был заменять результаты неверной длины случайным CEK. Свойство безопасности пересекало границы программных компонентов. Нижняя криптографическая примитива не могла самостоятельно обеспечить защиту, если ей не хватало контекста.
Более строгие проверки повышали цену атаки: проверить все октеты padding, длину CEK и, где нужно, биты чётности алгоритмов семейства DES. Каждое условие уменьшало вероятность принятия случайной трансформации.
Но редкий оракул оставался оракулом. Если ответ сообщал, какое условие не выполнено, атакующий мог продолжить, потратив больше запросов на тот же тип информации.
Неаутентифицированный CBC показывал и слабость фразы «расшифрование вернуло данные». Случайные байты могли закончиться похоже на padding. Если реализация читала только последний байт как длину усечения, RFC 3218 оценивал шанс видимой правильности примерно как 1/32. Проверка всех требуемых байтов снижала его примерно до 1/255.
Совпадение не придавало случайному содержимому смысла. MAC или подпись создавали более надёжную позднюю точку отказа. Но они не разрешали отдельно раскрыть начальное решение PKCS #1; защита зависела от слияния ранней ветви с последующими ошибками.
OAEP предлагал более чистое криптографическое направление. PKCS #1 v2.0 определил RSAES-OAEP, и RFC 3218 указывал, что обсуждаемая атака к нему не относится. Однако OAEP был несовместим с v1.5 на проводе. Отправители, получатели, сертификаты, идентификаторы алгоритмов и установленное ПО CMS должны были согласовать переход.
Название лучшей примитивы не отключало старую экосистему. Random filling был мерой сосуществования: пока устаревший формат принимал трафик, следовало ограничивать сведения его ошибочного пути.
TLS уже сталкивался с родственной угрозой для RSA-зашифрованного premaster secret. Спецификации заставляли сервер продолжать со случайным значением, а не раскрывать ошибку формата или версии. Идея была общей, но последующие следы оставались протокольными. TLS-handshake, CMS-сообщение и почтовый агент имели разные автоматы состояний и ответы.
Общая дисциплина находилась выше RSA: внутренний парсер не должен отвечать на вопрос, на который внешний протокол не может безопасно ответить. Протокол определяет, какая работа продолжается, какой итоговый отказ показывается и какие побочные каналы выравниваются.
RFC 3218 не утверждал, что random filling аутентифицирует отправителя, убирает все временные утечки, чинит скомпрометированный закрытый ключ или доказывает безопасность реализации. Он не приводил статистики внедрения. Его вклад был уже и долговечнее: если внутреннюю разницу можно запрашивать снова и снова, обработка ошибки становится частью криптосистемы.
Обзор для участников
Подробный контекст профиля
Войдите с подходящим уровнем подписки, чтобы открыть полный обзор и примечания к источникам.
Только для Стратегического сообщества
Стратегическое сообщество
Открыто всем читателям. Вступите и войдите, чтобы открыть обзоры профилей.
Вступить в Стратегическое сообществоТолько для Альянса лидеров
Альянс лидеров
Для проверенных владельцев IP-активов и руководителей. Войдите, чтобы открыть обзоры Альянса.
Вступить в Альянс лидеров
