Как создать самозаверяющий сертификат с помощью openssl?

Я добавляю поддержку https для встроенного устройства Linux. Я попытался создать самозаверяющий сертификат с помощью этих шагов:

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

Это работает, но я получаю некоторые ошибки, например, с Google Chrome:

Это, вероятно, не тот сайт, который вы ищете!
Сертификат безопасности сайта не является доверенным!

Я что-то пропустил? Это правильный способ создания самозаверяющего сертификата?

24 ответа

Решение

Вы можете сделать это одной командой:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Вы также можете добавить -nodes (Короче для no DES) если вы не хотите защищать свой закрытый ключ парольной фразой, в противном случае вам будет предложено ввести пароль "как минимум из 4 символов". Параметр days (365) можно заменить любым числом, чтобы повлиять на срок действия. Затем вам будет предложено указать такие вещи, как "Название страны", но вы можете просто нажать Enter и принять значения по умолчанию.

добавлять -subj '/CN=localhost' подавить вопросы о содержании сертификата (заменить localhost с желаемым доменом)

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

Следующая команда удовлетворяет все ваши потребности, включая SAN:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout example.key -out example.crt -extensions san -config <(echo '[req]'; echo 'distinguished_name=req'; echo '[san]'; echo 'subjectAltName=DNS:example.com,DNS:example.net') -subj '/CN=example.com'

В OpenSSL ≥ 1.1.1 это можно сократить до:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout example.key -out example.crt -subj '/CN=example.com' -addext 'subjectAltName=DNS:example.com,DNS:example.net'

Это создает сертификат, который

  • действует для доменов example.com а также example.net (САН),
  • относительно сильный (по состоянию на 2018 г.) и
  • действителен до 3650 дней (~10 лет).

Создает следующие файлы:

  • Закрытый ключ: example.key
  • Сертификат: example.crt

Вся информация предоставляется в командной строке. Там нет раздражающего интерактивного ввода. Там нет возни с конфигурационными файлами. Все необходимые шаги выполняются этим единственным вызовом OpenSSL: от генерации закрытого ключа до самозаверяющего сертификата.

Поскольку сертификат самоподписан и должен приниматься пользователями вручную, нет смысла использовать короткий срок действия или слабую криптографию.

В будущем вы можете использовать больше, чем 4096 биты для ключа RSA и алгоритм хеширования сильнее, чем sha256, но с 2018 года это нормальные значения. Они достаточно сильны, хотя поддерживаются всеми современными браузерами.

Замечание: теоретически вы можете оставить -nodes параметр (что означает "без шифрования DES"), в этом случае example.key будет зашифрован паролем. Тем не менее, это почти никогда не полезно для установки на сервере, потому что вам придется либо хранить пароль на сервере, либо вводить его вручную при каждой перезагрузке.

См. Также: https://security.stackexchange.com/a/198409/133603 и /questions/38227402/kak-vyi-svyazyivaete-dva-massiva/38227419#38227419

Я что-то пропустил? Это правильный способ создания самозаверяющего сертификата?

Легко создать самозаверяющий сертификат. Вы просто используете openssl req команда. Может быть сложно создать тот, который будет использоваться самым большим выбором клиентов, таких как браузеры и инструменты командной строки.

Это сложно, потому что браузеры имеют свои собственные требования, и они более строгие, чем IETF. Требования, используемые браузерами, задокументированы на форумах CA/Browser (см. Ссылки ниже). Ограничения возникают в двух ключевых областях: (1) якоря доверия и (2) имена DNS.

Современные браузеры (например, Warez, который мы используем в 2014/2015 гг.) Хотят получить сертификат, который связан с привязкой доверия, и хотят, чтобы DNS-имена были представлены в сертификате особым образом. И браузеры активно движутся против самозаверяющих сертификатов сервера

Некоторые браузеры не позволяют легко импортировать самозаверяющий сертификат сервера. На самом деле, вы не можете с некоторыми браузерами, такими как браузер Android. Итак, полное решение - стать вашим собственным авторитетом.

Если вы не обладаете собственными полномочиями, вы должны правильно присвоить DNS-имена, чтобы сертификат имел наибольшие шансы на успех. Но я бы посоветовал вам стать вашим собственным авторитетом. Легко стать вашим собственным авторитетом, и он будет обходить все вопросы доверия (кому лучше доверять, чем вам?).


Это, вероятно, не тот сайт, который вы ищете!
Сертификат безопасности сайта не является доверенным!

Это связано с тем, что браузеры используют предопределенный список якорей доверия для проверки сертификатов сервера. Самозаверяющий сертификат не связывается с доверенным якорем.

