Кратко

  • В актуальном RFC 9846 сообщение KeyUpdate продвигает секрет прикладного трафика только одного отправителя. Сам переход защищён старым ключом; последующие записи используют новое поколение, а пир обновляет соответствующую цепочку приёма.
  • update_requested обычно требует встречного обновления, но не отдаёт удалённой стороне управление соединением. Направления независимы, пересекающиеся запросы могут продвинуть обе цепочки дважды, молчаливые запросы объединяются, а лимиты поколения остаются локальными.
  • Надёжная запись различает планирование, фактическую отправку, принятие перехода и успешные данные нового поколения. Даже все четыре события не подтверждают удаление старого секрета, повторную аутентификацию или разрешение прикладного действия.

Переход, который опирается на прошлое

Представим долго живущее TLS-соединение для потока рыночных данных. Клиент решил сменить свой ключ передачи и попросил сервер сделать то же самое. На уровне интерфейса это похоже на одну команду, но в протоколе нет единой эпохи, которую удалённая сторона может перевести щелчком.

Клиент шифрует KeyUpdate текущим ключом. После отправки сообщения все следующие записи от клиента переходят на очередной секрет. Сервер сначала аутентифицирует староключевой мост, а затем продвигает цепочку приёма. Если он отвечает, его KeyUpdate тоже отправляется под прежним серверным ключом; лишь дальнейший трафик сервер-клиент получает новое поколение.

У двух направлений разные секреты, номера записей и моменты исполнения. Поэтому единый показатель «версия ключа TLS» теряет смысл именно тогда, когда нужно объяснить задержанную запись, встречный запрос или рассинхронизацию с аппаратным offload.

Действующая спецификация — RFC 9846

В 2026 году RFC 9846 заменил RFC 8446, сохранив совместимость TLS 1.3 на проводе. KeyUpdate по-прежнему имеет тип handshake 24 и только два допустимых значения: update_not_requested(0) и update_requested(1).

Сообщение до Finished требует завершения с unexpected_message, неизвестное значение — с illegal_parameter. KeyUpdate должно совпасть с границей записи перед сменой ключа. Приёмник обязан получить и аутентифицировать переход под старым ключом до данных следующего поколения; иначе пропуск протокольного решения создаёт возможность усечения.

Следующий секрет получают из текущего направленного секрета через HKDF-Expand-Label с меткой traffic upd, а затем выводят ключ и IV. Для отправителя задан предел эпохи 2^48-1. Приёмник не должен навязывать этот предел другому отправителю: будущая спецификация может изменить его локальное правило.

Обязанность отвечать имеет предел

При нулевом значении отправитель объявляет лишь о своей смене. При единице получатель обычно должен послать KeyUpdate без нового запроса до следующей записи Application Data. Это настоящая обязанность протокола, но не право пира распоряжаться ресурсами другой машины.

Нельзя создавать очередной запрошенный переход, пока от пира не пришёл последующий KeyUpdate. Несколько запросов, полученных в период его молчания, допускается удовлетворить одним обновлением. Если оба конца независимо отправили запросы и сообщения пересеклись, оба всё равно отвечают — каждое направление может продвинуться на два поколения.

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

Новый шифротекст не видит старую память

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

Запись нового поколения не способна проверить удалённый heap, слот аппаратного модуля, таблицу ядра, дамп сбоя или резервную копию. Ответ KeyUpdate означает совместимость цепочек, но не является аттестацией уничтожения. Доказательство удаления должно принадлежать отдельному локальному контуру управления памятью.

Не обновляется и личность. KeyUpdate не запрашивает новый сертификат сервера, не повторяет проверку имени, не меняет аутентифицированного клиента и не разрешает команду приложения. Свежий ключ может столь же надёжно защищать действие, которого система не должна была позволять.

Реализации разделяют вызов и провод

В OpenSSL SSL_key_update() допустима после исходного handshake и планирует обновление. До сети оно доходит при следующем I/O либо при явном продвижении handshake. Приложение должно согласовать незавершённые записи, поэтому успешный возврат API ещё не означает отправку.

GnuTLS делает выбор направления заметным: обычный вызов обновляет локальную передачу, а GNUTLS_KU_PEER дополнительно просит вторую сторону. Операция может возвращать неблокирующие состояния, как запись данных. Документация отдельно описывает rekey и повторную аутентификацию.

rustls предоставляет refresh_traffic_keys() и в штатном режиме следит за пределами конфиденциальности набора шифров. При выносе защиты записей в kernel-интерфейс приложение принимает ответственность за приблизительный подсчёт, обновление и аварийное завершение. Место вычисления меняется, владелец решения — нет.

TLS, DTLS и QUIC оставляют разные следы

QUIC применяет TLS 1.3 для handshake, но запрещает сообщения TLS KeyUpdate. QUIC версии 1 обновляет защиту пакетов с помощью бита Key Phase, последовательности подтверждений и вывода quic ku. Счётчик TLS KeyUpdate на исправном QUIC-соединении будет пуст.

DTLS 1.3 сохраняет KeyUpdate в среде потерь и перестановок. Он использует эпохи и подтверждения, а старый материал приёма может временно храниться для опоздавших датаграмм. Ответ способен пересечься с запросом и поэтому сам по себе не подтверждает именно его.

Общее название «TLS rekey» удобно для отчёта, но разрушает доказательство. Потоковый TLS требует упорядоченного староключевого моста, DTLS — движения эпохи с подтверждением, QUIC — фазы пакетного ключа.

Журнал без копирования секретов

Защитимый журнал хранит стабильную ссылку на соединение, роль, транспорт, версию, направление, старое и новое поколение. Он указывает инициатора — политику, предел библиотеки, оператора или пира —, значение запроса и незавершённость, принятие старого моста, границу записи, первые успешные прикладные данные, объединение и пересечение запросов, решение ограничителя и конечный alert.

Четыре отметки должны жить раздельно: запланировано, отправлено, принято, проверено данными. Доказательство стирания относится к самостоятельной локальной записи assurance. Сетевой дамп недостаточен, поскольку TLS 1.3 шифрует KeyUpdate; в контролируемом тесте переход можно связать с callbacks и счётчиками, не вынося ключевой материал в производственную телеметрию.

Источники