Як створити самопідписаний сертифікат за допомогою OpenSSL


1291

Я додаю підтримку 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:

Це, мабуть, не той сайт, який ви шукаєте!
Сертифікат безпеки сайту не довіряється!

Я щось пропускаю? Це правильний спосіб скласти самопідписаний сертифікат?


40
Самостійно підписані сертифікати вважаються небезпечними для Інтернету. Firefox буде вважати сайт недійсним сертифікатом, а Chrome діятиме так, як ніби з'єднання було звичайним HTTP. Більш детально: gerv.net/security/self-signed-certs
user1202136

34
Вам потрібно імпортувати свій сертифікат CA у ваші браузери та сказати браузерам, яким ви довіряєте сертифікат, або підпишіть його однією з великих організацій без грошей, які вже не довіряють браузерам, або проігноруйте попередження та натисніть повз нього. Мені подобається останній варіант сам.
trojanfoe

12
Ви не повинні використовувати такі "налаштування" OpenSSL-налаштування. Це тому, що ви не можете розміщувати імена DNS в альтернативному імені теми (SAN). Потрібно надати файл конфігурації з alternate_namesрозділом і передати його з -configопцією. Крім того, розміщення імені DNS у загальному імені (CN) є застарілим (але не заборонено) і IETF, і форумами CA / Browser. Будь-яке ім'я DNS в CN також повинно бути присутнім в SAN. Не можна уникнути використання SAN. Дивіться відповідь нижче.
jww

5
На додаток до коментаря @jww. На травень 2017 року Chrome більше не приймає сертифікати без введення SAN (emtpy) SAN: "Сертифікат для цього сайту не містить розширення з альтернативним іменем суб'єкта, що містить доменне ім'я або IP-адресу."
GerardJP

6
У ці дні, поки ваш веб-сервер буде доступний через його FQDN на порт 80 через Інтернет, ви можете використовувати LetsEncrypt та отримати безкоштовні повні сертифікати CA (дійсні 90 днів, оновлення може бути автоматизовано), що не дасть жодних попереджень браузера / повідомлення. www.letsencrypt.com
barny

Відповіді:


2130

Це можна зробити за допомогою однієї команди:

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.
Геа-Суан Лін

534

Я щось пропускаю? Це правильний спосіб скласти самопідписаний сертифікат?

Створити сертифікат самопідписання легко. Ви просто використовуєте openssl reqкоманду. Створити такого, який може споживати найбільший вибір клієнтів, як-от браузери та інструменти командного рядка, може бути складним.

Це складно, оскільки у браузерів є свій набір вимог, і вони більш обмежуючі, ніж IETF . Вимоги, якими користуються браузери, задокументовані на форумах CA / Browser (див. Посилання нижче). Обмеження виникають у двох ключових областях: (1) довіра якоря та (2) імена DNS.

Сучасні веб-переглядачі (як, наприклад, warez, який ми використовуємо у 2014/2015), хочуть отримати сертифікат, який прив’язується до якоря довіри, і вони хочуть, щоб імена DNS були представлені певним чином у сертифікаті. І браузери активно переходять проти самопідписаних серверних сертифікатів.

Деякі веб-переглядачі не дуже легко імпортувати сертифікат сервера, який самостійно підписав. Насправді ви не можете використовувати деякі браузери, як-от браузер Android. Отже, повне рішення - стати вашим власним авторитетом.

Якщо ви не станете своїм владним органом, ви повинні отримати права імен DNS, щоб дати сертифікату найбільший шанс на успіх. Але я б закликав вас стати власною владою. Стати власною владою легко, і це обійде стороною всі питання довіри (кому краще довіряти, ніж собі?).


Це, мабуть, не той сайт, який ви шукаєте!
Сертифікат безпеки сайту не довіряється!

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

Найкращий спосіб уникнути цього:

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

Крок 1. Створення власних повноважень означає лише створення сертифіката, який підписав самостійно, CA: trueта належного використання ключа. Це означає, що Суб'єкт та Емітент - це одне ціле об'єднання, CA встановлено в " Основні обмеження" істинним (його також слід позначати як критичне), використання ключа - keyCertSignі crlSign(якщо ви використовуєте CRL), а ідентифікатор ключа суб'єкта (SKI) - те саме, що ідентифікатор ключа авторитету (AKI).