Лучший способ избежать этого:

  1. Создайте свой собственный авторитет (например, станьте CA)
  2. Создать запрос на подпись сертификата (CSR) для сервера
  3. Подпишите CSR сервера с вашим ключом CA
  4. Установите сертификат сервера на сервере
  5. Установите сертификат CA на клиенте

Шаг 1 - Создать свой собственный орган - значит создать самозаверяющий сертификат с CA: true и правильное использование ключа. Это означает, что субъект и эмитент - это одна и та же сущность, для CA задано значение true в базовых ограничениях (это также должно быть помечено как критическое), использование ключа keyCertSign а также crlSign (если вы используете CRL), а идентификатор ключа субъекта (SKI) совпадает с идентификатором ключа авторизации (AKI).

Чтобы стать вашим собственным центром сертификации, см. Раздел Как подписать запрос на подпись сертификата в своем центре сертификации? Переполнение стека. Затем импортируйте свой CA в Trust Store, используемый браузером.

Шаги 2–4 - это примерно то же самое, что вы делаете сейчас для общедоступного сервера, когда вы подключаете службы CA, такие как Startcom или CAcert. Шаги 1 и 5 позволяют вам избежать полномочий третьих лиц и действовать как свои собственные полномочия (кому лучше доверять, чем себе?).

Следующий лучший способ избежать предупреждения браузера - это доверять сертификату сервера. Но некоторые браузеры, такие как браузер Android по умолчанию, не позволяют вам сделать это. Так что это никогда не будет работать на платформе.

Проблема браузеров (и других подобных пользовательских агентов), не доверяющих самоподписанным сертификатам, станет большой проблемой в Интернете вещей (IoT). Например, что произойдет, когда вы подключитесь к своему термостату или холодильнику, чтобы запрограммировать его? Ответ: ничего хорошего в отношении пользовательского опыта.

Рабочая группа W3C WebAppSec начинает изучать эту проблему. См., Например, Предложение: Пометка HTTP как незащищенного.


Как создать самозаверяющий сертификат с помощью openssl?

Приведенные ниже команды и файл конфигурации создают самозаверяющий сертификат (он также показывает, как создать запрос на подпись). Они отличаются от других ответов в одном отношении: имена DNS, используемые для самозаверяющего сертификата, находятся в дополнительном имени субъекта (SAN), а не в общем имени (CN).

Имена DNS помещаются в SAN через файл конфигурации со строкой subjectAltName = @alternate_names (нет способа сделать это через командную строку). Тогда есть alternate_names раздел в файле конфигурации (вы должны настроить его на свой вкус):

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

Важно ввести DNS-имя в SAN, а не в CN, потому что и IETF, и форумы CA/Browser определяют практику. Они также указывают, что DNS-имена в CN являются устаревшими (но не запрещены). Если вы поместите DNS-имя в CN, оно должно быть включено в SAN в соответствии с политиками CA / B. Таким образом, вы не можете избежать использования альтернативного имени субъекта.

Если вы не введете DNS-имена в SAN, сертификат не будет проверен в браузере и других пользовательских агентах, которые следуют рекомендациям CA/Browser Forum.

Связано: браузеры следуют политикам CA/Browser Forum; а не политики IETF. Это одна из причин, по которой сертификат, созданный с помощью OpenSSL (который обычно соответствует IETF), иногда не проверяется в браузере (браузеры следуют CA/B). Это разные стандарты, разные политики выдачи и разные требования к валидации.


Создайте самозаверяющий сертификат (обратите внимание на добавление -x509 опция):

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

Создайте запрос на подпись (обратите внимание на отсутствие -x509 опция):

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

Распечатать самоподписанный сертификат:

openssl x509 -in example-com.cert.pem -text -noout

Распечатать запрос на подпись:

openssl req -in example-com.req.pem -text -noout

Файл конфигурации (передается через -config опция)

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because its presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you 
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

Возможно, вам придется сделать следующее для Chrome. В противном случае Chrome может жаловаться, что общее имя недействительно ( ERR_CERT_COMMON_NAME_INVALID ) Я не уверен, какова связь между IP-адресом в SAN и CN в этом случае.

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

Существуют и другие правила обработки имен DNS в сертификатах X.509/PKIX. Обратитесь к этим документам для правил:

RFC 6797 и RFC 7469 перечислены, потому что они более строгие, чем другие документы RFC и CA / B. RFC 6797 и 7469 также не допускают IP-адреса.

Вот варианты, описанные в ответе @ diegows, более подробно описанном в документации:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX
req

Утилита запроса сертификата PKCS#10 и создания сертификата.

-x509

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

-newkey arg

эта опция создает новый запрос сертификата и новый закрытый ключ. Аргумент принимает одну из нескольких форм. rsa: nbits, где nbits - количество битов, генерирует RSA-ключ размером nbit.

-keyout filename

это дает имя файла для записи недавно созданного закрытого ключа.

