← Весь справочник

openssl

Сертификаты и ключи — посмотреть, создать, подписать своим CA, проверить TLS-сервер и пару ключ↔сертификат

openssl — набор подкоманд для работы с криптографией и TLS: создать ключ и сертификат, прочитать сертификат, подписать его своим центром сертификации, подключиться к серверу и посмотреть, что он отдаёт. Первым словом всегда идёт подкоманда: x509, req, s_client, genpkey, verify…

Синтаксис

openssl ПОДКОМАНДА [опции]
openssl ПОДКОМАНДА -help      # опции конкретной подкоманды

Файлы обычно в формате PEM — текст между строками -----BEGIN …----- и -----END …-----. Бинарный вариант того же — DER.

Заголовок PEMЧто внутри
BEGIN CERTIFICATEсертификат
BEGIN CERTIFICATE REQUESTзапрос на сертификат (CSR)
BEGIN PRIVATE KEYзакрытый ключ в формате PKCS#8 (BEGIN RSA PRIVATE KEY — старый формат RSA)
BEGIN ENCRYPTED PRIVATE KEYзакрытый ключ, зашифрованный паролем
BEGIN PUBLIC KEYоткрытый ключ

x509 — смотреть и подписывать сертификаты

ОпцияЧто делает
-in файлвходной сертификат (-inform DER — если он в DER)
-nooutне печатать сам сертификат в PEM — только запрошенные поля
-textвсё содержимое в читаемом виде
-subject / -issuerкому выдан / кем подписан; -nameopt RFC2253 — в виде CN=…,O=…
-dates, -startdate, -enddateсрок действия: notBefore и notAfter
-serialсерийный номер
-fingerprint -sha256отпечаток сертификата
-ext subjectAltNameодно расширение: SAN, keyUsage, basicConstraints…
-pubkeyоткрытый ключ из сертификата
-modulusмодуль RSA-ключа (только для RSA)
-checkend Nкод 1 и Certificate will expire, если истечёт в ближайшие N секунд
-outform DER -out файлконвертировать в DER
-req -in csr -CA ca.pem -CAkey ca.keyвыпустить сертификат по CSR, подписав своим CA
-CAcreateserialсоздать файл серийных номеров CA, если его нет
-days Nсрок действия выпускаемого сертификата
-copy_extensions copyперенести расширения (SAN) из CSR в сертификат (OpenSSL 3)

Поля x509 -text

ПолеЧто значит
Serial Numberуникальный номер у этого CA
Signature Algorithmчем подписан: sha256WithRSAEncryption, ecdsa-with-SHA256
Issuerкто подписал; у самоподписанного совпадает с Subject
Validity: Not Before / Not Afterс какого и до какого момента действителен (время в GMT)
Subjectкому выдан: CN (имя), O (организация), C (страна)
Subject Public Key Infoалгоритм и размер ключа: rsaEncryption 2048 bit, id-ecPublicKey 256 bit
X509v3 Subject Alternative Nameимена и IP, для которых сертификат действителен
X509v3 Basic ConstraintsCA:TRUE — сертификатом можно подписывать другие
X509v3 Key Usage / Extended Key Usageдля чего ключ: подпись, шифрование, TLS Web Server Authentication

req — запросы и самоподписанные сертификаты

ОпцияЧто делает
-newсоздать CSR
-x509вместо CSR сразу выдать самоподписанный сертификат
-newkey rsa:2048 / ec -pkeyopt ec_paramgen_curve:P-256заодно создать новый ключ
-key файлиспользовать существующий ключ
-keyout файл / -out файлкуда записать новый ключ / CSR или сертификат
-nodes (в OpenSSL 3 ещё -noenc)не шифровать ключ паролем
-subj '/CN=имя/O=Орг'субъект без интерактивных вопросов
-addext 'subjectAltName=DNS:a,IP:1.2.3.4'добавить расширение
-days Nсрок для -x509
-in csr -noout -text / -verifyпосмотреть CSR / проверить его подпись

Ключи

КомандаЧто делает
genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048RSA-ключ
genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256ключ на эллиптической кривой
genpkey -algorithm ed25519ключ Ed25519
genrsa -out key.pem 2048RSA-ключ, старая команда
pkey -in key.pem -puboutоткрытый ключ из закрытого
pkey -in key.pem -noout -textпараметры ключа
pkey -in key.pem -check -nooutпроверить целостность ключа
rsa -in key.pem -noout -modulusмодуль RSA-ключа

s_client — подключиться к TLS-серверу