Щоб стати власним органом сертифікації, див. * Як ви підписуєте запит на підписання сертифікату у своєму сертифікаційному органі? на стеку переповнення. Потім імпортуйте свій CA в Trust Store, який використовується браузером.

Кроки 2 - 4 - це приблизно те, що ви робите зараз для загальнодоступного сервера, коли ви зараховуєте до служб ЦС, наприклад, Startcom або CAcert . Кроки 1 і 5 дозволяють уникнути сторонніх повноважень та діяти як власні повноваження (кому краще довіряти, ніж собі?).

Наступний найкращий спосіб уникнути попередження браузера - довіряти сертифікату сервера. Але деякі браузери, як-от браузер за замовчуванням Android, не дозволяють вам це робити. Таким чином, це ніколи не буде працювати на платформі.

Випуск браузерів (та інших подібних агентів користувачів) немає довіряють сертифікатам, що підписуються самі, стане великою проблемою в Інтернеті речей (IoT). Наприклад, що буде, коли ви підключите до свого термостата або холодильника, щоб запрограмувати його? Відповідь - нічого хорошого, що стосується досвіду користувача.

Робоча група WebAppSec W3C починає розглядати це питання. Див., Наприклад, Пропозиція: Позначення 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. RFCs 6797 та 7469 також не дозволяють IP-адресу.


4
Чи можливо використовувати підстановку в alternate_namesрозділі? Особливо субдомени. У мене тут питання, на яке посилається ця відповідь: serverfault.com/questions/711596/…
LeonardChallis,

3
Я щойно відповів на його конкретне запитання. Думаю, не має сенсу додавати цей довгий опис безпеки, коли відповідь була такою простою
Дієго Войтасен,

14
@diegows - Ваша відповідь не повна або правильна. Причина її неправильності обговорюється в довгому дописі, який ви не хочете читати :)
1616

1
Дякую! Я вважаю вашу публікацію дуже корисною. FYI Я нещодавно грав зі сховищем і виявив, що він наполягав на IP.x 127.0.0.1, а не на DNS.x 127 ... Я не перевіряв, чи це у стандарті чи ні.
Чом

4
Дякую @jww. Ви сказали: "1. Створіть власні повноваження (тобто перетворіться на ЦС)" , потім сказали: "5. Встановіть сертифікат CA на клієнта" . Якщо кореневий ключ пошкодився, зловмисник може підписати сертифікат для будь-якого домену за допомогою цього ключа, і якщо вони змусять вас перейти на їхній веб-сайт, вони тепер можуть здійснити атаку "посередника". Чи є спосіб створити кореневий ЦС таким, щоб він міг підписувати лише посередницькі ЦО, а не сертифікати? Тоді ви можете захистити свого посередника CA обмеженням імені.
Робін Циммерманн

408

Ось варіанти, описані у відповіді @ diegows , описані більш докладно, із документації :

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

Запит на сертифікат PKCS №10 та утиліта для створення сертифікатів.

-x509

ця опція видає самопідписаний сертифікат замість запиту на сертифікат. Зазвичай використовується для генерації тестового сертифіката або самопідписаного кореня CA.

-newkey arg

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

-keyout filename

це дає ім'я файлу для запису щойно створеного приватного ключа.

-out filename

Це визначає назву вихідного файлу для запису або стандартний вихід за замовчуванням.

-days n

коли використовується опція -x509 , це вказує кількість днів для підтвердження сертифіката. За замовчуванням - 30 днів.

-nodes

якщо цей параметр вказаний, тоді, якщо буде створений приватний ключ, він не буде зашифрований.

Документація насправді більш детальна, ніж вище; Я просто тут це підсумував.


3
XXXУ вихідній команді повинно бути замінено на "кількість днів , щоб засвідчувати сертифікат. За замовчуванням - 30 днів. Наприклад, -days XXXстає, -days 365якщо ви хочете, щоб ваш сертифікат був дійсним 365 днів. Докладніше див. У документах .
Натан Джонс

Дякуємо, що додали документацію. Це посилання IBM на створення самопідписаного сертифіката за допомогою команди, яка здається ідентичною цій відповіді
Red Pea

313