-out filename

Это указывает имя выходного файла для записи или стандартный вывод по умолчанию.

-days n

когда используется опция -x509, это указывает количество дней, на которые сертификат должен быть сертифицирован. По умолчанию 30 дней.

-nodes

если указан этот параметр, то при создании закрытого ключа он не будет зашифрован.

Документация на самом деле более подробная, чем выше, я просто резюмировал ее здесь.

Я не могу комментировать, поэтому поставлю это как отдельный ответ. Я нашел несколько вопросов с принятым однострочным ответом:

  • Однострочник содержит ключевую фразу в ключе.
  • Однострочник использует SHA1, который во многих браузерах выдает предупреждения в консоли.

Вот упрощенная версия, которая удаляет парольную фразу, повышает безопасность для подавления предупреждений и включает предложение в комментариях для передачи в -subj для удаления полного списка вопросов:

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Замените localhost на любой домен, который вам требуется. Вам нужно будет выполнить первые две команды одну за другой, так как openssl запросит парольную фразу.

Чтобы объединить их в файл.pem:

cat server.crt server.key > cert.pem

Современные браузеры теперь выдают ошибку безопасности для правильно сформированных самозаверяющих сертификатов, если им не хватает SAN (Subject Alternate Name). OpenSSL не предоставляет способ командной строки для указания этого, поэтому многие учебные пособия и закладки для разработчиков неожиданно устарели.

Самый быстрый способ возобновить работу - это короткий автономный файл конфигурации:

  1. Создайте файл конфигурации OpenSSL (пример: req.cnf)

    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
    
  2. Создайте сертификат, ссылающийся на этот файл конфигурации

    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
    

Пример конфигурации из https://support.citrix.com/article/CTX135602_

Я бы порекомендовал добавить параметр -sha256, чтобы использовать алгоритм хеширования SHA-2, потому что основные браузеры рассматривают возможность отображения "сертификатов SHA-1" как небезопасные.

Та же самая командная строка из принятого ответа - @diegows с добавленным -sha256

openssl req -x509 -sha256 -newkey rsa: 2048 -keyout key.pem -out cert.pem -days XXX

Больше информации в блоге безопасности Google.

Обновление май 2018 года. Как отмечалось в комментариях многих, использование SHA-2 не повышает безопасность самозаверяющего сертификата. Но я все же рекомендую использовать его как хорошую привычку не использовать устаревшие / небезопасные криптографические хеш-функции. Полное объяснение доступно в: https://security.stackexchange.com/questions/91913/why-is-it-fine-for-certificates-above-the-end-entity-certificate-to-be-sha1-base

Я не могу комментировать, поэтому добавляю отдельный ответ. Я попытался создать самозаверяющий сертификат для NGINX, и это было легко, но когда я хотел добавить его в белый список Chrome, у меня возникла проблема. И моим решением было создать корневой сертификат и подписать им дочерний сертификат.

Итак, шаг за шагом. Создайте файл config_ssl_ca.cnf Обратите внимание: в файле конфигурации есть опция basicConstraints=CA:true, что означает, что этот сертификат должен быть корневым.

Это хорошая практика, потому что вы создаете его один раз и можете использовать повторно.

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=root region
localityName=root city
organizationName=root organisation
organizationalUnitName=roote department
commonName=root
emailAddress=root_email@root.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:true
subjectKeyIdentifier = hash
subjectAltName = @alternate_names

Следующий файл конфигурации для вашего дочернего сертификата.

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=Kyiv region
localityName=Kyiv
organizationName=market place
organizationalUnitName=market place department
commonName=FirstName LastName
emailAddress=email@market.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:false
subjectAltName = @alternate_names
subjectKeyIdentifier = hash

Первый шаг - создать Root-ключ и сертификат

openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt -days 365 -config config_ssl_ca.cnf

На втором этапе создается дочерний ключ и файл CSR - Certificate Signing Request. Потому что идея заключается в том, чтобы подписать дочерний сертификат root и получить правильный сертификат

openssl genrsa -out market.key 2048
openssl req -new -sha256 -key market.key -config config_ssl.cnf -out market.csr

Откройте терминал Linux и выполните эту команду echo 0

echo 1 > ca.srl
touch index.txt

Ca.srl текстовый файл, содержащий следующий серийный номер для использования в шестнадцатеричном формате. Обязательное. Этот файл должен присутствовать и содержать действительный серийный номер.

Последний шаг, создайте еще один файл конфигурации и назовите его config_ca.cnf

# we use 'ca' as the default section because we're usign the ca command
[ ca ]
default_ca = my_ca

[ my_ca ]
#  a text file containing the next serial number to use in hex. Mandatory.
#  This file must be present and contain a valid serial number.
serial = ./ca.srl

