Для чего нужны центры сертификации и чем самоподписанные сертификаты отличаются от выданных центрами
Что проверяют
Понимаете ли вы, что сертификат решает задачу подлинности, а не шифрования, и как Go проверяет цепочку доверия. Следом обычно просят показать, как Go-клиенту довериться внутреннему сертификату, не отключая проверку.
Как отвечать
TLS шифрует трафик одинаково с любым сертификатом. Вопрос в другом: как клиенту убедиться, что на том конце действительно api.example.com, а не посредник с собственным ключом. Для этого и нужен центр сертификации.
- CA: проверяет, что заявитель владеет доменом (публичные CA делают это автоматически по протоколу ACME), и подписывает сертификат своим ключом. Цепочка идёт от листового сертификата через промежуточный к корневому, а корневые уже лежат в хранилище доверия ОС и браузеров;
- самоподписанный: издатель и субъект совпадают, сертификат подписан собственным ключом. Никто третий за него не ручается, поэтому клиент отвергнет его, пока вы явно не добавите его в доверенные;
- частный CA: промежуточный вариант для внутренних сервисов и mTLS. Компания держит свой корень (Vault PKI, step-ca, cert-manager в Kubernetes) и раздаёт его сервисам.
В Go пул доверия по умолчанию берётся из системы (x509.SystemCertPool()). Чтобы доверять своему CA, создают пул через x509.NewCertPool(), добавляют корень методом AppendCertsFromPEM и передают его в tls.Config{RootCAs: pool}. Для mTLS на сервере задают ClientCAs и ClientAuth: tls.RequireAndVerifyClientCert. Для тестов есть httptest.NewTLSServer: он поднимает сервер с самоподписанным сертификатом, а ts.Client() уже ему доверяет.
Где спотыкаются
Говорят, что самоподписанный сертификат шифрует слабее. Алгоритмы те же, отличается только то, кто подтверждает владельца ключа.
Лечат ошибку x509: certificate signed by unknown authority через InsecureSkipVerify: true. Это отключает проверку целиком и открывает дорогу атаке посредника. Правильный путь: добавить нужный корень в RootCAs.
Выпускают сертификат только с полем CN. Современный Go сверяет имя хоста по SAN, и без DNSNames или IPAddresses в шаблоне сертификата проверка не пройдёт.