Станом на 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
Я не міг зрозуміти, у чому саме винен аргумент / CN = localhost, який розширюється до C: / Program Files / Git / CN = localhost, тому я просто запустив всю команду в звичайному cmd.exe, і це спрацювало чудово. Про всяк випадок, коли хтось бореться з цим.
Юрій Позняк

1
@FranklinYu Ви впевнені, що rsa: 2048 буде достатньо через 10 років? Тому що це термін дії. Як було пояснено, не має сенсу використовувати короткий термін дії або слабку криптовалюту. Більшість 2048-розрядних ключів RSA мають термін дії не більше 1-3 років. Щодо OpenSSL 1.1.1, я все ще залишаю там sha256, тому явніше і очевидно змінити, якщо ви хочете більш сильний хеш.
vog

1
@DaveFerguson Чи не створений тоді сертифікат //CN=localhostзамість /CN=localhost? Чи допоможе тут належна втеча? Наприклад, чи заміщення /CN=localhostна "/CN=localhost"вирішення проблеми чистим способом?
vog

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.
користувач169771

1
Tks, прекрасно працює , щоб створити власний підписаний сертифікат на 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


1
Він працював для мене після видалення останнього параметра -extensions 'v3_req', який викликав помилку. Використання OpenSSL для Windows. Нарешті, мені вдається виправити це питання! Дякую.
CGodo

1
@Kyopaxa ви праві - цей параметр є зайвим у рядку 3 файлу cnf; оновлено.
римо

2
Суцільний шлях. Дякую. Я б запропонував додати -sha256.
cherouvim

5
Тепер ви можете вказати SAN в командному рядку, -extension 'subjectAltName = DNS:dom.ain, DNS:oth.er'див. Github.com/openssl/openssl/pull/4986
Alexandre DuBreuil

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-2 не додає жодної безпеки до самопідписаного сертифіката. Але я все ж рекомендую використовувати це як гарну звичку не використовувати застарілі / небезпечні криптографічні хеш-функції. Повне пояснення доступне в розділі Чому доцільно, щоб сертифікати, що надходять до сертифікату кінцевої особи, засновані на 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
Saqib Omer

Я досі не впевнений, як CN впливає на загальну настройку? Я намагаюся запустити це як localhostабо 127.0.0.1:port#що було б відповідним CNдля чогось подібного.
DJ2

@ DJ2 Я б встановив BASE_DOMAIN = "localhost"
Дрейкс

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 файл, який містить і приватний ключ, і cert. Ви можете перемістити їх у окремі .pem файли, якщо це потрібно.


2
Для користувачів Linux вам потрібно буде змінити цей конфігурацію. наприклад, на поточних /etc/ssl/openssl.confроботах Ubuntu
скорочення

Для однострочнікі , який не вимагає від вас , щоб вказати місце розташування openssl.cnf, см: stackoverflow.com/a/41366949/19163
ВОГ

7

Я не можу коментувати, тому я додаю окрему відповідь. Я спробував створити самопідписаний сертифікат для NGINX, і це було легко, але коли я хотів додати його до білого списку Chrome, у мене виникла проблема. І моє рішення полягало в тому, щоб створити сертифікат Root і підписати довідку про нього.

Тож крок за кроком. Створіть файл config_ssl_ca.cnf Зауважте, що у файлі config є опція 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 - Запит на підпис сертифіката. Тому що ідея полягає в тому, щоб підписати сертифікат дитини під корінь і отримати правильний сертифікат

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

Ви можете запитати, чому так важко, чому ми повинні створити ще один конфігурацію для підписання довідкового сертифіката під корінь. Відповідь проста, тому що в довідці про дітей повинен бути блок SAN - Альтернативні імена предмета. Якщо ми підпишемо довідковий сертифікат утилітами "openssl x509", сертифікат Root видалить поле 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 

2
Хоча цей процес виглядає складним, саме для цього потрібен домен .dev, оскільки цей домен не підтримує самопідписані сертифікати, а Chrome і Firefox змушують HSTS. Я зробив наступні дії: це створення сертифіката, створення сертифіката і підписання його з моїм ЦА і, нарешті, довіра мого КА в браузері. Дякую.
bajicdusko

1
Ви, пане, проклята легенда. Моя домашня лабораторія дякую тобі!
антоун

6

У вас загальна процедура правильна. Синтаксис команди знаходиться нижче.

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

