OpenSSL, часть 2: Создание ключа и сертификата для веб-сервера
В данной серии публикаций предполагается, что читатель знаком с концепцией криптографических систем с открытым ключом PKI. Почитать теорию можно, например, в Википедии. Для реализации PKI будем использовать свободное ПО OpenSSL. В отличии от большинства публикаций, буду параллельно описывать процедуру сразу в 2-х вариантах PKI для криптоалгоритма RSA и ГОСТ Р 34.10-2012. Синтаксис команд не отличается для различных дистрибутивов Linux и даже для Windows, полная инструкция будет состоять из следующих частей:
- Часть 1: Создание корневого Удостоверяющего Центра (УЦ);
- Часть 2: Создание ключа и сертификата для веб-серверов [ВЫ НАХОДИТЕСЬ ЗДЕСЬ];
- Часть 3: Создание ключа и сертификата для пользователей.
Получение подписанного УЦ сертификата для веб-сервера (RSA)
Самоподписанный сертификат веб-сайта рассматривать не будем - это не актуально и отвергается большинством современных браузеров.
В качестве примера, пусть наш веб-сервер должен быть опубликован в интернете по адресу https://web1c.example.com, но из локальной сети может быть доступен как https://server3, https://web1c.local, а также для полного примера на все случаи жизни, пусть ещё и по IP https://10.0.0.10, и ещё по IPv6-адресу https://[fe80::b4c].
В норме, приватный ключ и запрос сертификата должны генерироваться на стороне запрашивающего (в нашем случае это должен делать администратор веб-сервера), а подписываться ключом УЦ со стороны администратора ИТ-безопасности. То есть это два разных человека каждый со своей зоной ответствености, поэтому получение сертификатов технически разделено на 2 этапа. При этом приватный ключ не должен покидать компьютер запрашивающего, а отправляться на подпись должен только файл-запрос.
ЭТАП 1:Генерируем приватный ключ сервера длиной 3072 бит и запрос сертификата. В OpenSSL 3.1 это можно сделать в один заход, с применением всех рекомендованных параметров для веб-сервера. Чтобы не запоминать создайте исполняемый bash-скрипт с именем gen-server-rsa.sh, выделеные поля требуется заменить на свои значения:
#!/bin/bash
openssl req -newkey rsa:3072 \
-keyform PEM \
-outform PEM \
-nodes \
-keyout ./newkey/webserver.key \
-out ./newkey/webserver.csr \
-subj "/C=RU/CN=web1c.example.com" \
-addext "basicConstraints = CA:FALSE" \
-addext "subjectKeyIdentifier = hash" \
-addext "keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment" \
-addext "extendedKeyUsage=serverAuth" \
-addext "subjectAltName = DNS:server3, DNS:web1c.local, IP:10.0.0.10, IP:fe80::b4c"
openssl req -text -noout -in ./newkey/webserver.csr
Скрипт сразу выводит на просмотр содержимое файла запроса. Проверяем в первую очередь выделенные поля:
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = RU, CN = web1c.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (3072 bit)
Modulus:
00:f3:e7:2f:1e:c2:d0:82:65:25:97:a1:42:29:6c:
...
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
09:1E:21:BD:7A:6A:51:CF:AF:F7:C2:36:DF:1B:EC:C8:03:84:38:85
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:server3, DNS:web1c.local, IP Address:10.0.0.10, IP Address:FE80:0:0:0:0:0:0:B4C
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
01:e3:83:a4:f9:33:be:ca:09:9b:f2:23:21:cd:20:37:f9:be:
...
ЭТАП 2:Администратор УЦ подписывает запрошенный сертификат на срок 365 дней следующим скриптом (назвать его можно например sign-server-rsa.sh):
#!/bin/bash
openssl x509 -req \
-in ./newkey/webserver.csr \
-CA ./ca/ca.crt \
-CAkey ./ca/ca.key \
-CAcreateserial \
-days 365 \
-out ./newkey/webserver.crt \
--copy_extensions=copyall
openssl x509 -text -in ./newkey/webserver.crt
Скрипт сразу выводит на просмотр готовый сертификат, чтобы проверить всё ли в порядке:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
73:a4:61:4b:28:5a:10:a6:12:1c:36:ae:c3:c7:d5:8c:d6:40:46:ce
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = RU, CN = Demo Root CA 2023
Validity
Not Before: Oct 17 09:44:32 2023 GMT
Not After : Oct 16 09:44:32 2024 GMT
Subject: C = RU, CN = web1c.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (3072 bit)
Modulus:
00:f3:e7:2f:1e:c2:d0:82:65:25:97:a1:42:29:6c:
...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
09:1E:21:BD:7A:6A:51:CF:AF:F7:C2:36:DF:1B:EC:C8:03:84:38:85
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:server3, DNS:web1c.local, IP Address:10.0.0.10, IP Address:FE80:0:0:0:0:0:0:B4C
X509v3 Authority Key Identifier:
73:35:64:85:FD:FF:94:DA:67:45:1A:01:C8:B9:7F:A6:47:09:93:2D
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
53:ab:67:c1:9f:78:ae:60:06:57:ce:48:05:a1:53:23:60:19:
...
Если всё правильно, отдаем файлы webserver.key и webserver.crt админу веб-сервера для настройки. Копию открытого сертификата crt складываем в папку certs - в будущем они могут пригодиться, остальное удаляем из папки newkey.
Получение подписанного УЦ сертификата для веб-сервера по ГОСТ Р 34.10-2012
ЭТАП 1:Генерируем приватный ключ ГОСТ-2012 длиной 512 с параметром подписи "С" и запрос сертификата, выделенные места изменить на свои значения:
#!/bin/bash
openssl req -engine gost \
-newkey gost2012_512 \
-pkeyopt paramset:C \
-keyform PEM \
-outform PEM \
-nodes \
-keyout ./newkey/webserver-gost.key \
-out ./newkey/webserver-gost.csr \
-subj "/C=RU/CN=web1c.example.com" \
-addext "basicConstraints = CA:FALSE" \
-addext "subjectKeyIdentifier = hash" \
-addext "keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment" \
-addext "extendedKeyUsage=serverAuth" \
-addext "subjectAltName = DNS:server3, DNS:web1c.local, IP:10.0.0.10, IP:fe80::b4c"
openssl req -text -noout -in ./newkey/webserver.csr
Скрипт сразу выводит на просмотр готовый сертификат, чтобы проверить всё ли в порядке:
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = RU, CN = web1c.example.com
Subject Public Key Info:
Public Key Algorithm: GOST R 34.10-2012 with 512 bit modulus
Public key:
X:BA7B27EA0FE124D4F1DD740905DBCD9940E4B072DB56CA5E8E345968E7B7D9C5BE01320DCE3C6BACCF36D0D2C810287DE1E0A03AEC9C3BDC6007D7E24DC67DCD
Y:F67321D08737199A810FE9E8B85254C6E3C03F73575C19011502EA61ED4871DA814FFE08DF9CC7BABBC2C68CDC2EADC78968D3ED1E555D3DF3D97E79E8E61B29
Parameter set: GOST R 34.10-2012 (512 bit) ParamSet C
Attributes:
Requested Extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
27:6B:F0:54:85:FB:4F:1F:9F:C8:78:CF:27:E4:B7:39:3C:9D:73:32
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:server3, DNS:web1c.local, IP Address:10.0.0.10, IP Address:FE80:0:0:0:0:0:0:B4C
Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)
Signature Value:
14:86:70:c7:e8:66:5a:d4:85:c8:67:70:f6:4f:fe:1d:9e:ea:
...
ЭТАП 2:Администратор УЦ ГОСТ подписывает запрошенный сертификат на срок 365 дней следующим скриптом (назвать его можно например sign-server-gost.sh):
#!/bin/bash
openssl x509 -engine gost \
-req \
-in ./newkey/webserver-gost.csr \
-CA ./ca/ca-gost.crt \
-CAkey ./ca/ca-gost.key \
-CAcreateserial \
-days 365 \
-out ./newkey/webserver-gost.crt \
--copy_extensions=copyall
openssl x509 -text -in ./newkey/webserver-gost.crt
Скрипт сразу выводит на просмотр готовый сертификат, чтобы проверить всё ли в порядке:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
2a:e7:1d:ab:e5:04:7c:7c:88:93:ca:45:ba:d5:a9:2d:fe:05:37:ed
Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)
Issuer: C = RU, CN = Demo Root CA GOST 2023
Validity
Not Before: Oct 17 11:20:12 2023 GMT
Not After : Oct 16 11:20:12 2024 GMT
Subject: C = RU, CN = web1c.example.com
Subject Public Key Info:
Public Key Algorithm: GOST R 34.10-2012 with 512 bit modulus
Public key:
X:BA7B27EA0FE124D4F1DD740905DBCD9940E4B072DB56CA5E8E345968E7B7D9C5BE01320DCE3C6BACCF36D0D2C810287DE1E0A03AEC9C3BDC6007D7E24DC67DCD
Y:F67321D08737199A810FE9E8B85254C6E3C03F73575C19011502EA61ED4871DA814FFE08DF9CC7BABBC2C68CDC2EADC78968D3ED1E555D3DF3D97E79E8E61B29
Parameter set: GOST R 34.10-2012 (512 bit) ParamSet C
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
27:6B:F0:54:85:FB:4F:1F:9F:C8:78:CF:27:E4:B7:39:3C:9D:73:32
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:server3, DNS:web1c.local, IP Address:10.0.0.10, IP Address:FE80:0:0:0:0:0:0:B4C
X509v3 Authority Key Identifier:
9B:52:17:C3:F1:CE:11:08:03:B3:0D:F1:02:E9:C7:59:C0:97:17:72
Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)
Signature Value:
0c:30:82:1e:1c:81:ce:cb:33:44:d1:f5:ce:5a:08:b0:0d:be:
...
Если всё правильно, отдаем файлы webserver-gost.key и webserver-gost.crt админу веб-сервера для настройки, и надеемся, что он знает что с ними делать 😇