воскресенье, 11 декабря 2016 г.

Создание корневой пары

Перевод: Create the root pair
Автор: Джэми Нгуен (Jamie Nguyen)

Работа в качестве удостоверяющего центра (CA) подразумевает использование криптографических пар приватных ключей и публичных сертификатов. Самая первая криптографическая пара, которую мы создадим - это корневая пара. Она состоит из корневого ключа (ca.key.pem) и корневого сертификата (ca.cert.pem). Эта пара образует удостоверение удостоверяющего центра.

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

Замечание. Лучшей практикой считается создание корневой пары в безопасной среде. Лучше всего, если это будет полностью зашифрованный компьютер, постоянно отключенный от Интернета. Лучше даже изъять из него беспроводные карты и залить клеем Ethernet-порты.
Подготовка каталога

Выберем каталог (/root/ca) для хранения всех ключей и сертификатов.
# mkdir /root/ca
Создадим структуру каталогов. Файлы index.txt и serial выступают в роли плоской базы данных для отслеживания подписанных сертификатов.
# cd /root/ca
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
Подготовка файла конфигурации

Нужно создать файл конфигурации, который будет использоваться OpenSSL. Скопируем файл конфигурации корневого удостоверяющего центра из Приложения А в файл /root/ca/openssl.cnf.

Раздел [ca] обязателен. Здесь мы сообщаем OpenSSL, что нужно использовать опции из раздела [CA_default].
[ca]
# `man ca`
default_ca = CA_default
Раздел [CA_default] содержит набор значений по умолчанию. Убедитесь, что указан выбранный ранее каталог (/root/ca).
[CA_default]
# Местонахождение каталогов и файлов
dir              = /root/ca
certs            = $dir/certs
crl_dir          = $dir/crl
new_certs_dir    = $dir/newcerts
database         = $dir/index.txt
serial           = $dir/serial
RANDFILE         = $dir/private/.rand

# Корневой ключ и корневой сертификат
private_key      = $dir/private/ca.key.pem
certificate      = $dir/certs/ca.cert.pem

# Настройки списков отозванных сертификатов
crlnumber        = $dir/crlnumber
crl              = $dir/crl/ca.crl.pem
crl_extensions   = crl_ext
default_crl_days = 30

# SHA-1 устарел, поэтому используем вместо него SHA-2
default_md       = sha256

name_opt         = ca_default
cert_opt         = ca_default
default_days     = 375
preserve         = no
policy           = policy_strict
Мы применим строгую политику policy_strict для всех подписей корневого удостоверяющего центра, потому что корневой удостоверяющий центр используется только для создания промежуточных удостоверяющих центров.
[policy_strict]
# Корневой удостоверяющий центр должен подписывать только соответствующие промежуточные сертификаты
# Обратитесь к разделу ФОРМАТ ПОЛИТИКИ из `man ca`
countryName            = match
stateOrProvinceName    = match
organizationName       = match
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional
Мы применим свободную политику policy_loose для всех подписей промежуточных удостоверяющих центров, потому что промежуточные удостоверяющие центры подписывают сертификаты серверов и клиентов, которые могут поступать от разнообразных сторонних лиц.
[policy_loose]
# Разрешим промежуточному удостоверяющему центру подписывать более широкий диапазон сертификатов
# Обратитесь к разделу ФОРМАТ ПОЛИТИКИ из `man ca`
countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional
Опции из раздела [req] применяются при создании сертификатов или запросов на подпись сертификата.
[req]
# Опции утилиты `req` (`man req`)
default_bits       = 2048
distinguished_name = req_distinguished_name
string_mask        = utf8only

# SHA-1 устарел, поэтому используем вместо него SHA-2
default_md         = sha256

# Расширения, добавляемые при использовании опции -x509
x509_extensions    = v3_ca
Раздел [req_distinguished_name] объявляет информацию обычно требуемую в запросе на подпись сертификата. Можно указать дополнительные значения по умолчанию.
[req_distinguished_name]
# Обратитесь к https://en.wikipedia.org/wiki/Certificate_signing_request
countryName                     = Название страны (двухбуквенный код)
stateOrProvinceName             = Название штата или провинции
localityName                    = Название местности
0.organizationName              = Название организации
organizationalUnitName          = Название подразделения организации
commonName                      = Общее имя
emailAddress                    = Адрес электронной почты

