Базовая целостность и аутентичность: MAC и подписи
В первых статьях курса мы:
зафиксировали, что в недоверенной сети нарушитель может быть активным (не только читать, но и менять сообщения)
разобрали примитивы (хэши, MAC, шифрование) и увидели, что одно лишь шифрование не гарантирует целостностьТеперь соберем это в практическую картину: как именно достигаются целостность и аутентичность на уровне сообщений, и чем отличаются два ключевых механизма: MAC и цифровые подписи.
Что именно мы хотим получить от механизма целостности
В модели угроз (из первой статьи) для активного нарушителя нам обычно нужны свойства:
Целостность: получатель должен обнаружить любое изменение сообщения.
Аутентичность: получатель должен убедиться, что сообщение сформировал ожидаемый субъект.
Свежесть: защита от replay (повторной отправки старого корректного сообщения) часто идет рядом с аутентичностью.Важно: целостность и аутентичность почти всегда проверяются на уровне конкретного сообщения. Поэтому механизм должен быть привязан к точному набору байт, которые считаются «тем самым сообщением».
MAC: аутентичность при общем секрете
Идея MAC
MAC (Message Authentication Code) — это значение (часто говорят тег), которое вычисляется по сообщению и секретному ключу, известному обеим сторонам.
В виде абстрактной схемы это выглядит так:
вычисление тега:
проверка: Пояснение обозначений:
— сообщение (байты, которые вы хотите защитить)
— общий секретный ключ MAC
— тег (короткое значение, отправляемое вместе с сообщением)Если атакующий изменит или , проверка должна отклонить сообщение с очень высокой вероятностью.
Что дает MAC
MAC обычно дает два сервиса сразу (в модели «общий секрет»):
целостность (модификации обнаруживаются)
аутентичность (тег мог вычислить только обладатель ключа)Но есть важное ограничение: если один и тот же ключ знают несколько субъектов, то любой из них может сгенерировать корректный тег, и доказать третьей стороне «кто именно подписал» невозможно. Поэтому MAC обычно не дает неотказуемость.
Стандартные конструкции MAC
На практике почти всегда используются стандартизованные MAC:
HMAC (на базе хэш-функции), стандарт: RFC 2104: HMAC
CMAC (на базе блочного шифра), стандарт: NIST SP 800-38B: Recommendation for Block Cipher Modes of Operation: The CMAC Mode for AuthenticationСвязь с предыдущей статьей: HMAC использует хэш как примитив, но превращает его в конструкцию, устойчивую к типовым проблемам «самодельных» схем.
Что обязательно продумать при использовании MAC
#### Защита от replay
MAC подтверждает, что сообщение аутентично, но не говорит, что оно свежее. Если протокол допускает повтор старого сообщения, атакующий может перехватить корректный пакет и позже повторить его.
Типовые решения:
добавлять в счетчик (монотонный sequence number)
добавлять nonce (одноразовое значение) и хранить «уже использованные» на стороне сервера
использовать метки времени и окна допустимого времени (если можно доверять времени и есть допуски)Главное правило: элемент свежести должен входить в защищаемое сообщение , то есть быть покрыт MAC.
#### Разделение ключей по назначению
Частая инженерная практика:
разные ключи для разных направлений (клиент → сервер и сервер → клиент)
разные ключи для разных типов сообщенийЭто уменьшает радиус поражения при ошибках протокола и упрощает анализ.
#### Сравнение тегов без утечек
Проверка тега должна быть реализована как сравнение с постоянным временем выполнения (constant-time compare), иначе возможны атаки по времени, особенно в сетевых сервисах.
Цифровые подписи: аутентичность без общего секрета
Идея цифровой подписи
Цифровая подпись использует пару ключей:
закрытый ключ хранится у подписанта
открытый ключ распространяется всем проверяющимАбстрактно:
подпись:
проверка: Пояснение обозначений:
— сообщение
— закрытый ключ (секрет подписанта)
— открытый ключ (публичный)
— подписьЕсли проверка проходит, это означает: «подпись мог создать тот, у кого был соответствующий закрытый ключ».
Что дают подписи
Цифровая подпись обычно обеспечивает:
целостность подписанного сообщения
аутентичность относительно владельца закрытого ключа
часто — основу для неотказуемости, но только при корректной инфраструктуре (идентификация владельца ключа, политика хранения ключей, аудит, метки времени и т.д.)Важно: подпись сама по себе не решает проблему «кому принадлежит открытый ключ». Это уже область инфраструктуры открытых ключей (сертификаты, доверие, привязка ключа к имени), к которой курс подойдет в следующих темах.
Алгоритмы и стандарты
Распространенные варианты:
RSA-PSS и ECDSA: стандарт FIPS 186-5: Digital Signature Standard (DSS)
Ed25519: стандарт RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)Практическая деталь: многие схемы подписи устроены как «подпиши хэш сообщения», поэтому для больших сообщений обычно сначала считают хэш, а затем подписывают результат.
Подпись и replay
Подпись, как и MAC, не делает сообщение свежим автоматически. Если злоумышленник перехватил подписанное сообщение, он может повторить его позднее.
Защита такая же по идее, как и с MAC: включать в nonce, счетчик, идентификатор операции, срок действия, контекст протокола — и подписывать вместе с полезной нагрузкой.
MAC и подписи: ключевые различия
!Сравнение моделей доверия для MAC и цифровой подписи
Сравнение в инженерных терминах:
| Критерий | MAC | Цифровая подпись |
|---|---|---|
| Ключи | один общий секрет у сторон | пара (секрет) и (публичный) |
| Кто может проверять | только тот, у кого есть | любой, у кого есть |
| Кто может создавать | любой, у кого есть | только владелец |
| Неотказуемость | обычно нет | возможно, но зависит от инфраструктуры |
| Производительность | обычно быстрее | обычно дороже по CPU |
| Типичный сценарий | внутренние сервисы, API, протоколы с общим секретом | обновления ПО, документы, распределенные системы, где проверяющих много |
Простое правило выбора:
если у вас две стороны и они могут безопасно хранить общий секрет, MAC часто проще и быстрее
если проверяющих много, нужен публичный аудит или нет общего секрета, обычно нужны подписиКомпозиция с конфиденциальностью: где место MAC и подписи
Из предыдущей статьи: шифрование без аутентификации не гарантирует целостность. Поэтому при активном нарушителе безопасные варианты обычно такие:
AEAD (например, AES-GCM или ChaCha20-Poly1305): единая схема «шифрование + аутентификация»
либо комбинация шифрования и MAC, но с правильным порядкомРаспространенная рекомендация в протоколах: Encrypt-then-MAC — сначала шифровать, затем считать MAC по шифртексту (и по нужным незашифрованным полям, если они должны быть защищены). Это снижает риск классов атак, связанных с обработкой некорректного шифртекста.
На практике чаще всего выбирают AEAD, потому что:
меньше шансов ошибиться в композиции
проще интерфейс использованияЧастые ошибки и как их избежать
Ошибка: «SHA-256 от сообщения рядом положим — будет целостность»
Это работает только если эталонный хэш получен из доверенного источника. В недоверенной сети атакующий подменит и сообщение, и хэш.
Правильный подход:
либо MAC (если есть общий секрет)
либо цифровая подпись (если нужна публичная проверка)Ошибка: не аутентифицировать контекст
Если MAC/подпись считается только по «данным», но не покрывает важные поля (например, user_id, amount, currency, destination, версию протокола), атакующий может переставлять поля, менять смысл или переносить тег между сообщениями.
Практика: включать в защищаемую строку/структуру все поля, которые определяют смысл операции, плюс явный контекст (например, строку "payment_v1").
Ошибка: подпись или MAC без защиты от replay
Если операция опасна при повторе (платеж, смена пароля, выдача токена), нужно встроить свежесть:
счетчик
nonce
срок действияИ все это должно входить в подписываемые/аутентифицируемые данные.
Ошибка: один ключ «на все»
Один и тот же ключ для разных задач усложняет анализ и увеличивает последствия утечки.
Практика: разделять ключи по назначению и по направлению, а для протоколов использовать KDF и отдельные ключи для шифрования и аутентификации.
Два минимальных инженерных шаблона
Запрос к API с HMAC
Идея: клиент и сервер разделяют секрет K. Клиент отправляет:
параметры запроса
timestamp или nonce
тег t = HMAC(K, canonical_request)Сервер:
проверяет свежесть timestamp/nonce
проверяет HMACКлючевой момент: должен быть однозначный канонический вид сообщения, чтобы обе стороны подписывали одни и те же байты.
Подписанное обновление ПО
Идея: производитель хранит sk в защищенной среде, клиенты вшивают или доверяют pk.
производитель публикует файл и подпись
клиент скачивает и проверяет подпись по pkЭто масштабируется, потому что проверяющим не нужен общий секрет и они не могут подделывать подписи.
Итоги
MAC дает целостность и аутентичность при наличии общего секрета; обычно быстрее и проще, но не дает публичной проверяемости и неотказуемости.
Цифровая подпись дает аутентичность без общего секрета и позволяет любому проверять сообщение по открытому ключу; часто используется как основа для неотказуемости.
И MAC, и подписи требуют проектирования свежести (защита от replay) и строгой привязки к контексту протокола.
Для сочетания конфиденциальности и целостности в сетевых протоколах чаще всего выбирают AEAD, чтобы избежать ошибок композиции.