> Для чего нужны центры сертификации и чем самоподписанные сертификаты отличаются от выданных центрами (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: VK

Стек: Go

> Пример ответа

Короткий ответ

Центры сертификации (CA) - это доверенные третьи стороны, которые подтверждают принадлежность публичного ключа конкретному субъекту, подписывая его сертификат. Самоподписанный сертификат - это сертификат, который субъект подписывает своим же ключом, без внешнего подтверждения. Разница в цепочке доверия: для CA клиент доверяет через предустановленные корневые сертификаты, для самоподписанного - только если клиент явно добавил его в доверенные. На практике CA используются в публичных системах, самоподписанные - во внутренних или для тестов.

Подробное объяснение

Сертификат X.509 - это структура данных, связывающая публичный ключ с идентификатором (домен, организация, человек) и подписанная некоторым ключом. Подпись гарантирует целостность и аутентичность содержимого.

Центр сертификации - это организация, которая:

  • выпускает сертификаты после проверки заявителя (domain validation, organization validation, extended validation);
  • подписывает их своим приватным ключом;
  • поддерживает CRL (certificate revocation list) и OCSP (online certificate status protocol) для отзыва;
  • управляет сроком действия и иерархией (root CA → intermediate CA → leaf).

Клиент (браузер, сервер, приложение) доверяет CA, потому что корневой сертификат CA предустановлен в доверенное хранилище операционной системы или приложения. При проверке клиент строит цепочку от leaf-сертификата до корневого, проверяя подписи на каждом уровне, срок действия, отзыв и имя.

Самоподписанный сертификат - это сертификат, где issuer и subject совпадают, и подпись сделана собственным приватным ключом. Он не входит ни в какую цепочку доверия, кроме самого себя. Клиент не может проверить его валидность без явного добавления в доверенные хранилище. Это создает риск MITM (man-in-the-middle), если клиент просто игнорирует предупреждение.

Ключевые отличия:

  • доверие: CA - через предустановленные корни, самоподписанный - через ручное добавление;
  • проверка подлинности: CA проверяет заявителя, самоподписанный - никто не проверяет;
  • отзыв: CA поддерживает CRL/OCSP, для самоподписанного отзыв не имеет смысла;
  • срок жизни: CA обычно выпускает на 1-2 года, самоподписанный - на любой срок;
  • стоимость: CA платный (или бесплатный Let's Encrypt), самоподписанный - бесплатный.

На практике

В Go работа с сертификатами идет через crypto/tls, crypto/x509 и crypto/x509/pkix.

Для сервера с самоподписанным сертификатом:

  • клиент должен либо добавить сертификат в RootCAs в tls.Config, либо использовать InsecureSkipVerify: true (крайне не рекомендуется в production);
  • для внутренних сервисов (например, между микросервисами в закрытой сети) самоподписанные сертификаты допустимы, если управление доверием автоматизировано (например, через внутренний CA или секреты).

Для публичного API или веб-сервиса обязательно использовать CA (Let's Encrypt, AWS Certificate Manager, внутренний корпоративный CA), потому что клиенты (браузеры, мобильные приложения) не будут доверять самоподписанному.

В Go при создании tls.Config для сервера обычно указывают Certificates (leaf + chain), а для клиента - RootCAs. При использовании CA-выданного сертификата цепочка включает промежуточные сертификаты, которые сервер должен отправлять клиенту.

Пример кода

GO
// Создание самоподписанного сертификата в Go
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"os"
"time"
)
func main() {
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
tmpl := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "localhost",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
DNSNames: []string{"localhost"},
}
derBytes, _ := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv)
certOut, _ := os.Create("cert.pem")
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, _ := os.Create("key.pem")
keyBytes, _ := x509.MarshalECPrivateKey(priv)
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes})
keyOut.Close()
}
GO
// Клиент с доверием к самоподписанному сертификату
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net/http"
)
func main() {
caCert, _ := ioutil.ReadFile("cert.pem")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
},
},
}
resp, err := client.Get("https://localhost:8443")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
}

Как отвечать на собеседовании

Начни с определения CA и его роли в PKI. Затем четко сформулируй разницу в модели доверия: CA - это предустановленный корень, самоподписанный - ручное доверие. Приведи примеры, когда что использовать: публичный API - CA, внутренний сервис - самоподписанный или внутренний CA. Упомяни про цепочку сертификатов, intermediate CA и проверку отзыва. Если спросят про Go, покажи, как настроить tls.Config для клиента с кастомным RootCAs и почему InsecureSkipVerify - это плохо. Не углубляйся в криптографию, если не просят.

Что проверяет интервьюер

  • понимание модели доверия PKI, а не просто заученных терминов;
  • умение объяснить, почему самоподписанный сертификат небезопасен для публичных систем;
  • знание практических аспектов: цепочка, отзыв, срок действия;
  • для Go - умение работать с crypto/tls и crypto/x509, понимание RootCAs и InsecureSkipVerify;
  • способность выбрать правильный подход под задачу (внутренний vs внешний сервис).

Типичные ошибки

  • утверждение, что самоподписанный сертификат "небезопасен" сам по себе - он небезопасен только из-за отсутствия доверия;
  • предложение использовать InsecureSkipVerify: true как решение - это отключает проверку полностью и открывает MITM;
  • игнорирование промежуточных сертификатов - сервер должен отправлять всю цепочку, иначе клиент не сможет построить путь до корня;
  • путаница между самоподписанным и self-signed CA (внутренний CA тоже может быть самоподписанным, но он используется для подписи других сертификатов);
  • забывание про отзыв сертификатов - для CA это критично, для самоподписанных - не применимо.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью