Апокриф 06

AEAD и режимы: сломанный GCM

AEAD и режимы: сломанный GCM

Аутентифицированное шифрование (AEAD) обещает сразу две вещи: данные скрыты и данные нельзя незаметно изменить. Это не «шифрование плюс MAC по вкусу», а конструкция, где обе операции связаны и проверяются вместе. GCM — самый распространённый AEAD в мире: он в TLS 1.2 и 1.3, в IPsec, в дисковом шифровании и в библиотеках, которыми пользуются все.

Именно поэтому у GCM есть одно требование, нарушение которого обнуляет обещание: nonce обязан быть уникальным для каждого сообщения при данном ключе. Не «случайным», не «секретным» — уникальным. Если nonce повторился, повторяется ключевой поток (конфиденциальность ломается так же, как в поточном шифре), а разность тегов двух сообщений превращается в уравнение на ключ аутентификации H, после чего подделка тега становится арифметикой.

Тема показывает конструкцию изнутри: умножение в GF(2^128), GHASH, сборку тега. Затем — три атаки: восстановление второго сообщения при повторе nonce, восстановление H по двум известным открытым текстам и подделку тега для изменённого сообщения. Заканчивается разбор тем, как проектировать протокол, чтобы повтор nonce был невозможен или безвреден: SIV, детерминированные nonce, разделение ключей.

Что такое AEAD

Интерфейс и гарантии

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

Гарантия конфиденциальности: без ключа шифртекст неотличим от случайного. Гарантия целостности: любое изменение шифртекста, тега, nonce или AAD приводит к отказу проверки с вероятностью, близкой к единице. Порядок операций при расшифровании строгий: сначала проверка тега, только потом расшифрование и разбор полей. Если сделать наоборот, получится оракул — ровно тот, что разобран в апокрифе 5.

Почему «шифрование плюс MAC» — не то же самое

Собрать AEAD из двух примитивов можно, но надо угадать порядок и охват. Encrypt-then-MAC поверх CBC работает, MAC-then-encrypt оставляет оракул дополнения. GCM решает это конструктивно: один ключ, одна операция, тег охватывает всё. Плата — жёсткие требования к nonce и цена умножения в GF(2^128) на некоторых платформах 7.

Конструкция GCM

Ключ аутентификации и GHASH

Из ключа шифрования K выводится ключ аутентификации H = E_K(0^128). GHASH — полиномиальный хеш: входные блоки складываются и умножаются на H в поле GF(2^128) по модулю x^128 + x^7 + x^2 + x + 1 1. Схема: Y_0 = 0, Y_i = (Y_{i-1} ⊕ X_i) · H.

Конструкция описана Макгрю и Виегой 2. Поле определено над GF(2), поэтому умножение — это сдвиги и XOR, без переносов; аппаратно оно ускоряется инструкцией PCLMULQDQ. Свойство, которое нас интересует: GHASH линеен по входу при фиксированном H и полиномиален по H при фиксированном входе. Обе линейности и эксплуатируются.

Шифрование и тег

Шифрование — CTR с начальным счётчиком J_0 = nonce || 0x00000001 для 96-битного nonce; в TLS 1.2 эта же конструкция описана в RFC 5288 3. Тег: T = GHASH(H, AAD, C) ⊕ E_K(J_0). Расшифрование повторяет вычисления и сравнивает тег. Структура на рисунке 1.

Конструкция GCM
Рисунок 1. GCM: CTR даёт шифртекст, GHASH — полиномиальный хеш по AAD и шифртексту, E_K(J0) маскирует результат

Важно, что E_K(J_0) одинаково для всех сообщений с одним nonce. Это и есть точка, из которой растёт атака при повторе: маска сокращается при вычитании тегов.

Повтор nonce: две атаки сразу

Конфиденциальность

Если два сообщения зашифрованы с одним nonce, их потоки совпадают: C_1 ⊕ C_2 = P_1 ⊕ P_2. Зная один открытый текст, противник получает второй. Это в точности two-time pad из апокрифа 4, только внутри AEAD — и потому особенно обидно: разработчик выбрал «стойкий режим» и всё равно получил поточный шифр с повтором.

Целостность

Сокращение маски при повторе nonce
Рисунок 2. Один nonce — одна маска E_K(J0); при вычитании тегов она исчезает, и остаётся уравнение на H

Теги двух сообщений с одним nonce: T_1 ⊕ T_2 = GHASH(H, AAD_1, C_1) ⊕ GHASH(H, AAD_2, C_2), потому что E_K(J_0) сокращается. Правая часть — полином по H с коэффициентами, известными из шифртекстов; его степень равна числу блоков GHASH-входа, то есть включает и блок длины. Уравнение решается не как система линейных уравнений, а как задача о корнях полинома над GF(2^128): стандартный приём атаки — построить два таких полинома по двум парам сообщений и взять их наибольший общий делитель, который с высокой вероятностью равен H − h; стоимость полиномиальна по числу блоков 4.

Получив H, противник подделывает тег для любого сообщения: T' = T ⊕ GHASH(H, AAD, C) ⊕ GHASH(H, AAD, C'). Ключ шифрования при этом не нужен — нужен только один валидный тег и H.

Наглядный расчёт в упрощённой модели