# На выбор, можно указать несколько значений по умолчанию
countryName_default             = GB
stateOrProvinceName_default     = England
localityName_default            =
0.organizationName_default      = Alice Ltd
#organizationalUnitName_default =
#emailAddress_default           =
Следующие несколько разделов - это расширения, которые могут быть применены при подписывании сертификатов. Например, передача аргумента командной строки -extensions v3_ca применит опции из набора в разделе [v3_ca].

При создании корневого сертификата применим расширение v3_ca.
[v3_ca]
# Расширения для типичного удостоверяющего центра (`man x509v3_config`)
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical, CA:true
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign
При создании промежуточного сертификата применим расширение v3_ca_intermediate. pathlen:0 гарантирует, что у промежуточного удостоверяющего центра не будет дочерних промежуточных удостоверяющих центров.
[v3_intermediate_ca]
# Расширения для типичного промежуточного удостоверяющего центра (`man x509v3_config`)
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical, CA:true, pathlen:0
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign
Расширение usr_cert будем применять при подписании клиентских сертификатов, которые будут использоваться для аутентификации удалённых пользователей.
[usr_cert]
# Расширения для клиентских сертификатов (`man x509v3_config`)
basicConstraints       = CA:FALSE
nsCertType             = client, email
nsComment              = "Сертификат клиента создан OpenSSL"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
keyUsage               = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage       = clientAuth, emailProtection
Применим расширение server_cert при подписании сертификатов серверов, например, используемых веб-серверами.
[server_cert]
# Расширения для сертификатов серверов (`man x509v3_config`)
basicConstraints       = CA:FALSE
nsCertType             = server
nsComment              = "Сертификат сервера создан OpenSSL"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage               = critical, digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth
Расширение crl_ext применяется автоматически при создании списков отозванных сертификатов.
[crl_ext]
# Расширение для списков отозванных сертификатов (`man x509v3_config`)
authorityKeyIdentifier = keyid:always
Применим расширение ocsp при подписании сертификата для протокола интерактивного статуса сертификата (Online Certificate Status Protocol - OCSP).
[ocsp]
# Расширение для подписи сертификатов OCSP (`man ocsp`)
basicConstraints       = CA:FALSE
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
keyUsage               = critical, digitalSignature
extendedKeyUsage       = critical, OCSPSigning
Создание корневого ключа

Создадим корневой ключ (ca.key.pem) и сохраним его в полной безопасности. Злоумышленник, заполучивший корневой ключ, сможет выпускать доверенные сертификаты. Зашифруйте корневой ключ при помощи 256-битного шифрования AES и сильного пароля.
Замечание. Используйте 4096 бит для всех корневых и промежуточных ключей удостоверяющих центров. Вы по-прежнему сможете подписывать сертификаты серверов и клиентов более короткой длины.
# cd /root/ca
# openssl genrsa -aes256 -out private/ca.key.pem 4096
Enter pass phrase for ca.key.pem: secretpassword             # Введите ключевую фразу для ca.key.pem: секретныйпароль
Verifying - Enter pass phrase for ca.key.pem: secretpassword # Проверка - Введите ключевую фразу для ca.key.pem: секретныйпароль
# chmod 400 private/ca.key.pem
Создание корневого сертификата

Воспользуемся корневым ключом (ca.key.pem) для создания корневого сертификата (ca.cert.pem). Примем срок действия корневого сертификата достаточно длинным, например - двенадцать лет. По истечении срока действия корневого сертификата все сертификаты, подписанные этим удостоверяющим центром, станут недействительными.
Предупреждение! При каждом использовании утилиты req нужно указывать используемый файл конфигурации с помощью опции -config, в противном случае OpenSSL будет использовать файл по умолчанию /etc/pki/tls/openssl.cnf.
# cd /root/ca
# openssl req -config openssl.cnf \
  -key private/ca.key.pem \
  -new -x509 -days 7300 -sha256 -extensions v3_ca \
  -out certs/ca.cert.pem
