CSR: что это, как сгенерировать запрос на сертификат в OpenSSL и не потерять приватный ключ
15 мин чтения
CSR: что это, как сгенерировать запрос на сертификат в OpenSSL и не потерять приватный ключ

CSR: что это, как сгенерировать запрос на сертификат в OpenSSL и не потерять приватный ключ

Платный или корпоративный SSL-сертификат начинается с CSR — файла, который вы отдаёте удостоверяющему центру. Разбираем, что в нём лежит, почему без SAN сертификат не примет ни один браузер, как сгенерировать запрос одной командой OpenSSL для RSA и ECDSA, что делать в Windows и панелях хостинга, как проверить CSR перед отправкой и как после выпуска собрать цепочку и поставить сертификат в nginx или Apache.

CSR (Certificate Signing Request, запрос на подпись сертификата) — файл в формате PKCS#10 по RFC 2986, в котором лежат публичный ключ, имена доменов и данные владельца, и который подписан парным приватным ключом. CSR отправляют в удостоверяющий центр, а приватный ключ, созданный вместе с ним, никуда не уходит и остаётся на сервере. Из CSR УЦ делает сертификат, который работает только в паре с тем самым ключом: потеряли ключ — сертификат придётся перевыпускать.

Что находится внутри CSR и что из этого уходит в удостоверяющий центр

По RFC 2986 запрос состоит из трёх частей: блока CertificationRequestInfo (версия — всегда 0, имя субъекта, публичный ключ и атрибуты), идентификатора алгоритма подписи и самой подписи. Подпись сделана парным приватным ключом — так УЦ убеждается, что ключ у вас есть; право на домен она не доказывает, его УЦ проверяет отдельно через DNS-запись, файл на сайте или письмо.

Домены живут не в имени субъекта, а в атрибуте extensionRequest из PKCS#9 — там перечислены расширения будущего сертификата, прежде всего subjectAltName. Всё содержимое CSR публично: приватный ключ в файл не попадает ни в каком виде. Сводка полей на сентябрь 2026 по CA/Browser Forum Baseline Requirements (версия 2.3.0 от 7 сентября 2026):

Поле Пример Статус по Baseline Requirements Типичная ошибка
SAN (subjectAltName) DNS:example.com, DNS:www.example.com Обязателен, минимум одно имя DNS или IP Не указан вовсе — браузер покажет ERR_CERT_COMMON_NAME_INVALID
CN (commonName) example.com Не рекомендован; если есть — ровно одно имя, скопированное из SAN; до 64 символов Кириллица вместо punycode; www забыт
O (organizationName) Romashka LLC OV/EV: обязательно, сверяется с реестром; DV: запрещено Название не совпадает с ЕГРЮЛ — проверка OV затягивается
OU (organizationalUnitName) IT Department Запрещено с ballot SC047 (2021), УЦ вырежет Заполнен по старой инструкции
L / ST (город / регион) Moscow / Moscow OV: хотя бы одно из двух, до 128 символов; DV: запрещено Сокращения «Msk», «MO»
C (countryName) RU Ровно две буквы ISO 3166-1 «RUS», «Russia»
Публичный ключ RSA 2048 или EC P-256 RSA от 2048 бит, кратно 8; ECDSA только P-256, P-384, P-521 RSA 1024 из старого скрипта — отказ УЦ
Подпись запроса sha256WithRSAEncryption SHA-256 и выше default_md = sha1 в древнем openssl.cnf

Практический вывод: для DV-сертификата (проверяется только домен) в CSR достаточно SAN и, по традиции, CN — остальное УЦ выбросит. Для OV и EV поля O, L или ST и C обязательны и должны совпадать с реестром юрлиц.

Почему CN без SAN не работает и как правильно перечислить домены

Браузеры сверяют имя сайта только со списком subjectAltName; поле CN для этого не используется. Chrome отключил сопоставление по CN в версии 58 (апрель 2017): RFC 2818 объявил CN устаревшим ещё в 2000 году, а Baseline Requirements с 2012 года требуют SAN во всех публичных сертификатах. Действующие BR формулируют жёстко: SAN обязателен, CN «не рекомендован», а если есть — обязан быть точной копией одного из имён SAN.

Отсюда правила заполнения. Голый домен и www — два разных имени, оба нужно перечислить явно. Wildcard *.example.com покрывает ровно один уровень: shop.example.com — да, example.com и a.b.example.com — нет. Кириллические домены записываются только в punycode (пример.рф → xn--e1afmkfd.xn--p1ai). IP-адрес в SAN допустим, но только публичный: зарезервированные диапазоны УЦ не подпишет. Лимит на число имён у каждого УЦ свой; у Let's Encrypt, по его документации, — до 100 идентификаторов в одном сертификате.