Однак попередження відображаються, оскільки веб-переглядач не зміг перевірити ідентифікацію, перевіривши сертифікат відомим органом сертифікації (CA).

Оскільки це самопідписаний сертифікат, немає ЦА, і ви можете сміливо ігнорувати попередження та продовжувати. Якщо ви хочете отримати реальний сертифікат, який буде впізнаваний будь-хто в загальнодоступному Інтернеті, то процедура нижче.

  1. Створіть приватний ключ
  2. Використовуйте цей приватний ключ, щоб створити файл CSR
  3. Подайте КСВ до ЦС (Verisign або інші тощо)
  4. Встановіть отриманий сертифікат від CA на веб-сервері
  5. Додайте інші certs до ланцюжка аутентифікації залежно від типу cert

Докладніше про це я маю у публікації в розділі Забезпечення зв'язку: Створення сертифіката безпеки з OpenSSL


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"

Ця єдина команда містить усі відповіді, які ви зазвичай надаєте для деталей сертифіката. Таким чином ви можете встановити параметри і запустити команду, отримати результат - тоді йдіть на каву.

>> Більше тут <<


1
Усі аргументи, за винятком SANs… @ 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"))

Редагувати: додано попередній Slash до параметра "subj" для Ubuntu.


3

Створення ключів

Я використовую /etc/mysqlдля зберігання cert, оскільки /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 може бути відмовлено в доступі до читання до вашого файла сертифікатів, якщо він не в конфігурації програми . Як було зазначено в попередніх кроках ^, збережіть усі наші сертифікати у вигляді .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 для підключення конкретного користувача ('вимагає ssl'):

    • SSL

    Показує серверу дозволяти для облікового запису тільки з'єднання, зашифровані SSL.

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

    Для підключення клієнт повинен вказати параметр --ssl-ca для автентифікації сертифіката сервера, а також може додатково вказати параметри --ssl-ключ та --ssl-cert. Якщо не вказано ні параметр --ssl-ca, ні --ssl-capath, клієнт не підтверджує сертифікат сервера.


Альтернативне посилання: Тривалий підручник із захищених підключень PHP до MySQL з SSL .


-1; це значною мірою дотичне до поставленого питання, а також робить погану роботу, щоб зрозуміти, звідки беруться його цитати.
Марк Амері

Це показує резервування сертифікатів CA, сервер / клієнт, підписані ЦА, налаштування їх для читання mysqld на хості з apparmor. Це ілюструє досить марний випадок розміщення ca, сервера та клієнта на одній машині та небезпечно піддавати повноваження цього ca процедурі mysqld. Ця настройка насправді не має сенсу, крім тестування конфігурації ssl у тестовому середовищі. Для роботи з внутрішньою службою CA я рекомендую ланцюжок інструментів gnuttls над openssl help.ubuntu.com/community/GnuTLS та добре розумію tls перед тим, як працювати над справою mysqld + apparmor
ThorSummoner

3

Як було детально обговорено, сертифікати, що підписуються самостійно , не довіряються Інтернету . Ви можете додати свій самопідписаний сертифікат у багатьох браузерах, але не у всіх . Крім того, ви можете стати власним органом сертифікації .

Основна причина, за якою хтось не хоче отримати підписаний сертифікат від сертифікаційного органу, - це вартість Symantec від 995 до 999 доларів США на рік за сертифікати - лише за сертифікат, призначений для внутрішньої мережі, Symantec стягує 399 доларів на рік . Цю вартість легко виправдати, якщо ви обробляєте платежі кредитною карткою або працюєте в центрі прибутку високоприбуткової компанії. Більше, ніж багато хто може дозволити собі особистий проект, який створюється в Інтернеті, або для некомерційного використання мінімального бюджету, або якщо працює в центрі витрат організації - центри завжди намагаються зробити більше з меншою.

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

Якщо ви встановите certbot, ви можете ввімкнути його для створення та підтримки сертифіката, виданого вами сертифікатом Let’s Encrypt .

Я зробив це у вихідні для своєї організації. Я встановив необхідні пакети для certbot на своєму сервері (Ubuntu 16.04), а потім запустив команду, необхідну для установки та включення certbot. Ймовірно, потрібен плагін DNS для certbot - ми зараз використовуємо 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.