ОпцияЧто делает
-connect хост:порткуда подключаться
-servername имяSNI: какое имя сайта просить у сервера
-showcertsвывести всю цепочку, которую прислал сервер
-CAfile ca.pemдоверять этому CA при проверке
-verify_hostname имяпроверить, что сертификат выдан на это имя
-verify_return_errorпрервать соединение, если проверка не прошла (код выхода 1)
-briefкороткая сводка: протокол, шифр, сертификат
-tls1_2 / -tls1_3только эта версия протокола
-starttls smtpTLS поверх обычного протокола (smtp, imap, ftp, postgres…)

В выводе важны строки subject= / issuer= (сертификат сервера), Protocol/Cipher и Verify return code: 0 (ok) — цепочка проверена; 18 — самоподписанный; 20/21 — не найден CA; 10 — истёк; 62 — имя не совпало.

Прочее

КомандаЧто делает
verify -CAfile ca.pem cert.pemпроверить подпись цепочки; -untrusted inter.pem — промежуточные сертификаты
dgst -sha256 файлхеш файла
rand -hex 16 / rand -base64 24случайные байты: пароли, токены
passwd -6 'пароль'хеш пароля для /etc/shadow; -apr1 — для htpasswd
enc -aes-256-cbc -pbkdf2 -in f -out f.encзашифровать файл паролем; -d — расшифровать
pkcs12 -export -in cert.pem -inkey key.pem -out b.p12упаковать сертификат и ключ в PKCS#12 (.p12/.pfx)
pkcs12 -in b.p12 -nokeysдостать сертификаты из PKCS#12

Примеры

# самоподписанный сертификат на год для localhost, ключ без пароля
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
  -keyout key.pem -out cert.pem \
  -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost'

# кому выдан, кем и до какого числа
openssl x509 -in cert.pem -noout -subject -issuer -dates

# истекает ли в ближайшие 30 дней
openssl x509 -in cert.pem -noout -checkend $((30*86400)) || echo 'скоро истечёт'

# свой CA и сертификат, подписанный им
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 -subj '/CN=Demo CA' -keyout ca.key -out ca.pem
openssl req -new -newkey rsa:2048 -nodes -subj '/CN=localhost' \
  -addext 'subjectAltName=DNS:localhost' -keyout srv.key -out srv.csr
openssl x509 -req -in srv.csr -CA ca.pem -CAkey ca.key -CAcreateserial \
  -days 90 -copy_extensions copy -out srv.pem
openssl verify -CAfile ca.pem srv.pem

# подходит ли ключ к сертификату: открытые ключи должны совпасть
diff <(openssl x509 -in cert.pem -noout -pubkey) <(openssl pkey -in key.pem -pubout) && echo 'пара'

# то же для RSA через модуль
openssl x509 -in cert.pem -noout -modulus | sha256sum
openssl rsa  -in key.pem  -noout -modulus | sha256sum

# что отдаёт TLS-сервер; </dev/null — чтобы команда не ждала ввода
openssl s_client -connect localhost:8443 -servername localhost </dev/null

# сертификат сервера сразу в x509: срок и субъект
openssl s_client -connect localhost:8443 -servername localhost </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -dates

# случайный пароль
openssl rand -base64 24

Подводные камни

  • s_client висит без </dev/null. После рукопожатия он ждёт ввода с клавиатуры. Для разовой проверки подавай пустой stdin.
  • -servername важен: без SNI сервер с несколькими сайтами может отдать сертификат не того сайта.
  • s_client не обрывает соединение при ошибке проверки. Verify return code: 18 — соединение установлено, просто сертификат никто не подписывал. Для строгой проверки добавь -verify_return_error, для своего CA — -CAfile.
  • CN больше не главный. Браузеры и программы на Go сверяют имя хоста только с subjectAltName, CN они игнорируют. curl с сертификатом без SAN ещё может согласиться, а браузер — уже нет. Добавляй -addext 'subjectAltName=…'.
  • SAN из CSR не переносится сам. x509 -req по умолчанию выбрасывает расширения запроса. Нужен -copy_extensions copy (OpenSSL 3) или -extfile с нужными строками.
  • -modulus есть только у RSA. Для EC и ed25519 сравнивай открытые ключи через -pubkey / pkey -pubout — этот способ работает для любых ключей.
  • Без -nodes ключ шифруется паролем, и nginx будет спрашивать его при каждом старте.
  • Формат genrsa изменился. В OpenSSL 3 он пишет BEGIN PRIVATE KEY (PKCS#8), а не BEGIN RSA PRIVATE KEY. Если инструкция ищет старый заголовок, дело в версии, а не в ключе.
  • Порядок в файле цепочки: сначала сертификат сервера, потом промежуточные. Корневой CA серверу отдавать не нужно.
  • Ключ — секрет: права 600, владелец — тот, кто его читает.

См. также

nginx · curl · ssh · checksums · base64