Что нужно закрыть Что писать в SAN Что писать в CN Примечание
Сайт с www и без DNS:example.com, DNS:www.example.com example.com Многие УЦ добавляют www бесплатно, но в CSR лучше указать самому
Все поддомены первого уровня DNS:*.example.com, DNS:example.com *.example.com Wildcard не покрывает голый домен — добавляйте отдельно
Несколько разных сайтов DNS:romashka.ru, DNS:romashka.com, DNS:shop.romashka.ru romashka.ru Тариф multi-domain (SAN/UCC); каждое имя проходит свою проверку
Кириллический домен DNS:xn--e1afmkfd.xn--p1ai xn--e1afmkfd.xn--p1ai Только punycode; Unicode в CSR — отказ или битый сертификат

Как сгенерировать CSR в OpenSSL одной командой: RSA и ECDSA

Ключ и запрос создаются одной командой openssl req с флагом -newkey; SAN добавляется флагом -addext без правки конфигов. Так это выглядит в OpenSSL 3.x (флаг -noenc появился в 3.0; в OpenSSL 1.1.1 вместо него пишите -nodes — в 3.x он объявлен устаревшим, но работает):

# RSA 2048: ключ без пароля + CSR с двумя именами в SAN
openssl req -new -newkey rsa:2048 -noenc \
  -keyout example.com.key -out example.com.csr \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=Romashka LLC/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com"

# ECDSA P-256: то же, но ключ на эллиптической кривой
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc \
  -keyout example.com.ec.key -out example.com.ec.csr \
  -subj "/C=RU/O=Romashka LLC/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com"

# Ключ читает только root
chmod 600 example.com.key example.com.ec.key

Файл .csr — блок между строками -----BEGIN CERTIFICATE REQUEST----- и -----END CERTIFICATE REQUEST-----; его целиком, с обеими строками-ограничителями, вставляют в форму УЦ. Файл .key остаётся на сервере: если форма УЦ просит «загрузить ключ», это повод закрыть вкладку. Когда имён много, вынесите всё в конфиг — его удобно хранить в репозитории и повторять при перевыпуске.

# san.cnf
[ req ]
default_bits       = 3072
default_md         = sha256
prompt             = no
distinguished_name = dn
req_extensions     = ext

[ dn ]
C  = RU
ST = Moscow
L  = Moscow
O  = Romashka LLC
CN = example.com

[ ext ]
subjectAltName = @alt

[ alt ]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = shop.example.com
DNS.4 = api.example.com

# Генерация по конфигу: ключ RSA 3072 возьмётся из default_bits
openssl req -new -noenc -config san.cnf \
  -keyout example.com.key -out example.com.csr

Какой ключ выбирать — RSA или ECDSA. Оба разрешены Baseline Requirements (раздел 6.1.5): RSA от 2048 бит, ECDSA на кривых P-256, P-384 и P-521; другого публичные УЦ не подпишут. Разница — в размере и скорости при равной стойкости (значения — из таблицы сопоставимых длин ключей NIST SP 800-57 Part 1):

Параметр RSA 2048 RSA 3072 ECDSA P-256
Стойкость по NIST, бит 112 128 128
Размер публичного ключа 256 байт 384 байт 64 байта
Размер подписи 256 байт 384 байт около 70 байт
Совместимость с клиентами Все, включая устаревшие Все Все современные; нет у Windows XP, Android до 4.x, Java 6
Когда выбирать Максимально широкая аудитория, старые кассы и терминалы Требование 128 бит при обязательном RSA Обычный сайт или API в 2026 году, мобильный трафик

Компромисс — два сертификата сразу: nginx с версии 1.11.0 принимает несколько пар ssl_certificate / ssl_certificate_key и отдаёт ECDSA современным клиентам, а RSA — старым; для этого делают два CSR на один набор имён.

Как сделать CSR в Windows и панелях хостинга и где он не нужен вообще

В Windows штатный инструмент — certreq с INF-файлом: ключ создаётся в хранилище компьютера, SAN задаётся в секции [Extensions]. Мастер «Создать запрос сертификата» в IIS Manager проще, но SAN не добавляет, поэтому пользуйтесь certreq:

; request.inf
[Version]
Signature = "$Windows NT$"