Enter pass phrase for ca.key.pem: secretpassword                         # Введите ключевую фразу для ca.key.pem: секретныйпароль
You are about to be asked to enter information that will be incorporated # У вас будет запрошена информация, которая будет вставлена
into your certificate request.                                           # в ваш запрос сертификата.
-----
Country Name (2 letter code) [XX]:GB                                     # Название страны (двухбуквенный код) [XX]:GB
State or Province Name []:England                                        # Название штата или провинции []:Англия
Locality Name []:                                                        # Название местности []:
Organization Name []:Alice Ltd                                           # Название организации []:ООО Алиса
Organizational Unit Name []:Alice Ltd Certificate Authority              # Название подразделения []:Удостоверяющий центр ООО Алиса
Common Name []:Alice Ltd Root CA                                         # Общее имя []:Корневой удостоверяющий центр ООО Алиса
Email Address []:                                                        # Адрес электронной почты []:
# chmod 444 certs/ca.cert.pem
Проверка корневого сертификата
# openssl x509 -noout -text -in certs/ca.cert.pem
В выводе будут отображены:
  • используемый алгоритм подписания,
  • даты действия сертификата,
  • битовая длина публичного ключа,
  • эмитент, который подписал этот сертификат,
  • субъект, который относится к этому сертификату.
Эмитент и субъект идентичны в случае самозаверенного сертификата. Отметим, что все корневые сертификаты являются самозаверенными.
Signature Algorithm: sha256WithRSAEncryption                  # Алгоритм подписания: sha256WithRSAEncryption
    Issuer: C=GB, ST=England,                                 #     Эмитент: C=GB, ST=Англия,
            O=Alice Ltd, OU=Alice Ltd Certificate Authority,  #              O=ООО Алиса, OU=Удостоверяющий центр ООО Алиса,
            CN=Alice Ltd Root CA                              #              CN=Корневой удостоверяющий центр ООО Алиса
    Validity                                                  #     Действительность
        Not Before: Apr 11 12:22:58 2015 GMT                  #         Не ранее: 11 апреля 2015 года в 12:22:58 по Гринвичу
        Not After : Apr 6 12:22:58 2035 GMT                   #         Не позднее: 6 апреля 2035 года 12:22:58 по Гринвичу
    Subject: C=GB, ST=England,                                #     Субъект: C=GB, ST=Англия,
             O=Alice Ltd, OU=Alice Ltd Certificate Authority, #              O=ООО Алиса, OU=Удостоверяющий центр ООО Алиса,
             CN=Alice Ltd Root CA                             #              CN=Корневой удостоверяющий центр ООО Алиса
    Subject Public Key Info:                                  #     Информация публичного ключа субъекта:
        Public Key Algorithm: rsaEncryption                   #         Алгоритм публичного ключа: rsaEncryption
            Public-Key: (4096 bit)                            #             Публичный ключ: (4096 бит)
В выводе также отображаются расширения X509v3. Мы применили расширение v3_ca, поэтому в выводе должны отобразиться опции из [v3_ca].
X509v3 extensions:                                    # Расширения X509v3:
    X509v3 Subject Key Identifier:                    #     Идентификатор ключа субъекта X509v3:
        38:58:29:2F:6B:57:79:4F:39:FD:32:35:60:74:92:60:6E:E8:2A:31
    X509v3 Authority Key Identifier:                  #     Идентификатор ключа подлинности X509v3:
        keyid:38:58:29:2F:6B:57:79:4F:39:FD:32:35:60:74:92:60:6E:E8:2A:31

    X509v3 Basic Constraints: critical                #     Базовые ограничения X509v3: критично
        CA:TRUE
    X509v3 Key Usage: critical                        #     Использование ключа X509v3: критичное
        Digital Signature, Certificate Sign, CRL Sign #         Цифровая подпись, подписание сертификата, подписание списка отозванных сертификатов

8 комментариев:

Дмитрий комментирует...

Доброго времени суток.
Можете подсказать, будут ли работать сертификаты для базы данных mysql или это только для HTTPS?

morbo комментирует...

Дмитрий, будут работать. В MySQL используются сертификаты в формате PEM. Большинство веб-серверов тоже используют этот формат.

Дмитрий комментирует...

Вот что интересно. Сделал, все как тут написано. В ответ получаю ошибку ERROR 2026 (HY000): SSL connection error: error:00000000:lib(0):func(0):reason(0).

morbo комментирует...

