Что такое handshake (рукопожатие) в HTTPS?

«Что такое handshake (рукопожатие) в HTTPS?» — вопрос из категории Сети, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Handshake (рукопожатие) в HTTPS — это процесс установления безопасного TLS/SSL-соединения между клиентом (например, браузером) и сервером перед началом обмена зашифрованными данными. Его цель — аутентификация сервера, согласование криптографических алгоритмов и безопасная генерация общего секретного ключа для симметричного шифрования.

Основные этапы TLS handshake (упрощенно):

  1. Client Hello: Клиент отправляет серверу свою максимальную поддерживаемую версию TLS, список поддерживаемых шифр-наборов (cipher suites) и случайное число (client random).
  2. Server Hello: Сервер отвечает выбранной версией TLS, выбранным шифр-набором, своим случайным числом (server random) и своим SSL-сертификатом, содержащим его публичный ключ.
  3. Проверка сертификата: Клиент проверяет подлинность сертификата сервера (цепочка доверия, срок действия, имя домена).
  4. (Key Exchange): Клиент генерирует Pre-Master Secret, шифрует его публичным ключом сервера и отправляет. Либо используется Ephemeral Diffie-Hellman (DHE/ECDHE), когда обе стороны обмениваются параметрами для вычисления общего секрета без его передачи по сети.
  5. Генерация ключей: И клиент, и сервер независимо вычисляют одинаковый Master Secret из client random, server random и Pre-Master Secret, а затем на его основе генерируют ключи для симметричного шифрования и MAC (коды аутентификации сообщений).
  6. Finished: Обе стороны обмениваются зашифрованными сообщениями, подтверждающими, что handshake прошел успешно и ключи вычислены корректно.

Практический взгляд (C++ разработчика): При реализации сетевого клиента на C++ с использованием библиотек вроде OpenSSL или Boost.Asio + SSL, handshake — это вызов соответствующей функции установки соединения. После его успешного завершения можно писать/читать данные в/из SSL-сокета, и библиотека будет автоматически их шифровать/расшифровывать.

// Псевдокод с использованием Boost.Asio + SSL
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_stream(io_context, ssl_context);
boost::asio::connect(ssl_stream.next_layer(), endpoint);
// Выполнение TLS handshake
ssl_stream.handshake(boost::asio::ssl::stream_base::client);
// После этого соединение безопасно
boost::asio::write(ssl_stream, boost::asio::buffer("GET / HTTP/1.1rnHost: example.comrnrn"));