[NewRequest]
Subject = "CN=example.com, O=Romashka LLC, L=Moscow, S=Moscow, C=RU"
KeyLength = 2048
KeyAlgorithm = RSA
HashAlgorithm = sha256
Exportable = TRUE
MachineKeySet = TRUE
KeySpec = 1
RequestType = PKCS10

[Extensions]
2.5.29.17 = "{text}"
_continue_ = "dns=example.com&"
_continue_ = "dns=www.example.com"

:: В cmd от администратора: создать запрос
certreq -new request.inf example.com.csr

:: После выпуска: привязать сертификат к ключу в хранилище
certreq -accept example.com.cer

Ключ при этом лежит не в файле, а в хранилище сертификатов компьютера; на другой сервер его переносят экспортом в PFX через certlm.msc (нужен Exportable = TRUE, заданный при создании). В панелях хостинга логика та же: cPanel в разделе SSL/TLS требует сначала создать приватный ключ и только потом CSR; ISPmanager делает запрос в разделе «SSL-сертификаты» с типом «запрос на сертификат». Ключ хранит панель, в неё же вставляют выпущенный сертификат; без экспорта на другой сервер он не уедет.

Есть сценарий, где CSR вы вообще не видите: протокол ACME. Клиент вроде certbot или acme.sh сам генерирует ключ, собирает CSR, проходит проверку домена и ставит сертификат. Так работают Let's Encrypt и другие бесплатные DV-центры — подробно в статье про Let's Encrypt. Обратная сторона: срок 90 дней (по желанию — 6) и только DV, без OV и EV.

Способ Где создаётся ключ Где он потом лежит SAN Кому подходит
openssl req На вашем сервере Файл .key рядом с CSR -addext или конфиг Linux, BSD, macOS; скрипты и CI
certreq Windows, хранилище ключей Хранилище компьютера, экспорт в PFX Секция [Extensions] IIS, Exchange, RDP-шлюзы
cPanel, ISPmanager На хостинге Внутри панели Список доменов в форме Виртуальный хостинг; панель сама ставит сертификат
Форма УЦ «сгенерировать за меня» В браузере или у УЦ Скачивается файлом один раз Да Когда сервера ещё нет; ключ путешествует по почте — худший вариант
ACME-клиент На вашем сервере, автоматически Каталог клиента, например /etc/letsencrypt/live/ Да, по списку -d Бесплатный DV с автопродлением

Как проверить CSR перед отправкой в УЦ

Одна команда показывает всё содержимое запроса и проверяет его подпись: openssl req -text -noout -verify. Смотреть нужно на четыре строки — Subject, Public-Key, Subject Alternative Name и Signature Algorithm; если что-то не так, перегенерируйте запрос до отправки: после выпуска исправление — это перевыпуск.

openssl req -in example.com.csr -text -noout -verify
# пример вывода (OpenSSL 3.x)
Certificate request self-signature verify OK
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = RU, ST = Moscow, O = Romashka LLC, CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
        Attributes:
            Requested Extensions:
                X509v3 Subject Alternative Name:
                    DNS:example.com, DNS:www.example.com
    Signature Algorithm: sha256WithRSAEncryption

# Убедиться, что CSR сделан именно этим ключом
openssl req  -in example.com.csr -noout -pubkey | sha256sum
openssl pkey -in example.com.key -pubout      | sha256sum
# пример вывода: хеши совпадают
3f1a9c...e07d  -
3f1a9c...e07d  -

«Version: 1 (0x0)» — норма: в PKCS#10 номер версии равен 0, OpenSSL показывает его как v1. В OpenSSL 1.1.1 первая строка короче — «verify OK»; с версии 3.3 при неверной подписи команда завершается с кодом 1, что удобно в скриптах. Онлайн-декодеры CSR использовать можно: запрос содержит только публичные данные. Опасна соседняя кнопка «сгенерировать CSR онлайн» — она создаёт ключ в чужом браузере или на чужом сервере, а это единственное, чего с ключом делать нельзя.

Что делать после выпуска: цепочка, проверка ключа и установка в nginx и Apache

УЦ присылает сам сертификат и один или несколько промежуточных (ca-bundle); сервер должен отдавать их вместе, ваш сертификат — первым. Без промежуточных на компьютере, где они уже закешированы, всё откроется, а на телефонах посетители увидят ERR_CERT_AUTHORITY_INVALID. Корневой сертификат в файл добавлять не нужно — он и так есть у клиента.

# Собрать цепочку: сначала ваш сертификат, затем промежуточные
cat example.com.crt ca-bundle.crt > fullchain.pem