В учебной модели, где GHASH определён как Y_i = (Y_{i-1} ⊕ C_i)·H без блока длины, для сообщения из одного блока и пустого AAD получается GHASH(H, C) = C · H, и разность тегов даёт (C_1 ⊕ C_2) · H = T_1 ⊕ T_2. Если C_1 ≠ C_2, то H = (T_1 ⊕ T_2) · (C_1 ⊕ C_2)^{-1} — одно деление в поле. Эта модель удобна для первого знакомства, но лабораторная работа использует полный GHASH с блоком длины: там после деления требуется ещё извлечь квадратный корень, а для много-блочных сообщений — решать полиномиальное уравнение. Смысл атаки тот же; отличается только объём арифметики.

В стандартном GCM (NIST SP 800-38D) GHASH получает на вход ещё и блок длины L = 0^64 ‖ len(C)_64, поэтому для одного блока шифртекста GHASH(H, C) = C·H^2 ⊕ L·H: степень повышается, и «одного деления» уже нет. Атака остаётся рабочей — меняется только техника решения уравнения на H, — но формула C·H верна лишь для оговорённой учебной модели и не должна переноситься на реальный GCM.

Подделка тега

Атака без ключа шифрования

Имея H и один валидный (C, T), противник меняет шифртекст на C' и пересчитывает тег по формуле выше. Сервер принимает сообщение: тег верный, шифртекст расшифровывается в желаемый текст. Целостность исчезла полностью, хотя AES не взломан и ключ не извлечён.

Почему это не «теоретическая» атака

В 2016 году группа исследователей просканировала Интернет и нашла тысячи TLS-серверов и библиотек, которые повторяли nonce в GCM из-за ошибок в генерации или из-за отката при перезапуске 6. Атака на nonce-reuse в GCM входит в стандартный арсенал; в учебных заданиях она воспроизводится за десятки строк кода.

Как проектировать правильно

Уникальность nonce

Nonce должен быть уникален для каждой пары «ключ, сообщение». Два рабочих способа: счётчик, который никогда не повторяется (и хранится надёжно), или случайные 96 бит с вероятностью коллизии, приемлемой для объёма сообщений. Второй способ требует оценки: при 2^32 сообщениях вероятность коллизии около 2^-33, что для большинства протоколов приемлемо, но для долгоживущих ключей — нет.

Ключ обязан меняться до исчерпания счётчика или до накопления слишком большого числа сообщений. В TLS 1.3 это зашито в дизайне: ключи обновляются, номера последовательностей не повторяются, а nonce выводится из ключа и счётчика 8.

SIV и детерминированное шифрование

Если nonce негде хранить (например, шифрование файлов), используют SIV: тег вычисляется первым как синтетический IV и подаётся в режим шифрования. Повтор nonce становится безвредным, потому что IV получается из самого сообщения; цена — невозможность параллельного шифрования и необходимость двух проходов 5.

Другой вариант — детерминированный nonce из счётчика с гарантией уникальности на уровне хранилища: база данных выдаёт монотонный номер, и он же служит nonce.

Разделение ключей и домены

Один ключ — одно назначение. Если один и тот же ключ используется и для GCM, и для чего-то ещё, требования к nonce складываются, и ошибка в одном месте ломает другое. Вывод ключей по назначению (HKDF с разными метками) стоит дёшево и снимает целый класс ошибок.

Итоги темы

  • AEAD связывает конфиденциальность и целостность в одной операции; порядок «сначала тег, потом текст» обязателен.
  • GCM: H = E_K(0^128), GHASH — полиномиальный хеш, тег маскируется E_K(J_0).
  • Повтор nonce ломает конфиденциальность (поток повторяется) и целостность (H восстанавливается).
  • В упрощённой учебной модели (без блока длины) с одним блоком сообщения H вычисляется одним делением в GF(2^128); в стандартном GCM уравнение на H полиномиально и решается через НОД полиномов.
  • Защита: уникальный nonce, счётчики, ротация ключей, SIV, разделение ключей по назначению.

Литература

  1. NIST. SP 800-38D: Recommendation for Block Cipher Modes of Operation — Galois/Counter Mode. 2007. — спецификация GCM и требования к nonce.
  2. McGrew D., Viega J. The Galois/Counter Mode of Operation (GCM). 2004. — исходное описание конструкции и доказательства.
  3. RFC 5288: AES Galois Counter Mode for TLS. 2008. — как GCM встроен в TLS 1.2.
  4. Joux A. Authentication Failures in NIST Version of GCM. 2006. — разбор последствий повтора nonce и слабостей аутентификации.
  5. Rogaway P., Shrimpton T. A Provable-Security Treatment of the Key-Wrap Problem. 2006. — основания SIV и детерминированного шифрования.
  6. Böck H., Zauner A., Devlin S., Somorovsky J., Jovanovic P. Nonce-Disrespecting Adversaries: Practical Forgery Attacks on GCM in TLS. 2016. — измерение реальных повторов nonce в Интернете.
  7. RFC 5116: An Interface and Algorithms for Authenticated Encryption. 2008. — общий интерфейс AEAD и требования к nonce.
  8. RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3. 2018. — обновление ключей и построение nonce в TLS 1.3.