NGINX и SSL: Одновременная работа ECDSA- и RSA-сертификатов для выигрыша в скорости и сохранения обратной совместимости

ECDSA- и RSA-сертификаты одинаково безопасны. Однако последнее время появляется всё больше сайтов c ECDSA-сертификатами. Почему? Потому что 256-битный открытый ключ основанный на элиптических кривых по безопасности равен 3248-битному RSA-ключу. Такое разительное отличие битного размера ключей, позволяет значительно выиграть в скорости хэндшейка. Компания Cloudflare ещё в далеком 2013 году проводила тестирование, сравнивая производительность RSA- и ECDSA-ключей:

Название и битность алгоритма Подписей в секунду
RSA (2048 bits) 1001.8
ECDSA (256 bits) 9516.8

По этой таблице можно увидеть, что 256-битный ключ на элиптических кривых примерно в 10 раз быстрее своего RSA-брата.

В плане безопасности никаких преимуществ у ECDSA-ключей нет. Однако в плане скорости ECDSA безусловный лидер

Поддержка нескольких сертификатов NGINX была добавлена в версии 1.11.0. Поэтому вам потребуется именно она. Вы можете просто скачать их из официальных репозиториев для вашего дистрибутива или же собрать свой, например. Проверить версию NGINX можно командой nginx -V.

Let's Encrypt поддерживает RSA-ключи из коробки, то есть получить его можно одной простой командой:

letsencrypt certonly --webroot --email mail@domain.xyz -w /var/www/coolsite -d domain.xyz --rsa-key-size 4096

После этого вам достаточно указать NGINX на ключ и сертификат из папки /etc/letsencrypt/live/domain.xyz и всё. Однако в случае с ECDSA-сертификатом дела обстоят чуточку сложнее. Let's Encrypt уже достаточно давно поддерживает подписывание ключей подобного типа, но решения "из коробки нет". Однако всё намного проще, чем кажется:

# Создаем приватный 384-битный ECDSA-ключ
openssl ecparam -out private.key -name secp384r1 -genkey

# Создаем CSR-файл на базе ключа
openssl req -new -key private.key -out domain.csr

После второй команды, OpenSSL попросит заполнить несколько полей:

Country Name (2 letter code) [AU] Код страны по стандарту ISO 3166-1. В моём случае RU

State or Province Name (full name) [Some-State] Опционально. Я написал область проживания на английском.

Locality Name (eg, city) [] Город, населенный пункт.

Organization Name (eg, company) [Internet Widgits Pty Ltd] Если вы физическое лицо можно просто нажать Enter или ввести Private Person.

Organizational Unit Name (eg, section) [] Смело оставляем пустым, хотя можно написать IT Department, к примеру.

Common Name (e.g. server FQDN or YOUR name) [] Важное поле, тут пишем ваш FQDN, то есть полный домен в моём случае krasovsky.me. Если ваш сайт с www в начале, то пишем и его.

Email Address [] Ваш email-адрес.

A challenge password [] Опциальный пароль для защиты CSR от считывания.

An optional company name [] Оставьте пустым.

Натравляем Let's Encrypt на полученный нами CSR-файл:

# Не забудьте прописать root и путь к CSR-файлу
letsencrypt certonly --webroot --email mail@domain.xyz --csr /root/domain.csr -w /var/www/coolsite -d domain.xyz

Последний шаг -- указываем полученный нами сертификат и приватный ключ в конфигурации NGINX:

# ECDSA
ssl_certificate /var/www/coolsite/certs/0001_chain.pem;
ssl_certificate_key /var/www/coolsite/certs/private.key;

# RSA
ssl_certificate /etc/letsencrypt/live/fearful.space/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fearful.space/privkey.pem;

На сайте SSLLabs как обычно можно проверить правильно ли мы всё сконфигурировали. После завершения теста в самом начале будет два блока: Certificate #1 и Certificate #2. Конктректно в моём случае:

  1. Certificate #1: EC 384 bits (SHA256withRSA)
  2. Certificate #2: RSA 4096 bits (SHA256withRSA)

По-умолчанию любым браузером будет выбираться первый поддерживаемый сертификат, в большинстве случаев им будет ECDSA-сертификат. А если устройство старое и не поддерживает его, то оно само выберет RSA. В этом плане всё очень удобно.