# Убедиться, что сертификат подходит к ключу (RSA и ECDSA)
openssl x509 -in example.com.crt -noout -pubkey | sha256sum
openssl pkey -in example.com.key -pubout       | sha256sum
# Классический способ только для RSA: сравнить modulus
openssl x509 -in example.com.crt -noout -modulus | openssl md5
openssl rsa  -in example.com.key -noout -modulus | openssl md5

# Срок и имена в полученном сертификате
openssl x509 -in example.com.crt -noout -dates -ext subjectAltName

Дальше — конфиг веб-сервера. В nginx две директивы; в Apache 2.4.8 и новее промежуточные сертификаты кладут в тот же файл SSLCertificateFile, а SSLCertificateChainFile объявлен устаревшим:

# nginx
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
}
# проверить синтаксис и перечитать конфиг без остановки
nginx -t && systemctl reload nginx

# Apache 2.4.8+: SSLCertificateFile /etc/ssl/example.com/fullchain.pem
#                SSLCertificateKeyFile /etc/ssl/example.com/example.com.key

# Проверка снаружи: цепочка и код верификации
openssl s_client -connect example.com:443 -servername example.com \
  </dev/null 2>/dev/null | grep -E "s:|i:|Verify return"
# пример вывода: ваш сертификат, промежуточный, код 0
 0 s:CN = example.com
   i:C = US, O = Example CA, CN = Example CA DV R3
 1 s:C = US, O = Example CA, CN = Example CA DV R3
Verify return code: 0 (ok)

Если перепутать порядок в fullchain.pem, nginx не стартует с ошибкой «SSL_CTX_use_PrivateKey_file … key values mismatch»: он прикладывает ваш ключ к первому сертификату в файле, а это промежуточный. Та же ошибка при верном порядке означает, что ключ и сертификат из разных пар. Остальные поля s_client разобраны в статье о проверке SSL-сертификата сайта.

Отдельный вопрос — как часто всё это повторять. Максимальный срок сертификата задают Baseline Requirements (раздел 6.3.2); ballot SC-081v3, принятый в апреле 2025 года, запустил его сокращение по расписанию, и на сентябрь 2026 действует уже второй этап (срок повторного использования проверки домена сокращается синхронно, а с 2029 года падает до 10 дней):

Сертификат выпущен Максимальный срок Что это значит для CSR
До 15.03.2026 398 дней Один CSR в год
15.03.2026 – 14.03.2027 (сейчас) 200 дней Два выпуска в год; годовой тариф УЦ — два сертификата подряд
15.03.2027 – 14.03.2029 100 дней Четыре выпуска в год
С 15.03.2029 47 дней Восемь выпусков в год; ручной CSR нереалистичен — нужна автоматизация через ACME или API УЦ

Типичные ошибки: потерянный ключ, чужой сервер, пароль на ключе и старый сертификат

Почти все проблемы после выпуска сводятся к одному: сертификат и ключ разъехались — ключ не там, его нет или сервер не может его прочитать. Восстановить ключ из сертификата или CSR невозможно; лечится это новым CSR и перевыпуском, который у большинства УЦ бесплатен в течение оплаченного срока.

Симптом Причина Что делать
Сертификат пришёл, а файла .key нет CSR делали на другом сервере, в панели, в форме УЦ или на ноутбуке, который переустановили Забрать ключ оттуда, где он создан (экспорт PFX, панель); не нашли — новый CSR и перевыпуск
nginx: «key values mismatch» Ключ от другой пары или в fullchain первым идёт промежуточный сертификат Сравнить хеши -pubkey (команды выше); проверить порядок в fullchain.pem
После перезагрузки сайт не поднялся, в логе «Enter PEM pass phrase» Ключ зашифрован паролем, автозапуск ждёт ввода Снять пароль: openssl pkey -in enc.key -out plain.key; либо ssl_password_file в nginx (с 1.7.3) или SSLPassPhraseDialog exec: в Apache
Сертификат заменили, браузер показывает старый Конфиг не перечитан; другой server-блок отвечает первым; CDN или балансировщик перед сервером со своим сертификатом nginx -T | grep ssl_certificate; reload; s_client с -servername; обновить сертификат на CDN отдельно

Как сгенерировать CSR и установить сертификат: пошагово

Порядок для Linux с nginx или Apache; в Windows шаги те же, меняются инструменты.

  1. Составьте полный список имён: голый домен, www, поддомены или wildcard, кириллические домены в punycode. Выберите тип ключа: ECDSA P-256 для нового сайта, RSA 2048 для аудитории со старыми устройствами.
  2. На сервере, где будет работать сайт, выполните openssl req -new -newkey … -noenc -keyout -out с -subj и -addext subjectAltName или с конфигом san.cnf; сразу сделайте chmod 600 на ключ.
  3. Проверьте запрос командой openssl req -text -noout -verify: подпись OK, длина ключа, все имена в Subject Alternative Name, подпись sha256.
  4. Вставьте содержимое .csr вместе со строками BEGIN и END в форму УЦ и пройдите проверку владения доменом: DNS-запись, файл по HTTP или письмо.
  5. Получив сертификат и промежуточные, соберите fullchain.pem (сначала ваш сертификат) и сверьте хеш публичного ключа сертификата с хешем ключа.
  6. Пропишите пути в ssl_certificate и ssl_certificate_key (nginx) или SSLCertificateFile и SSLCertificateKeyFile (Apache 2.4.8+), проверьте конфиг и сделайте reload.
  7. Проверьте снаружи: openssl s_client -servername должен показать цепочку и Verify return code 0; если перед сервером CDN или балансировщик, загрузите сертификат и туда.
  8. Заведите автоматический контроль срока: при действующем лимите 200 дней следующий CSR понадобится через полгода, а с 2027 года — каждые три месяца.

Как не пропустить истечение и убедиться, что новый сертификат виден отовсюду

Разовая проверка s_client показывает состояние сертификата на одном сервере в одну минуту. Она не скажет, что срок кончится в субботу или что один из узлов CDN всё ещё отдаёт старый сертификат, — для этого нужна проверка по расписанию из разных сетей.

Пруфен выполняет проверку SSL-сертификата с интервалом от суток из 20 точек мониторинга — 17 в России, а также Минск, Астана и Испания: контролирует срок действия, соответствие имени и цепочку, а об истечении предупреждает за заданное число дней (параметр expiration_notify_before_days есть и в REST API). Рядом стоит проверка домена: истёкшая регистрация роняет сайт так же надёжно, как истёкший сертификат. После замены сертификата HTTP-проверка из тех же 20 точек с интервалом от 2 минут покажет во вкладке «По локациям», что каждый регион и каждый узел CDN получает рабочий HTTPS.

Срок сертификата — под контролем без календаря

Пруфен предупредит заранее об истечении сертификата и сообщит в Email, Telegram или Макс, если после замены сайт перестал открываться по HTTPS хотя бы из части точек; когда ресурс восстановится, придёт второе уведомление. Если ресурс так и не поднялся, подключается голосовой звонок. Время обнаружения равно интервалу проверки. Бесплатный план включает 5 проверок — хватит на сертификат, домен и HTTP главной страницы; при регистрации на баланс начисляется 150 ₽.

Частые вопросы

Можно ли при продлении использовать старый CSR?

Технически да: CSR не имеет срока действия, большинство УЦ примут тот же файл повторно, и сертификат будет работать с прежним ключом. Но ключ тогда живёт годами, и любая его утечка обесценивает все выпущенные на него сертификаты. Разумнее генерировать новую пару при каждом выпуске — команда та же и занимает секунду.

Где взять приватный ключ, если CSR делали в панели хостинга или в форме УЦ?

Там, где генерировали: в cPanel — раздел SSL/TLS → Private Keys, в ISPmanager — карточка сертификата, откуда ключ можно скачать. Если CSR делала форма УЦ в браузере, ключ отдавали ровно один раз в момент генерации; не сохранили — его нет ни у кого, включая УЦ. Выход один: новый CSR на своём сервере и бесплатный перевыпуск.

Нужно ли добавлять www в SAN, если сайт работает без www?

Нужно, если www.example.com редиректит на голый домен: редирект по HTTPS браузер выполнит только после TLS-рукопожатия, а для него нужен сертификат с именем www. Иначе посетитель, набравший www, получит ошибку раньше, чем редирект. Не включать www можно только если это имя вообще не резолвится в DNS.

Почему УЦ выпустил сертификат на 200 дней, если оплачен год?

Потому что с 15 марта 2026 года Baseline Requirements запрещают публичным УЦ выпускать сертификаты дольше 200 дней; годовая подписка означает право на бесплатные перевыпуски в течение оплаченного периода. Перевыпуск делают тем же или новым CSR через кабинет УЦ. С 15 марта 2027 года лимит станет 100 дней, с 15 марта 2029-го — 47.

Была ли статья полезна?

Начните мониторинг прямо сейчас

Бесплатный тариф — до 5 проверок. 150 ₽ на баланс при регистрации.

Создать аккаунт