SSL и TLS

В речи «SSL-сертификат» обычно означает сертификат для TLS. Исторические версии SSL устарели; современное HTTPS использует TLS.

TLS решает три задачи:

  • шифрует трафик;
  • обнаруживает изменение данных;
  • проверяет подлинность сервера по сертификату и имени.

Клиентский сертификат может дополнительно аутентифицировать клиента — mutual TLS.

Асимметричное и симметричное шифрование

Закрытый ключ хранится только у владельца. Открытый ключ можно распространять. Сертификат связывает открытый ключ с именами и подписывается центром сертификации.

Асимметричные операции применяются в handshake для аутентификации и согласования секрета. Основной трафик затем шифруется быстрыми симметричными ключами сеанса.

Нельзя описывать TLS как «сервер шифрует всё открытым ключом, клиент расшифровывает закрытым»: закрытый ключ сервера не передаётся клиенту, а современные наборы шифров согласуют временные session keys.

Упрощённый TLS 1.3 handshake

  1. Клиент отправляет поддерживаемые параметры, случайные данные, SNI и key share.
  2. Сервер выбирает параметры, отправляет свой key share и цепочку сертификатов.
  3. Клиент проверяет подписи, срок действия и соответствие hostname полю SAN.
  4. Стороны независимо вычисляют общий секрет и ключи.
  5. Проверочные сообщения подтверждают целостность handshake.
  6. Начинается защищённый обмен application data.
sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello + key share
    S-->>C: ServerHello + key share + certificate + Finished
    C->>C: verify chain and hostname
    C->>S: Finished
    C<<->>S: encrypted HTTP

Цепочка доверия

Сервер обычно отдаёт leaf-сертификат и промежуточные сертификаты. Клиент строит цепочку до root CA из локального trust store. Root обычно не нужно передавать сервером.

Проверяются:

  • подпись каждого звена;
  • срок действия;
  • назначение ключа;
  • имя хоста в Subject Alternative Name;
  • при доступности — статус отзыва по принятой политике.

Ошибка «сертификат доверенный, но имя не совпадает» не должна игнорироваться.

Форматы

  • PEM — текстовый контейнер Base64 с заголовками; может хранить сертификат или ключ;
  • DER — бинарное представление;
  • .crt/.cer — часто сертификат, но расширение не гарантирует кодировку;
  • .key — соглашение для ключа;
  • CSR — запрос на выпуск сертификата с открытым ключом и данными субъекта;
  • PKCS#12 (.p12, .pfx) — контейнер для ключа и цепочки, обычно защищённый паролем;
  • JKS — Java keystore; для новых систем часто достаточно PKCS#12.

Смотреть нужно на содержимое и команду импорта, а не только на расширение.

Локальная памятка OpenSSL

Создать ключ и CSR:

openssl genpkey -algorithm RSA -out server.key \
  -pkeyopt rsa_keygen_bits:3072
 
openssl req -new -key server.key -out server.csr \
  -subj "/CN=service.local"

Посмотреть сертификат и проверить пару:

openssl x509 -in server.crt -text -noout
openssl x509 -in server.crt -pubkey -noout > cert.pub
openssl pkey -in server.key -pubout > key.pub
diff cert.pub key.pub

Для реального сертификата SAN задают явно. Закрытый ключ не коммитят, ограничивают права файла и меняют при подозрении на компрометацию.

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

  • сервер не отдал intermediate certificate;
  • сертификат выпущен не на то имя;
  • часы машины сильно расходятся;
  • keystore содержит сертификат без private key;
  • приложение доверяет самоподписанному сертификату глобально;
  • TLS завершается на proxy, а приложение неверно обрабатывает forwarded headers;
  • сертификат обновили, но процесс продолжает использовать старый keystore.

На собеседовании

Сертификат шифрует данные? Он подтверждает связь открытого ключа и имени; session keys для шифрования согласуются в handshake.

Чем trust store отличается от key store? Trust store хранит доверенные сертификаты; key store сервера содержит его private key и цепочку.

Связанные заметки: Http протокол, DNS, Tomcat.