Как устанавливается HTTPS-соединение: кто определяет алгоритм шифрования и как передаются ключи
Что проверяют
Понимаете ли вы, что в современном TLS сессионный ключ никто никому не пересылает, а стороны вычисляют его сами. Следом обычно спрашивают, зачем тогда нужен сертификат и что изменилось в TLS 1.3 по сравнению с 1.2.
Как отвечать
Опишите рукопожатие TLS 1.3, сейчас оно по умолчанию почти везде:
- ClientHello: клиент присылает поддерживаемые версии, список наборов шифров, группы для обмена ключами, свою половину обмена (
key_share, чаще всего X25519, в свежих браузерах гибрид с постквантовым ML-KEM), имя хоста в SNI и протоколы в ALPN (h2,http/1.1); - выбор алгоритма: делает сервер. Он берёт из предложенного списка набор по своим предпочтениям, например
TLS_AES_128_GCM_SHA256, и отвечает в ServerHello своей половиной обмена; - общий секрет: обе стороны по (EC)DHE получают одинаковое значение, из него через HKDF выводятся ключи. Сам ключ по сети не идёт, поэтому даже утечка закрытого ключа сервера не раскроет записанный ранее трафик (forward secrecy);
- сертификат: сервер присылает цепочку и
CertificateVerify, подпись закрытым ключом над всей перепиской рукопожатия. Клиент проверяет цепочку до корня в хранилище доверия, срок действия и совпадение имени хоста; - Finished: обе стороны подтверждают, что видели одну и ту же переписку. На всё уходит один круг туда-обратно, при возобновлении сессии возможен 0-RTT с риском повтора запроса.
Для Python добавьте практику: ssl.create_default_context() проверяет сертификат и имя хоста по умолчанию, requests берёт корневые сертификаты из certifi, а посмотреть реальное рукопожатие удобно через openssl s_client -connect host:443.
Где спотыкаются
Рассказывают, что клиент шифрует сессионный ключ открытым ключом сервера. Так работал RSA-обмен в TLS 1.2 и раньше, в TLS 1.3 его убрали именно из-за отсутствия forward secrecy.
Говорят «SSL». Все версии SSL давно запрещены, сейчас в ходу TLS 1.2 и 1.3.
Отключают проверку через verify=False в requests, чтобы «заработало». Это открывает дорогу атаке «человек посередине»; правильно передать свой CA-файл через verify="путь" или переменную REQUESTS_CA_BUNDLE.