Чем обеспечивается безопасность HTTPS
Что проверяют
Понимаете ли вы, из чего складывается защита канала: шифрование, целостность, аутентификация стороны. Для бэкендера на Go важна ещё и практика, как сервис ходит в чужие API и что происходит при проверке сертификата, потому что именно здесь чаще всего и появляются дыры.
Как отвечать
HTTPS это обычный HTTP поверх TLS, и защита складывается из трёх свойств.
- Конфиденциальность: после рукопожатия стороны получают общий сеансовый ключ, дальше трафик шифруется симметрично. Ключ согласуется эфемерным Диффи Хеллманом на эллиптических кривых, поэтому утечка приватного ключа сервера не расшифрует записанный ранее трафик.
- Целостность: в современном TLS шифрование и проверку подлинности делает один режим AEAD, например AES-GCM или ChaCha20-Poly1305. У каждой записи есть тег, изменённый байт ломает расшифровку.
- Аутентификация: сервер присылает цепочку сертификатов и подписывает рукопожатие приватным ключом. Клиент проверяет подпись, срок, цепочку до доверенного корня и обязательно совпадение имени хоста.
В Go всё это в стандартной библиотеке: crypto/tls, корни берутся из системного хранилища, у сервера задаются MinVersion и набор шифров. Уместно упомянуть взаимный TLS между сервисами, когда сертификат предъявляет и клиент, и заголовок HSTS с редиректом на границе.
Где спотыкаются
Говорят, что целостность обеспечивает HMAC. В старых версиях TLS так и было, в актуальной отдельного MAC нет, тег считает сам режим AEAD, и эта деталь хорошо отделяет выученный ответ от понимания.
Второе: включают InsecureSkipVerify ради запроса к сервису с самоподписанным сертификатом. Это отключает проверку и имени, и всей цепочки, то есть убирает защиту от подмены сервера целиком, а правильный путь добавить нужный корень в свой пул.
Третье: считают, что HTTPS прячет всё. Имя хоста видно в SNI и в запросах DNS, объём и тайминги тоже, а после терминации TLS на балансировщике трафик внутри периметра идёт открытым, если про это не позаботились отдельно.