awesome-everything EN
↑ Обратно к восхождению

Сети и протоколы

Рукопожатие за 1 RTT: key share и ECDHE

Суть Как key share в ClientHello, эфемерные ключи ECDHE и хеш транскрипта сворачивают двухшаговое рукопожатие TLS 1.2 в одно — и почему Perfect Forward Secrecy следует из этого автоматически.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 14 min

Браузер открывает TCP-соединение и немедленно отправляет ClientHello. Это единственное сообщение содержит и список шифров, и половину ключа шифрования — сервер может вычислить общий секрет прямо здесь и ответить зашифрованными данными за один проход. Именно так TLS 1.3 превращает два RTT в один.

Рукопожатие за 1 RTT: шаг за шагом

Шаг 1 — ClientHello. Клиент отправляет: список версий TLS (через расширение supported_versions), поддерживаемые наборы шифров, поддерживаемые именованные группы (кривые), поддерживаемые алгоритмы подписи и расширение key_share с как минимум одним публичным ключом ECDHE — обычно x25519.

Шаг 2 — ServerHello. Сервер выбирает набор шифров (например TLS_AES_128_GCM_SHA256), выбирает именованную группу из key_share клиента, генерирует собственную эфемерную пару ключей и отвечает своим публичным ключом. Теперь обе стороны знают публичные ключи друг друга и могут запустить ECDHE для вывода общего секрета.

Шаг 3 — Зашифрованное рукопожатие. Сервер немедленно выводит ключ трафика рукопожатия из общего секрета и отправляет EncryptedExtensions, Certificate, CertificateVerify и серверный Finished — все зашифрованные — в одном сетевом проходе.

Шаг 4 — Клиент завершает. Клиент выводит тот же ключ трафика, расшифровывает сообщения сервера, проверяет цепочку сертификатов, проверяет подпись CertificateVerify над транскриптом, проверяет HMAC серверного Finished, отправляет клиентский Finished и начинает передавать данные приложения.

Итого round-trip: один. ClientHello уходит, ServerHello + зашифрованное рукопожатие приходит, клиентский Finished + первые данные приложения уходят — всё в одном сетевом обмене.

Стоимость холодного рукопожатия TLS 1.3 на проводе
ClientHello
~512 байт
ServerHello
~150 байт
Certificate (цепочка ECDSA P-256)
1–3 КБ
CertificateVerify (ECDSA)
~70 байт
Server Finished
~50 байт
Client Finished
~50 байт
Итого RTT
1

ECDHE: обмен ключами за key share

Обе стороны договариваются о кривой (обычно x25519 для производительности или P-256 для FIPS). Каждая генерирует приватный скаляр (случайное 256-битное целое) и вычисляет публичную точку: public = private · G, где G — базовый генератор кривой. Антон отправляет свою публичную точку в key_share, Дима — свою в ответ. Каждый вычисляет общий секрет, умножая публичную точку другого на свой приватный скаляр:

  • Антон: shared = ant_private · dim_public
  • Дима: shared = dim_private · ant_public

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

Perfect Forward Secrecy (PFS)

Оба клиент и сервер используют эфемерные пары ключей, сгенерированные заново для каждого соединения и уничтожаемые после него. Если злоумышленник позже украдёт долгосрочный приватный ключ Димы с диска, прошлые сессии всё равно не расшифруются — они использовали эфемерные ключи, которых уже нет. Это и есть Perfect Forward Secrecy.

TLS 1.2 позволял RSA-транспорт ключей: клиент шифровал секрет сессии долгосрочным публичным ключом сервера. Кража приватного ключа означала расшифровку всех записанных прошлых сессий. TLS 1.3 требует эфемерный обмен ключами, делая PFS настройкой по умолчанию.

Проверка цепочки сертификатов