Да, это действительно интересно. Но в этой статье нет ни слова про настройку SSL в MySQL. Здесь рассматривается настройка корневого сертификата удостоверяющего центра. Создание сертификатов серверов рассматривается в одной из следующих статей. Возможно вам не нужен удостоверяющий центр, а нужна статья про настройку SSL в MySQL? Тогда посмотрите куда-нибудь сюда:
http://cyber01.ru/manuals/rabota-mysql-s-ssl/
https://habrahabr.ru/post/104412/

Дмитрий комментирует...

Меня интересует только один вопрос. Собственно ища ответ на него, попал на оригинал этой статьи, потом попал на вашу статью. А, вопрос заключается в следующем. Как мне организовать CRL на Mysql, таким образом, чтобы когда я добавляю в список CRL скомпрометированный сертификат, чтобы по этому сертификату нельзя было подключиться к серверу, как локально так и с других машин?
У меня получается создать сертификаты, создать CRL.pem в который я добавляют удаленные сертификаты и когда находясь на этом же компе, где локально лежит этот файл(crl.pem) я не могу подключиться к БД, что очень хорошо. Но, стоит взять этот удаленный сертификат и подключиться с ним с другой машины, где не будет crl.pem и там вообще будет только клиент БД, то подключение удается и я нахожусь внутри БД сервера. Ни, каких надстроек не делал над openssl.cnf.

morbo комментирует...

Насколько я понимаю, вы хотите отзывать сертификаты клиентов, чтобы сервер MySQL не пускал клиентов с отозванными сертификатами.

В таком случае серверу MySQL нужно указать файл, откуда он будет брать список отозванных сертификатов. Почитайте тогда материал по этой ссылке:
https://dev.mysql.com/doc/refman/5.7/en/secure-connection-options.html

Там упоминаются такие вот опции:
--ssl-crl Path of file that contains certificate revocation lists
--ssl-crlpath Path of directory that contains certificate revocation list files

Насколько я понимаю, эти же опции можно указать и в файле /etc/mysql/my.cnf, записав их таким вот образом:
ssl-crl=
ssl-crlpath=

На стороне клиента можно проверять, был ли отозван сертификат сервера. Не думаю, что вам нужно именно это. С этим уже сложнее - по идее сам клиент должен скачивать список отозванных сертификатов по протоколу HTTP по той ссылке, которая указана в самом сертификате сервера. Но, возможно, для этого нужно использовать те же опции --ssl-crl или --ssl-crlpath клиенту mysql. Сам я SSL в MySQL не настраивал, поэтому уверенно подсказать что и как нужно делать не смогу.

Дмитрий комментирует...

Спасибо. Вы все верно сказал. Нужно в конфиг файле my.cnf указать в
[mysqld]
...
ssl-crl=/путь/до/crl.pem
...

[mysql]
...
ssl-crl=/путь/до/crl.pem
...
И, вот этого уже будет достаточно.
Потом, я столкнулся с проблемой, которую выше озвучил.
И, понял, что для того, чтобы другие подключаясь по старым(отозванным) сертификатам не могли попасть в БД, нужно дописать в файл конфиг. openssl.cnf
crlDistributionPoints = URI:http://domen.ru/crl.pem
и если потом просмотреть, содержимое файла с сертификатом, то будет виден это адрес. Но, видимо нужно еще, что-то прописать в конфиге Openssl.cnf или еще где, чтобы все это заработало. Я так и не разобрался в этом.
Ну, да ладно, спасибо, что выделили время на меня.

morbo комментирует...

Вот тут описывается такая же ошибка, как у вас: https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html

Пишут, что у сертификатов клиента, сервера и удостоверяющего центра должны отличаться друг от друга значения в полях Common Name.

От себя добавлю, что у клиентского сертификата и у сертификата удостоверяющего центра там может быть любое имя, а у серверного сертификата там должно быть доменное имя сервера. Клиенту MySQL нужно для подключения указывать имя сервера, тогда он из него через DNS узнает IP-адрес, подключится к этому IP-адресу и получит от сервера сертификат. Если в сертификате указано именно это доменное имя сервера, которое использовалось для подключения, и в остальном сертификат годный (подписан удостоверяющим центром, который известен клиенту и все сертификаты в цепочке годны по сроку действия), то подключение должно установиться.