# the text database file to use. Mandatory. This file must be present though
# initially it will be empty.
database = ./index.txt

# specifies the directory where new certificates will be placed. Mandatory.
new_certs_dir = ./

# the file containing the CA certificate. Mandatory
certificate = ./ca.crt

# the file contaning the CA private key. Mandatory
private_key = ./ca.key

# the message digest algorithm. Remember to not use MD5
default_md = sha256

# for how many days will the signed certificate be valid
default_days = 365

# a section with a set of variables corresponding to DN fields
policy = my_policy

# MOST IMPORTANT PART OF THIS CONFIG
copy_extensions = copy

[ my_policy ]
# if the value is "match" then the field value must match the same field in the
# CA certificate. If the value is "supplied" then it must be present.
# Optional means it may be present. Any fields not mentioned are silently
# deleted.
countryName = match
stateOrProvinceName = supplied
organizationName = supplied
commonName = supplied
organizationalUnitName = optional
commonName = supplied

Вы спросите, почему так сложно, зачем нужно создавать еще один конфиг для подписи дочернего сертификата root. Ответ прост, поскольку в дочернем сертификате должен быть блок SAN - альтернативные имена субъектов. Если мы подпишем дочерний сертификат с помощью утилит "openssl x509", корневой сертификат удалит поле SAN в дочернем сертификате. Поэтому мы используем openssl ca вместо openssl x509, чтобы избежать удаления поля SAN. Мы создаем новый файл конфигурации и приказываем ему скопировать все расширенные поля copy_extensions = copy.

openssl ca -config config_ca.cnf -out market.crt -in market.csr

Программа задаст вам 2 вопроса: 1. Подписать сертификат? Скажите "Y" 2. 1 из 1 запросов на сертификат сертифицирован, зафиксировать? Скажите "Y"

В терминале вы можете увидеть предложение со словом "База данных", это означает файл index.txt, который вы создаете командой "touch". Он будет содержать всю информацию обо всех сертификатах, которые вы создаете с помощью утилиты "openssl ca". Чтобы проверить действительность сертификата, используйте:

openssl rsa -in market.key -check

Если вы хотите посмотреть, что внутри CRT:

openssl x509 -in market.crt -text -noout

Если вы хотите посмотреть, что внутри в CSR:

openssl req -in market.csr -noout -text 

Этот сценарий я использую на локальных ящиках для установки SAN (subjectAltName) в самозаверяющих сертификатах.

Этот сценарий берет имя домена (example.com) и создает SAN для *.example.com и example.com в одном сертификате. Разделы ниже комментируются. Назовите сценарий (например, generate-ssl.sh) и дать ему исполняемые разрешения. Файлы будут записаны в тот же каталог, что и скрипт.

Chrome 58 и более поздних версий требует, чтобы SAN был установлен в самозаверяющих сертификатах.

#!/usr/bin/env bash

# Set the TLD domain we want to use
BASE_DOMAIN="example.com"

# Days for the cert to live
DAYS=1095

# A blank passphrase
PASSPHRASE=""

# Generated configuration file
CONFIG_FILE="config.txt"

cat > $CONFIG_FILE <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = CA
ST = BC
L = Vancouver
O = Example Corp
OU = Testing Domain
emailAddress = webmaster@$BASE_DOMAIN
CN = $BASE_DOMAIN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.$BASE_DOMAIN
DNS.2 = $BASE_DOMAIN
EOF

# The file name can be anything
FILE_NAME="$BASE_DOMAIN"

# Remove previous keys
echo "Removing existing certs like $FILE_NAME.*"
chmod 770 $FILE_NAME.*
rm $FILE_NAME.*

echo "Generating certs for $BASE_DOMAIN"

# Generate our Private Key, CSR and Certificate
# Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout "$FILE_NAME.key" -days $DAYS -out "$FILE_NAME.crt" -passin pass:$PASSPHRASE -config "$CONFIG_FILE"

# OPTIONAL - write an info to see the details of the generated crt
openssl x509 -noout -fingerprint -text < "$FILE_NAME.crt" > "$FILE_NAME.info"

# Protect the key
chmod 400 "$FILE_NAME.key"

Этот сценарий также записывает информационный файл, чтобы вы могли проверить новый сертификат и убедиться, что SAN настроен правильно.

                ...
                28:dd:b8:1e:34:b5:b1:44:1a:60:6d:e3:3c:5a:c4:
                da:3d
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            DNS:*.example.com, DNS:example.com
Signature Algorithm: sha256WithRSAEncryption
     3b:35:5a:d6:9e:92:4f:fc:f4:f4:87:78:cd:c7:8d:cd:8c:cc:
     ...

Если вы используете Apache, вы можете ссылаться на вышеуказанный сертификат в вашем конфигурационном файле следующим образом:

<VirtualHost _default_:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/htdocs

    SSLEngine on
    SSLCertificateFile path/to/your/example.com.crt
    SSLCertificateKeyFile path/to/your/example.com.key
</VirtualHost>

Не забудьте перезапустить сервер Apache (или Nginx, или IIS), чтобы новый сертификат вступил в силу.

2017 Один лайнер:

openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.pem \
-new \
-out server.pem \
-subj /CN=localhost \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
-sha256 \
-days 3650

Это также работает в Chrome 57, так как он предоставляет SAN, не имея другого файла конфигурации. Взято из ответа здесь. Это создает один файл.pem, который содержит как закрытый ключ, так и сертификат. Вы можете переместить их в отдельные файлы.pem, если это необходимо.

Сгенерировать ключ без пароля и сертификата на 10 лет, короткий путь:

      openssl req  -x509 -nodes -new  -keyout server.key -out server.crt -days 3650 -subj "/C=/ST=/L=/O=/OU=web/CN=www.server.com"

openssl позволяет сгенерировать самоподписанный сертификат одной командой (-newkeyпредписывает сгенерировать закрытый ключ и -x509 предписывает выдать самозаверяющий сертификат вместо запроса на подпись)::

openssl req -x509 -newkey rsa:4096 \
-keyout my.key -passout pass:123456 -out my.crt \
-days 365 \
-subj /CN=localhost/O=home/C=US/emailAddress=me@mail.internal \
-addext "subjectAltName = DNS:localhost,DNS:web.internal,email:me@mail.internal" \
-addext keyUsage=digitalSignature -addext extendedKeyUsage=serverAuth

Вы можете сгенерировать закрытый ключ и создать самозаверяющий сертификат в отдельные шаги:

openssl genrsa -out my.key -passout pass:123456 2048

openssl req -x509 \
-key my.key -passin pass:123456 -out my.csr \
-days 3650 \
-subj /CN=localhost/O=home/C=US/emailAddress=me@mail.internal \
-addext "subjectAltName = DNS:localhost,DNS:web.internal,email:me@mail.internal" \
-addext keyUsage=digitalSignature -addext extendedKeyUsage=serverAuth

Просмотрите полученный сертификат:

openssl x509 -text -noout -in my.crt

Ява keytool создает хранилище PKCS#12::

keytool -genkeypair -keystore my.p12 -alias master \
-storetype pkcs12 -keyalg RSA -keysize 2048 -validity 3650 \
-storepass 123456 \
-dname "CN=localhost,O=home,C=US" \
-ext 'san=dns:localhost,dns:web.internal,email:me@mail.internal'

Чтобы экспортировать самоподписанный сертификат:

keytool -exportcert -keystore my.p12 -file my.crt \
-alias master -rfc -storepass 123456

Просмотрите полученный сертификат:

keytool -printcert -file my.crt

certtoolиз GnuTLS не позволяет передавать различные атрибуты из CLI. Не люблю возиться с конфигурационными файлами ((

oneliner v2017:

CentOS:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

убунт:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

Генерировать ключи

я использую /etc/mysql для хранения сертификата, потому что /etc/apparmor.d/usr.sbin.mysqld содержит /etc/mysql/*.pem r,

sudo su -
cd /etc/mysql
openssl genrsa -out ca-key.pem 2048;
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem;
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem;
openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;

Добавить конфигурацию

/etc/mysql/my.cnf

[client]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/client-cert.pem
ssl-key=/etc/mysql/client-key.pem

[mysqld]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

На моей установке сервер Ubuntu вошел в систему: /var/log/mysql/error.log

Последующие заметки:

  • SSL error: Unable to get certificate from '...'

    Mysql может быть отказано в доступе к чтению вашего файла сертификата, если он не находится в конфигурации apparmors. Как упоминалось в предыдущих шагах ^, сохраните все наши сертификаты как .pem файлы в /etc/mysql/ каталог, который по умолчанию утвержден apparmor (или измените ваш apparmor/SELinux, чтобы разрешить доступ к тому месту, где вы их сохранили).

  • SSL error: Unable to get private key

    Ваша версия сервера MySQL может не поддерживать по умолчанию rsa:2048 формат.

    Скрытый сгенерированный rsa:2048 равнине rsa с:

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • Проверьте, поддерживает ли локальный сервер ssl:

    mysql -u root -p
    mysql> show variables like "%ssl%"; 
    +---------------+----------------------------+
    | Variable_name | Value                      |
    +---------------+----------------------------+
    | have_openssl  | YES                        |
    | have_ssl      | YES                        |
    | ssl_ca        | /etc/mysql/ca-cert.pem     |
    | ssl_capath    |                            |
    | ssl_cert      | /etc/mysql/server-cert.pem |
    | ssl_cipher    |                            |
    | ssl_key       | /etc/mysql/server-key.pem  |
    +---------------+----------------------------+
    
  • Проверка соединения с БД ssl зашифрована:

    Проверка соединения

    При входе в экземпляр MySQL вы можете выполнить запрос:

    show status like 'Ssl_cipher'; 
    

    Если ваше соединение не зашифровано, результат будет пустым:

    mysql> show status like 'Ssl_cipher'; 
    +---------------+-------+ 
    | Variable_name | Value | 
    +---------------+-------+ 
    | Ssl_cipher    |       |  
    +---------------+-------+ 
    1 row in set (0.00 sec) 
    

    В противном случае он будет показывать строку ненулевой длины для используемого шифра:

    mysql> show status like 'Ssl_cipher'; 
    +---------------+--------------------+ 
    | Variable_name | Value              | 
    +---------------+--------------------+ 
    | Ssl_cipher    | DHE-RSA-AES256-SHA |  
    +---------------+--------------------+ 
    1 row in set (0.00 sec) 
    
  • Требовать ssl для подключения конкретного пользователя ('require ssl'):

    • SSL

    Сообщает серверу разрешить только учетные записи с шифрованием SSL для учетной записи.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      REQUIRE SSL;
    

    Для подключения клиент должен указать параметр --ssl-ca для проверки подлинности сертификата сервера и может дополнительно указать параметры --ssl-key и --ssl-cert. Если не указана ни опция --ssl-ca, ни опция --ssl-capath, клиент не аутентифицирует сертификат сервера.


Альтернативная ссылка: длительный учебник здесь http://www.madirish.net/214

Один лайнер FTW. Мне нравится быть простым. Почему бы не использовать одну команду, которая содержит ВСЕ необходимые аргументы? Вот как мне это нравится - это создает сертификат x509 и его ключ PEM:

openssl req -x509 \
 -nodes -days 365 -newkey rsa:4096 \
 -keyout self.key.pem \
 -out self-x509.crt \
 -subj "/C=US/ST=WA/L=Seattle/CN=example.com/emailAddress=someEmail@gmail.com" 

Эта единственная команда содержит все ответы, которые вы обычно предоставляете для деталей сертификата. Таким образом, вы можете установить параметры и запустить команду, получить выходные данные - а затем пойти на кофе.

>> подробнее здесь <<;;

Быстрая командная строка: Минимальная версия

«Мне нужен самоподписанный сертификат в форме pfx для www.example.com с минимальными усилиями»:

      openssl req -x509 -sha256 -days 365 -nodes -out cert.crt -keyout cert.key -subj "/CN=www.example.com"
openssl pkcs12 -export -out cert.pfx -inkey cert.key -in cert.crt

У вас правильная общая процедура. Синтаксис команды приведен ниже.

openssl req -new -key {private key file} -out {output file}

Тем не менее, предупреждения отображаются, потому что браузер не смог проверить идентификацию путем проверки сертификата с помощью известного центра сертификации (CA).

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

  1. Генерация закрытого ключа
  2. Используйте этот закрытый ключ для создания файла CSR
  3. Отправить CSR в CA (Verisign или другие и т. Д.)
  4. Установите полученный сертификат от CA на веб-сервере
  5. Добавить другие сертификаты в цепочку аутентификации в зависимости от типа сертификата

У меня есть более подробная информация об этом в сообщении на https://bigthinkingapplied.com/secure-the-connection-installing-certificates-on-3-common-web-servers/

Как подробно обсуждалось, самоподписанные сертификаты не являются доверенными для Интернета. Вы можете добавить свой самозаверяющий сертификат во многие, но не во все браузеры. В качестве альтернативы вы можете стать вашим собственным центром сертификации.

Основная причина, по которой человек не хочет получать подписанный сертификат от центра сертификации, - это стоимость - Symantec взимает от 995 до 1999 долларов в год за сертификаты - только за сертификат, предназначенный для внутренней сети, Symantec взимает 399 долларов в год. Эту стоимость легко оправдать, если вы обрабатываете платежи по кредитным картам или работаете в центре прибыли высокодоходной компании. Это больше, чем многие могут себе позволить для личного проекта, который каждый создает в Интернете, или для некоммерческой организации, работающей с минимальным бюджетом, или если кто-то работает в центре затрат организации - центры затрат всегда пытаются сделать больше менее.

Альтернативой является использование certbot (см. О certbot). Certbot - это простой в использовании автоматический клиент, который получает и развертывает сертификаты SSL/TLS для вашего веб-сервера.

Если вы настроили certbot, вы можете разрешить ему создавать и поддерживать для вас сертификат, выданный центром сертификации Let's Encrypt.

Я сделал это на выходных для своей организации. Я установил необходимые пакеты для certbot на своем сервере (Ubuntu 16.04), а затем выполнил команду, необходимую для настройки и включения certbot. Вероятно, для certbot нужен плагин DNS - в настоящее время мы используем DigitalOcean, хотя, возможно, скоро перейдем на другой сервис.

Обратите внимание, что некоторые инструкции были не совсем верными и заняли время, чтобы разобраться с Google. В первый раз это заняло довольно много времени, но теперь я думаю, что смогу сделать это за считанные минуты.

Что касается DigitalOcean, я столкнулся с трудностями, когда мне предложили ввести путь к INI-файлу учетных данных DigitalOcean. Сценарий имеет в виду страницу " Приложения и API" и вкладку "Токены / ключи" на этой странице. Вам необходимо иметь или сгенерировать личный токен доступа (чтение и запись) для API DigitalOcean - это шестнадцатеричная строка из 65 символов. Затем эту строку необходимо поместить в файл на веб-сервере, с которого вы запускаете certbot. Этот файл может содержать комментарий в качестве первой строки (комментарии начинаются с #). Вторая строка:

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

Как только я понял, как настроить токен чтения и записи для API DigitalOcean, было довольно легко использовать certbot для установки сертификата с подстановочными знаками. Обратите внимание, что не нужно настраивать подстановочный сертификат, вместо этого можно указать каждый домен и поддомен, к которому требуется применить сертификат. Это был подстановочный сертификат, который требовал INI-файл учетных данных, содержащий личный токен доступа от DigitalOcean.

Обратите внимание, что сертификаты открытых ключей (также известные как сертификаты идентификации или сертификаты SSL) истекают и требуют обновления. Таким образом, вам необходимо будет обновлять свой сертификат на периодической (повторяющейся) основе. Документация certbot покрывает продление сертификатов.

Мой план состоит в том, чтобы написать скрипт, который будет использовать команду openssl, чтобы получить дату истечения срока действия моего сертификата и инициировать продление по истечении 30 дней или менее до его истечения. Затем я добавлю этот скрипт в cron и буду запускать его один раз в день.

Вот команда, чтобы прочитать дату истечения срока действия вашего сертификата:

root@prod-host:~# /usr/bin/openssl x509 -enddate -noout -in path-to-certificate-pem-file
notAfter=May 25 19:24:12 2019 GMT

После долгих поисков, игры с различными решениями, я все же столкнулся с проблемой, из-за которой выдача самозаверяющего сертификата для локального хоста дала мне ошибку

ERR_CERT_INVALID

При раскрытии деталей хром сказал:

Вы не можете посетить локальный хост прямо сейчас, потому что веб-сайт отправил зашифрованные учетные данные...

И единственный уродливый способ пройти — набрать (прямо в этом экране, не видя никакого курсора для текста):

(введите на клавиатуре) это небезопасно

Что позвольте мне продолжить.

Пока я не нашел extendedKeyUsage = serverAuth, clientAuth

TL;DR

  1. openssl genrsa -out localhost.key 2048

  2. openssl req -key localhost.key -new -out localhost.csr

  3. (нажмите «Ввод» для всего и просто заполните общее имя (CN) с помощью localhost или другого вашего полного доменного имени.

      echo "
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints       = CA:TRUE
keyUsage               = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign
extendedKeyUsage       = serverAuth, clientAuth
subjectAltName         = DNS:localhost, DNS:localhost.localdomain
issuerAltName          = issuer:copy
" > v3.ext
  1. openssl x509 -req -in localhost.csr -signkey localhost.key -out localhost.pem -days 3650 -sha256 -extfile v3.ext

И вуаля! Вы можете посетить веб-сайт, развернуть «Дополнительно» и нажать «Перейти к локальному хосту (небезопасно)».

Это сработало для меня

openssl req -x509 -nodes -subj '/CN=localhost'  -newkey rsa:4096 -keyout ./sslcert/key.pem -out ./sslcert/cert.pem -days 365

server.js

var fs = require('fs');
var path = require('path');
var http = require('http');
var https = require('https');
var compression = require('compression');
var express = require('express');
var app = express();

app.use(compression());
app.use(express.static(__dirname + '/www'));    

app.get('/*', function(req,res) {
  res.sendFile(path.join(__dirname+'/www/index.html'));
});

// your express configuration here

var httpServer = http.createServer(app);
var credentials = {
    key: fs.readFileSync('./sslcert/key.pem', 'utf8'),
    cert: fs.readFileSync('./sslcert/cert.pem', 'utf8')
};
var httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

console.log(`RUNNING ON  http://127.0.0.1:8080`);
console.log(`RUNNING ON  http://127.0.0.1:8443`);

Сценарии самоподписанного сертификата и цепочки сертификатов для RSA и ECDSA с использованием OpenSSL доступны здесь.

Это очень простое приложение Python, которое создает самозаверяющий сертификат. Код:

      from OpenSSL import crypto, SSL
from secrets import randbelow
print("Please know, if you make a mistake, you must restart the program.")
def cert_gen(
    emailAddress=input("Enter Email Address: "),
    commonName=input("Enter Common Name: "),
    countryName=input("Enter Country Name (2 characters): "),
    localityName=input("Enter Locality Name: "),
    stateOrProvinceName=input("Enter State of Province Name: "),
    organizationName=input("Enter Organization Name: "),
    organizationUnitName=input("Enter Organization Unit Name: "),
    serialNumber=randbelow(1000000),
    validityStartInSeconds=0,
    validityEndInSeconds=10*365*24*60*60,
    KEY_FILE = "private.key",
    CERT_FILE="selfsigned.crt"):
    #can look at generated file using openssl:
    #openssl x509 -inform pem -in selfsigned.crt -noout -text
    # create a key pair
    k = crypto.PKey()
    k.generate_key(crypto.TYPE_RSA, 4096)
    # create a self-signed cert
    cert = crypto.X509()
    cert.get_subject().C = countryName
    cert.get_subject().ST = stateOrProvinceName
    cert.get_subject().L = localityName
    cert.get_subject().O = organizationName
    cert.get_subject().OU = organizationUnitName
    cert.get_subject().CN = commonName
    cert.get_subject().emailAddress = emailAddress
    cert.set_serial_number(serialNumber)
    cert.gmtime_adj_notBefore(0)
    cert.gmtime_adj_notAfter(validityEndInSeconds)
    cert.set_issuer(cert.get_subject())
    cert.set_pubkey(k)
    cert.sign(k, 'sha512')
    with open(CERT_FILE, "wt") as f:
        f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
    with open(KEY_FILE, "wt") as f:
        f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"))
    print("GENERATED")
    input("Press enter to close program.")
cert_gen()

Однако вы по-прежнему получаете сообщение об ошибке «Сертификат не является доверенным». Это связано с несколькими причинами:

  1. Он является самозаверяющим/не проверенным (для проверенного сертификата потребуется ЦС (центр сертификации), например Let's Encrypt, чтобы ему можно было доверять на всех устройствах).
  2. На вашей машине ему не доверяют. ( этот ответ показывает, как вы можете заставить Windows доверять вашему сертификату).

Если вы хотите генерировать самоподписанные сертификаты с использованием открытого ssl — вот сгенерированный нами скрипт, который можно использовать как есть.

      #!/bin/bash

subj='//SKIP=skip/C=IN/ST=Country/L=City/O=MyCompany/OU=Technology'
red='\033[31m'        # red
yellow='\033[33m'        # yellow
green='\033[32m'        # green
blue='\033[34m'        # Blue
purple='\033[35m'      # Purple
cyan='\033[36m'        # Cyan
white='\033[37m'       # White


gencerts(){
certname=$1
pkname=$2
alias=$3
$(openssl genrsa -out $pkname'pem.pem' 4096)
$(openssl req -new -sha256 -key $pkname'pem.pem' -out $certname'csr.csr' -subj $subj)
$(openssl x509 -req -sha256 -days 3650 -in $certname'csr.csr' -signkey $pkname'pem.pem' -out $certname'.crt')
$(openssl pkcs12 -export -out $pkname'.p12' -name $alias -inkey $pkname'pem.pem' -in $certname'.crt')
}

verify(){
pkname=$1
keytool -v -list -storetype pkcs12 -keystore $pkname'.p12'
}

echo -e "${purple}WELCOME TO KEY PAIR GENERATOR"
echo -e "${yellow} Please enter the name of the certificate required: "
read certname
echo -e "${green}Please enter the name of the Private Key p12 file required: "
read pkname
echo -e "${cyan}Please enter the ALIAS of the Private Key p12 file : "
read pkalias
echo -e "${white}Please wait while we generate your Key Pair"

gencerts $certname $pkname $pkalias
echo -e "${white}Now lets verify the private key :)"

tput bel     # Play a bell

verify $pkname
  • Дайте мне знать, если в скрипт можно внести какие-либо улучшения.

Вам не нужно использоватьopensslПлохой пользовательский интерфейс вообще! Попробуйте mkcert .

      $ brew install mkcert nss
[...]

$ mkcert -install
Created a new local CA 
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires browser restart)! 

$ mkcert example.com "*.example.com" example.test localhost 127.0.0.1 ::1

Created a new certificate valid for the following names 
 - "example.com"
 - "*.example.com"
 - "example.test"
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./example.com+5.pem" and the key at "./example.com+5-key.pem" ✅
Другие вопросы по тегам