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

1294

Я добавляю поддержку 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:

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

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

michelemarcon
источник
40
Самоподписанные сертификаты считаются небезопасными для Интернета. Firefox будет рассматривать сайт как имеющий недействительный сертификат, в то время как Chrome будет действовать так, как если бы соединение было простым HTTP. Более подробная информация: gerv.net/security/self-signed-certs
user1202136
34
Вам необходимо импортировать сертификат CA в ваши браузеры и сообщить браузерам, что вы доверяете сертификату, или подписать его одной из крупных организаций, которым уже доверяют браузеры, или игнорировать предупреждение и нажать кнопку. мимо него. Мне нравится последний вариант сам.
trojanfoe
12
Вы не должны использовать «стандартные» настройки OpenSSL, как это. Это потому, что вы не можете помещать DNS-имена в дополнительное имя субъекта (SAN). Вам нужно предоставить файл конфигурации с alternate_namesразделом и передать его с -configопцией. Кроме того, размещение DNS-имени в Common Name (CN) не рекомендуется (но не запрещено) как IETF, так и CA / Browser Forums. Любое DNS-имя в CN также должно присутствовать в SAN. Нет способа избежать использования SAN. Смотрите ответ ниже.
jww
5
В дополнение к комментарию @jww. В мае 2017 года Chrome больше не принимает сертификаты без (emtpy) SAN: «Сертификат для этого сайта не содержит расширение Subject Alternative Name, содержащее доменное имя или IP-адрес».
GerardJP
6
В настоящее время, если ваш веб-сервер доступен по его полному доменному имени через порт 80 через Интернет, вы можете использовать LetsEncrypt и получать бесплатные полные сертификаты CA (действительные в течение 90 дней, обновление может быть автоматизировано), которые не будут выдавать предупреждения браузера / Сообщения. www.letsencrypt.com
Барни

Ответы:

2131

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

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на нужный домен).

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

Диего Войтасен
источник
8
Для тех, кто заинтересован, вот документация , если вы хотите что-то проверить самостоятельно.
17
Как подпись со сторонним поставщиком обеспечивает большую безопасность?
Джеймс Миллс
201
Для всех, кто использует это в автоматизации, вот все общие параметры для предмета:-subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
Alex S
17
@JamesMills Я имею в виду, подумайте об этом - если тенистый парень с надписью «бесплатная конфета» на боку его фургона приглашает вас войти внутрь, вы полностью подумаете дважды и будете настороже - но если кто-то, кому вы доверяете - например, по- настоящему доверяете, - все это как «нау человек, он легитимен», вы будете думать об этой бесплатной конфете
BrainSlugs83
73
Не забудьте использовать -sha256для генерации сертификата на основе SHA-256.
Gea-Suan Lin
536

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

Создать самозаверяющий сертификат легко. Вы просто используете 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 примерно то , что вы делаете сейчас для публики перед сервером , когда вы заручиться услугами ЦС как 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
# IP.1        = 127.0.0.1
# IP.2        = ::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 it's 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-адреса.

jww
источник
4
Можно ли использовать подстановочные знаки в alternate_namesразделе? Особенно суб-субдомены. У меня есть вопрос, ссылающийся на этот ответ здесь: serverfault.com/questions/711596/…
LeonardChallis
3
Я только что ответил на его конкретный вопрос. Я думаю, что нет смысла добавлять это длинное описание безопасности, когда ответ был таким простым
Диего Войтасен
14
@diegows - ваш ответ не является полным или правильным. Причина, по которой это не правильно, обсуждается в длинном посте, который вы не хотите читать :)
jww
1
Спасибо! Я нашел ваш пост очень полезным. Кстати, я недавно играл с хранилищем и обнаружил, что он настаивал на IP.x 127.0.0.1, а не DNS.x 127 ... Я не проверял, в стандарте это или нет.
Чоме
4
Спасибо, @jww. Вы сказали: «1. Создайте свой собственный орган (т. Е. Станьте центром сертификации)» , а затем сказали: «5. Установите сертификат CA на клиенте» . Если корневой ключ был скомпрометирован, злоумышленник может подписать сертификат для любого домена с этим ключом, и если он обманом заставит вас перейти на свой веб-сайт, он может теперь выполнить атаку «человек посередине». Есть ли способ создать корневой ЦС так, чтобы он мог подписывать только промежуточные ЦС, а не сертификаты? Тогда вы можете защитить свой промежуточный центр сертификации с помощью ограничения имени.
Робин Циммерманн
408

Вот варианты, описанные в ответе @ 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

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

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

Питер Мортенсен
источник
3
XXXВ исходной команде должно быть заменено на "количество дней , чтобы удостоверять сертификат. По умолчанию 30 дней. Например, -days XXXстановится, -days 365если вы хотите, чтобы ваш сертификат действовал в течение 365 дней. Смотрите документы для получения дополнительной информации .
Натан Джонс
Спасибо за добавление документации. Эта ссылка IBM на создание самозаверяющего сертификата с использованием команды, которая кажется идентичной этому ответу
The Red Pea
314

Начиная с 2020 года, следующая команда обслуживает все ваши потребности, включая 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,IP:10.0.0.1
    ) \
  -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,IP:10.0.0.1"

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

  • действителен для доменов example.comи example.net(SAN),
  • также действителен для IP-адреса 10.0.0.1(SAN),
  • относительно сильный (по состоянию на 2020 год) и
  • действителен в течение 3650дней (~ 10 лет).

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

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

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

Замечание № 1: параметры шифрования

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

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

Замечание № 2: параметр " -nodes"

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

Замечание № 3: Смотрите также

ВОГ
источник
1
Я не мог понять, в чем именно виноват аргумент arg / CN = localhost, расширяющийся до C: / Program Files / Git / CN = localhost, поэтому я просто запустил всю команду в обычном cmd.exe, и она отлично работала. На всякий случай, если кто-то борется с этим.
Юрий Позняк
1
@FranklinYu Вы уверены, что rsa: 2048 будет достаточно через 10 лет? Потому что это срок действия. Как объяснено, не имеет смысла использовать короткий срок действия или слабую криптографию. Большинство 2048-битных ключей RSA имеют срок действия не более 1-3 лет. Что касается OpenSSL 1.1.1, я все еще оставляю sha256 там, так что это более явно и очевидно изменить, если вы хотите более сильный хеш.
ВОГ
1
@DaveFerguson Разве тогда //CN=localhostвместо этого создается сертификат /CN=localhost? Поможет ли здесь правильный побег? Например, решает ли замена /CN=localhostс "/CN=localhost"чистой проблемой?
ВОГ
4
1000 + 1 для создания «однострочного», который использует новый требуемый SAN, без необходимости создавать длинный конфигурационный файл с большим количеством шаблонов. Отлично сработано!
Джошуа Пинтер
1
@cautionbug Спасибо! Я просто отредактировал это в ответ. Правильный ли сейчас ответ для Windows / MinGW?
Фог
143

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

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

Вот упрощенная версия, которая удаляет ключевую фразу, повышает безопасность для подавления предупреждений и включает предложение в комментариях для передачи в -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
Майк Н
источник
6
Мне нужен был сертификат разработчика для github.com/molnarg/node-http2, и этот ответ просто лучший.
Капай
1
Чтобы объединить сертификат и ключ в одном файле: cat server.crt server.key >foo-cert.pem. Работает с примером вopenssl-1.0.2d/demos/ssl/
18446744073709551615
Сертификат, который я создал таким образом, все еще использует SHA1.
user169771
1
Ткс, прекрасно работает, чтобы создать самозаверяющий сертификат FreeBSD 10 OpenLDAP 2.4сTLS
Тьяго Перейра
2
Как насчет файла key.pem?
Quikchange
72

Современные браузеры теперь выдают ошибку безопасности для правильно сформированных самозаверяющих сертификатов, если им не хватает 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

rymo
источник
1
Это сработало для меня после удаления последнего параметра -extensions 'v3_req', который вызывал ошибку. Использование OpenSSL для Windows. Наконец-то мне удалось решить эту проблему! Спасибо.
CGodo
1
@ Kyopaxa вы правы - этот параметр избыточен со строкой 3 файла cnf; обновлено.
rymo
2
Солидный способ. Спасибо. Я бы предложил добавить -sha256.
Черувим
5
Теперь вы можете указать SAN в командной строке, -extension 'subjectAltName = DNS:dom.ain, DNS:oth.er'см. Github.com/openssl/openssl/pull/4986
Александр Дюбрей
2
Похоже, эта опция называется -addextсейчас.
Александр Зарубкин
67

Я бы порекомендовал добавить параметр -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-1? ,