Получив Certificate, клиент видит цепочку: листовой сертификат для хоста, затем один или несколько промежуточных. Он обходит цепочку снизу вверх:

  1. Проверить, что листовой подписан промежуточным.
  2. Проверить, что промежуточный подписан корневым.
  3. Убедиться, что корень находится в локальном хранилище доверия.
  4. Проверить, что SAN (Subject Alternative Names) листового включают хост подключения.
  5. Проверить срок действия (notBefore <= now <= notAfter).
  6. Проверить отзыв (CRLite, stapled OCSP или политика короткоживущих сертификатов).

Если хоть один шаг провалился — соединение завершается с fatal alert (например unknown_ca).

Хеш транскрипта и Finished

Каждый байт, отправленный в ходе рукопожатия, поступает в накапливаемый SHA-256-дайджест — хеш транскрипта. Сообщение Finished — это HMAC(finished_key, transcript_hash). Если один бит на проводе был перевёрнут или подменён — HMAC не совпадёт и соединение прервётся. Именно так TLS 1.3 обнаруживает атаки понижения версии: транскрипт записывает первоначально предложенную клиентом версию, поэтому попытка middlebox’а принудить к TLS 1.2 сломает проверку Finished.

Проследи
1/5

Проследите успешное холодное рукопожатие TLS 1.3 от ClientHello до первого зашифрованного байта данных.

1
Step 1 of 5
Клиент отправляет ClientHello. Какие поля важнее всего?
2
Locked
Сервер выбирает набор шифров и именованную группу. Что он отправляет?
3
Locked
Какие сообщения рукопожатия отправляются зашифрованными под серверным ключом трафика?
4
Locked
Клиент проверяет и отвечает. Что отправляет клиент?
5
Locked
Итоговая стоимость в RTT?
Викторина

Почему TLS 1.3 требует эфемерный обмен ключами (ECDHE) и убирает RSA-транспорт ключей?

Викторина

Какую гарантию целостности даёт хеш транскрипта TLS 1.3?

Расставь шаги по порядку

Упорядочьте шаги проверки цепочки сертификатов:

  1. 1 Получить Certificate с листовым + промежуточными сертификатами
  2. 2 Убедиться, что SAN листового совпадает с именем хоста подключения
  3. 3 Обойти цепочку: проверить подпись каждого сертификата публичным ключом его издателя
  4. 4 Найти корневой в локальном хранилище доверия
  5. 5 Проверить срок действия (notBefore <= now <= notAfter)
  6. 6 Проверить статус отзыва (CRLite, stapled OCSP или политика короткоживущих сертификатов)
Почему это работает

RSA vs ECDSA сертификаты. Алгоритм подписи серверного сертификата не зависит от ECDHE. Сертификаты ECDSA P-256 примерно в 5 раз быстрее верифицировать, чем RSA-2048, и подписи в четыре раза меньше. Edge-сервер, обрабатывающий миллион рукопожатий в секунду, платит в пять раз больше CPU при RSA. Провайдеры облаков по умолчанию используют цепочки ECDSA; RSA предлагается только для совместимости с устаревшими клиентами.

Вспомните перед уходом
  1. 01
    Почему сервер отправляет HelloRetryRequest и что клиент делает в ответ?
  2. 02
    Что происходит при провале проверки цепочки сертификатов (неизвестный CA)?
  3. 03
    Объясните ECDHE в одном абзаце. Почему обе стороны приходят к одному секрету, не передавая его?
Итог

TLS 1.3 сжимает рукопожатие до одного RTT, встраивая публичный ключ ECDHE клиента в первое сообщение. Сервер немедленно запускает алгоритм Диффи-Хеллмана на эллиптических кривых для вычисления общего секрета, шифрует остальную часть рукопожатия под выведенным ключом трафика и отправляет сертификат, CertificateVerify и Finished в одном проходе. Поскольку обе стороны используют свежие эфемерные ключи, компрометация долгосрочного ключа подписи сервера позднее не позволит расшифровать прошлые сессии — это и есть Perfect Forward Secrecy. Хеш транскрипта в каждом сообщении Finished обнаруживает любые изменения байтов рукопожатия, включая попытки понижения версии middlebox’ами.

Связанные уроки
встречается в152
Продолжить восхождение ↑Возобновление сессии и 0-RTT
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.