Марис Б.
источник
1
Если это самозаверяющий ключ, он все равно будет генерировать ошибки браузера, так что это не имеет значения
Марк
30
@ Марк, это важно, потому что SHA-2 более безопасен
Марис Б.
1
Открытие сертификата в Windows после переименования cert.pem в cert.cer говорит, что алгоритм отпечатка пальца все еще - Sha1, но алгоритм хэша подписи - sha256.
согрешил
2
«Шифрование мирового класса * нулевая аутентификация = нулевая безопасность» gerv.net/security/self-signed-certs
x-yuri
4
Обратите внимание, что алгоритм подписи, используемый на самозаверяющем сертификате, не имеет значения при принятии решения, заслуживает ли он доверия или нет. Корневые сертификаты CA являются самозаверяющими. и по состоянию на май 2018 года все еще существует много активных корневых сертификатов CA, которые подписаны SHA-1. Потому что не имеет значения, доверяет ли сертификат самому себе и как этот сертификат проверяет это доверие. Вы либо доверяете корневому / самоподписанному сертификату того, кто это говорит, либо нет. См. Security.stackexchange.com/questions/91913/…
Эндрю Хенле,
20

Это сценарий, который я использую на локальных компьютерах для установки 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), чтобы новый сертификат вступил в силу.

Дрейки
источник
Работает на macOS High Siera и Chrome 58
Сакиб Омер
Я до сих пор не уверен, как CN влияет на общую настройку? Я пытаюсь запустить это как localhostили 127.0.0.1:port#что будет соответствовать CNдля чего-то вроде этого.
DJ2
@ DJ2 Я бы установил BASE_DOMAIN = «localhost»
Drakes
9

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, если это необходимо.

joemillervi
источник
2
Для пользователей Linux вам нужно изменить этот путь для конфигурации. например, на текущей Ubuntu /etc/ssl/openssl.confработает
склонение
Для однострочника, который не требует указания местоположения openssl.cnf, см .: stackoverflow.com/a/41366949/19163
vog
7

Я не могу комментировать, поэтому я добавляю отдельный ответ. Я попытался создать самозаверяющий сертификат для 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

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

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

На втором этапе создается дочерний ключ и файл CSR - запрос на подпись сертификата. Потому что идея заключается в том, чтобы подписать дочерний сертификат 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 - Subject Alternative Names. Если мы подписываем дочерний сертификат утилитой 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 
mrkiril
источник
2
Хотя этот процесс выглядит сложным, это именно то, что нам нужно для домена .dev, так как этот домен не поддерживает самозаверяющие сертификаты, а Chrome и Firefox форсируют HSTS. Я выполнил следующие действия: создание CA, создание сертификата и подписание его с моим CA, а в конце - доверие к CA в браузере. Спасибо.
bajicdusko
1
Вы, сэр, чертова легенда. Мой homelab спасибо тебе!
antsyawn
6

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

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

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

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

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

У меня есть более подробная информация об этом в посте « Защита соединения: создание сертификата безопасности с OpenSSL».

nneko
источник
6

Один лайнер 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"

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

>> Подробнее здесь <<

OkezieE
источник
1
Все аргументы, кроме SAN ... ответ @ vog также охватывает это (и предшествует этому) (хотя здесь заполнено более полное поле "Тема" ...) (Не большой поклонник истечения одного года)
Герт ван ден Берг
6

Однострочная версия 2017:

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"))

Ubuntu:

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"))

Редактировать: добавлен предшествующий слеш в 'subj' для Ubuntu.

user327843
источник
3

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

Я использую /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, клиент не аутентифицирует сертификат сервера.


Альтернативная ссылка: подробное руководство по безопасным PHP-соединениям с MySQL по SSL .

ThorSummoner
источник
-1; это в значительной степени касательно задаваемого вопроса, а также плохо проясняет, откуда взяты его цитаты.
Марк Амери
Это показывает, что инициализирующий CA, сервер / клиентские сертификаты подписаны CA, настраивают их для чтения mysqld на хосте с apparmor. Он иллюстрирует довольно бесполезный случай размещения CA, сервера и клиента на одной машине и опасно подвергает полномочия этого CA процессу mysqld. Эта настройка не имеет смысла, кроме как протестировать конфигурацию ssl в тестовой среде. Для работы с внутренним ЦС я бы порекомендовал набор инструментов gnuttls поверх openssl help.ubuntu.com/community/GnuTLS и хорошо разбирался в tls, прежде чем обойти дело mysqld + apparmor
ThorSummoner
3

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

Основная причина, по которой человек не хочет получать подписанный сертификат от центра сертификации, - это стоимость - 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
Питер Джирак Элдрич
источник