Cert chain: What’s My Chain Cert?
Дёргаем цепочку сертификатов / Хабр
Вчера, видимо, был шабаш https и клиенты стали массово слать сертификаты. Разумеется ни корневых ни промежуточных не прилагалось и просьба их выслать вызывала такое же недоумение как встречный поток у блондинки на дороге с односторонним движением.
На 4-м сертификате дёргать их вручную стало лень (а я ленив по натуре), поэтому набросал «самокат» выцепляющий издателя и формирующий chain-файл для скармливания nginx’у.
Наверняка он не идеален и проверен лишь на полуторадесятках сертификатов, но чем богаты.
Об устройстве x.509 много сказано (в том числе на хабре), поэтому повторяться не буду.
Ниже просто пошаговая инструкция получения цепочки вперемешку с небольшой выжимкой из теории и не более того.
Всё нижесказанное актуально для:
Скрытый текст
$ uname -or
FreeBSD 10.3-STABLE
$ openssl version
OpenSSL 1.0.2h 3 May 2016
$ `echo $SHELL` --version
tcsh 6.18.01 (Astron) 2012-02-14 (x86_64-amd-FreeBSD) options wide,nls,dl,al,kan,sm,rh,color,filec
$ /usr/local/bin/bash --version
GNU bash, version 4.3.25(1)-release (amd64-portbld-freebsd10.0)
Итак, предположим, что у нас есть PEM-сертификат сайта. Для примера мы возьмём сертфикат ya.ru (не только ж пинговать его).
$ echo | openssl s_client -connect ya.ru:443 | openssl x509 -certopt ca_default -out ya.pem -outform PEM
Помимо самого кодированного запроса, версии, подписи и т.п. в нём имеется ряд расширений. Одно из которых Authority Information Access нас и интересует:
$ openssl x509 -in ./ya.pem -noout -text | grep 'Authority Information Access' -A 2
Authority Information Access:
OCSP - URI:http://yandex.ocsp-responder.com
CA Issuers - URI:http://repository.certum.pl/ycasha2.cer
Параметр CA Issuers как раз и содержит следующий в цепочке сертификат. Как правило, данный сертификат либо в PEM, либо в DER(как в нашем случае) форматах.
$ fetch http://repository.certum.pl/ycasha2.cer
На деле PEM формат не более чем base64 представление DER и получить PEM из DER можно сделав base64 ./ycasha2.cer ./ycasha2.pem и обрамив кодированный текст «——BEGIN CERTIFICATE——«,»——END CERTIFICATE——«. Однако, логичнее и проще сделать это преобразование средствами openssl:
$ openssl x509 -inform der -in ./ycasha2.cer -out ./ycasha2.pem
Едем дальше и смотрим следующий сертификат в цепочке:
$ openssl x509 -in ./ycasha2.pem -noout -text | grep 'Authority Information Access' -A 2
Authority Information Access:
OCSP - URI:http://subca.ocsp-certum.com
CA Issuers - URI:http://repository.certum.pl/ctnca.cer
$ fetch http://repository.certum.pl/ctnca.cer
Преобразовываем и его:
$ openssl x509 -inform der -in ./ctnca.cer -out ./ctnca.pem
В данном сертификате (т.к. он корневой) отсутствует расширение Authority Information Access:
$ openssl x509 -in ./ctnca.pem -noout -text | grep 'X509v3 extensions' -A 6
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
08:76:CD:CB:07:FF:24:F6:C5:CD:ED:BB:90:BC:E2:84:37:46:75:F7
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
То есть на нём и закончим вытягивание цепочки. Осталось собрать это всё в chain-файл:
$ cat ya.pem ycasha2.pem ctnca.pem > chain0.pem
Вроде бы теперь можно ставить (если есть Private Key), но остановлюсь ещё на паре нюансов.
Установив свой сертификат на свой Яндекс проверяем его:
$ echo | openssl s_client -connect ya.ru:443 | grep Verify
Verify return code: 0 (ok)
Всё хорошо, но это лишь потому, что в дефолтных путях -CApath, -CAfile моего openssl нашлись нужные хеши сертификатов. Если мы их изменим, либо по дефолтным путям их нет, либо они просто устарели, либо у кого-то версия openssl с багом, в которой не «цеплялись» default CApath (если не ошибаюсь с 1.0.1с по 1.0.1e), то получим неприятность в виде:
$ echo | openssl s_client -connect ya.ru:443 -CApath . | grep Verify
Verify return code: 20 (unable to get local issuer certificate)
Понятно, что корневой сертификат подписать некому, поэтому нужно нашей системе разрешить доверять ему. Для этого можно создать кусочек хранилища. При поиске требуемого сертифката openssl пытается отыскать его по хешу сертификата.
$ openssl x509 -noout -hash -in ./ctnca.pem
48bec511
$ ln -s `pwd`/ctnca.pem `pwd`/48bec511.0
И теперь наша система доверяет ya.ru:
$ echo | openssl s_client -connect ya.ru:443 -CApath . | grep Verify
DONE
Verify return code: 0 (ok)
Разумеется делать руками каждый раз лень, потому слегка автоматизируем:$ cat ./issuers.sh
#!/usr/local/bin/bash
cmd_grep='/usr/bin/grep '
cmd_openssl='/usr/bin/openssl '
cmd_cut='/usr/bin/cut '
cmd_fetch='/usr/bin/fetch '
tmp_der='tmp.der'
tmp_cert='tmp.cert'
#------------------------------------------------------------------------------
usage () {
#printf "function ${FUNCNAME}\n"
printf "Error!\nUsage:\t\"$0 certificate.pem\"\n"
exit 1
}
#------------------------------------------------------------------------------
if [ "X$1" = "X" ]
then
usage
else
cp $1 $tmp_cert
chain_cert="chain.pem"
fi
i=0
while :
do
issuer=`$cmd_openssl x509 -in $tmp_cert -noout -text | $cmd_grep 'CA Issuers' | $cmd_cut -d : -f 2,3`
if [ "X$issuer" != "X" ]
then
echo $i
echo $issuer
tmp_pem=$1$i.pem
$cmd_fetch $issuer --output=$tmp_der
is_pem=`$cmd_grep -c CERTIFICATE $tmp_der`
printf "IS PEM:\t[$is_pem]\n"
#echo "$tmp_der -> $tmp_pem"
if [ $is_pem -ne 0 ]
then
echo "PEM($tmp_der) -> PEM($tmp_pem)"
cp -f $tmp_der $tmp_pem
else
echo "DER($tmp_der) -> PEM($tmp_pem)"
echo "$cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem"
$cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem
fi
cp $tmp_pem $tmp_cert
let "i+=1"
#sleep 2
else
break
fi
done
if [ $i -gt 0 ]
then
echo "cat ./$1* > $chain_cert"
cat ./$1* > $chain_cert
printf "Certificate chain:\n"
ls -l $chain_cert
#ls | grep -Ev ^ya.pem$ | xargs rm
fi
Выполняем:
$ ./issuers.sh ./ya.pem
0
http://repository.certum.pl/ycasha2.cer
tmp.der 100% of 1196 B 16 MBps 00m00s
IS PEM: [0]
DER(tmp.der) -> PEM(./ya.pem0.pem)
/usr/bin/openssl x509 -inform der -in tmp.der -out ./ya.pem0.pem
1
http://repository.certum.pl/ctnca.cer
tmp.der 100% of 959 B 13 MBps 00m00s
IS PEM: [0]
DER(tmp.der) -> PEM(./ya.pem1.pem)
/usr/bin/openssl x509 -inform der -in tmp.der -out ./ya.pem1.pem
cat ././ya.pem* > chain.pem
Certificate chain:
-rw-r--r-- 1 root wheel 5842 Jun 30 15:46 chain.pem
Сверяем показания:
$ md5 chain0.pem ; md5 chain.pem
MD5 (chain0.pem) = 6d32b0798d48d14764cd26cc4f730444
MD5 (chain.pem) = 6d32b0798d48d14764cd26cc4f730444
Как-то так… Разумеется скрипт не универсален, всё на скорую руку в предверии грандиозного шухера. Комментарии/пожелания приветствуются, но отвечать вряд ли смогу — у нас тут (в Беларуси) дурдом деноминация.
Python, PostgreSQL, JavaScript, Linux, Git e t.c.
Для написания тестов на валидность загружаемых сертификатов мне потребовалось создать несколько вариантов
цепочек и приватных ключей. Прошерстив некоторый объем интернета, я собрал всю необходимую информацию о том,
как локально сгенерировать корректную цепочку SSL сертификатов, которая будет проходить проверку стандартными
средствами.
Чтобы не писать кучу команд всякий раз, напишем bash-скрипт. Для начала, зададим несколько настроечных констант:
CSR_FILE="csrfile.csr"
KEY_BITS=2048
CONF_DIR="conf"
CHAIN_CRT="ca_chain.crt"
Затем пара функций для подготовки и последующей подчистки каталога с настройками:
function clean {
find conf -not -name '*.cnf' -type f -delete
rm -f $CSR_FILE $CHAIN_CRT
}
function prepare {
clean
echo 1000 > "$CONF_DIR/root_serial"
cp /dev/null "$CONF_DIR/root_index.txt"
echo 2000 > "$CONF_DIR/im_serial"
cp /dev/null "$CONF_DIR/im_index.txt"
}
prepare
Все готово к созданию фальшивой, но технически корректной пары корневой сертификат / приватный ключ:
ROOT_URL="mycorp.com"
ROOT_ORG="MYCORP"
ROOT_CNF="$CONF_DIR/root_openssl.cnf"
ROOT_CRT="root.crt"
ROOT_KEY="root.key"
ROOT_EXP=5000
ROOT_SUB="/C=RU/ST=Moscow/L=Moscow/O=$ROOT_ORG/CN=$ROOT_URL"
# Generate root key
openssl genrsa -out $ROOT_KEY $KEY_BITS
# Generate root certificate
openssl req -config $ROOT_CNF -new -x509 -sha256 -extensions v3_ca \
-key $ROOT_KEY -out $ROOT_CRT -days $ROOT_EXP -subj $ROOT_SUB
# Verify root certificate
openssl x509 -noout -text -in $ROOT_CRT
Хорошо, теперь создадим промежуточный сертификат с ключом:
IM_CRT="intermediate.crt"
IM_KEY="intermediate.key"
IM_CNF="$CONF_DIR/im_openssl.cnf"
IM_EXP=4000
IM_SUB="/C=RU/ST=Moscow/L=Moscow/O=${ROOT_ORG}/CN=department.${ROOT_URL}"
# Generate intermediate key
openssl genrsa -out $IM_KEY $KEY_BITS
# Generate intermediate request
openssl req -config $IM_CNF -new -key $IM_KEY -out $CSR_FILE -subj $IM_SUB
# Generate intermediate certificate
openssl ca \
-config $ROOT_CNF -batch \
-extensions v3_intermediate_ca -notext -md sha256 \
-days $IM_EXP -in $CSR_FILE -out $IM_CRT
# Verify intermediate certificate
openssl x509 -noout -text -in $IM_CRT
openssl verify -CAfile $ROOT_CRT $IM_CRT
Обратите внимание, что команда на создание промежуточного сертификата берет конфигурацию
корневого ($ROOT_CNF
), т.е. подписывать будем им. Также важно, чтобы срок подписываемого
был меньше срока подписывающего.
Ну а теперь, собственно, итог:
SERVER_CRT="server.crt"
SERVER_KEY="server.key"
SERVER_EXP=365
SERVER_SUB="/C=RU/ST=Moscow/L=Moscow/O=MYSERVER/CN=myserver.com"
# Generate key
openssl genrsa -out $SERVER_KEY $KEY_BITS
# Generate request
openssl req \
-config $IM_CNF -key $SERVER_KEY -new -sha256 \
-out $CSR_FILE -subj $SERVER_SUB
# Generate certificate
openssl ca \
-batch \
-config $IM_CNF -days $SERVER_EXP \
-extensions server_cert \
-notext -md sha256 \
-in $CSR_FILE -out $SERVER_CRT
# Verify certificate
cat $IM_CRT $ROOT_CRT > $CHAIN_CRT
openssl verify -CAfile $CHAIN_CRT $SERVER_CRT
Обратите внимение, что проверка осуществляется с указанием не только промежуточного,
но всех CA-сертификатов, предварительно собранных в один файл ($CHAIN_CRT
).
И файл запроса, и сертификат создаются с использованием конфигурации промежуточного сертификата.
Темным пятном тут осталось содержимое файлов конфигурации. Они очень похожи на стандартные конфигурации
openssl
, за исключением нескольких параметров, касающихся путей размещения служебных файлов и сертификатов для подписи.
Вот эти параметры:
[ CA_default ]
dir = conf
certs = $dir
crl_dir = $dir
new_certs_dir = $dir
Для корневого:
database = $dir/root_index.txt
serial = $dir/root_serial
private_key = $dir/../root.key
certificate = $dir/../root.crt
Для промежуточного:
database = $dir/im_index.txt
serial = $dir/im_serial
private_key = $dir/../intermediate.key
certificate = $dir/../intermediate.crt
Строго говоря, проверка корректности уже была произведена в процессе создания.
Но так как мне нужно было делать это в Python, я использовал
библиотеку pyOpenSSL, а именно
модуль crypto. Для примера покажу, как это можно сделать без затей:
from OpenSSL import crypto
# Prepare X509 objects
root_cert = crypto.load_certificate(
crypto.FILETYPE_PEM, open('root.crt').read()
)
intermediate_cert = crypto.load_certificate(
crypto.FILETYPE_PEM, open('intermediate.crt').read()
)
server_cert = crypto.load_certificate(
crypto.FILETYPE_PEM, open('server.crt').read()
)
# Prepare X509 store
store = crypto.X509Store()
store.add_cert(root_cert)
store.add_cert(intermediate_cert)
# Verify
crypto.X509StoreContext(store, server_cert).verify_certificate()
Для X509Store
можно добавить
флаги проверок,
которые все сломают. К примеру, если добавить вот такой флаг, то получим исключение
OpenSSL.crypto.X509StoreContextError
:
store.set_flags
Шпоры по сертификатам X.509 / Хабр
Чудище обло, озорно, огромно, стозевно и лаяй.
Набор технологий, который мы по привычке именуем сертификатами SSL, представляет из себя здоровенный айсберг, на вершине которого зеленый замочек слева от доменного имени в адресной строке вашего браузера. Правильное название X.509 сертификат
, который восходит к X.500
стандарту ITU-T DAP (Directory Access Protocol)
. DAP не взлетел, в IETF его посчитали неудобным для использования со всеми этими OSI нагромождениями и вместо него придумали LDAP, Lightweight DAP где первая буква обозначает «легковесный». Те, кому пришлось настраивать, или что хуже производить его отладку могут оценить иронию в полной мере. Никогда еще первая буква аббревиатуры так не лгала, не считая SNMP.
Кстати что общего между LDAP, SNMP и X.509 ну кроме того, что им еще не скоро предстоит собрать стадионы фанатов? Их объединяет ASN.1 — мета-язык описания объектов древности. Если бы эти технологии создавали сейчас, в ход бы пошли XML, DTD или какой-нибудь другой ML. Но в то время стандарты создавались титанами, для которых даже SNMP был простым делом.
Словарный запас
Определение X.509 сертификатов есть в архиве ITU-T
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
Для того, чтобы досконально понять обозначения и синтаксис, придется читать спеки X.680 редакции 2008 г., где есть полное описание ASN.1. В понятиях ASN.1 SEQUENCE
обозначает примерно то же самое, что и struct
в Си. Это может сбить с толку, ведь по семантике оно должно было соответствовать скорее массиву. И тем не менее.
Стандарт X.690 определяет следующие правила кодирования структур данных, созданных в соответствии с ASN.1: BER
(Basic Encoding Rules), CER
(Canonical Encoding Rules), DER
(Distinguished Encoding Rules). Есть даже XER
(XML Encoding Rules), который на практике мне никогда не встречался.
Да, но для чего нужны сертификаты X.509, которые доставляют столько головной боли? Первая и основная функция сертификатов X.509 — служить хранилищем открытого или публичного ключа PKI (public key infrastructure). К этой функции нареканий нет, а вот со второй не все так однозначно.
Вторая функция сертификатов X.509 заключается в том, чтобы предъявитель сего был принят человеком, либо программой в качестве истинного владельца некоего цифрового актива: доменного имени, веб сайта и пр. Это получается по-разному, далеко не все сертификаты имеют высокую ликвидность, если пользоваться финансовой терминологией. Полгода назад Гугл пригрозил компании Симантек, что перестанет доверять их сертификатам из-за того, что те выпустили аж 30,000 неисправных сертификатов.
Номенклатура сертификатов
Давайте рассмотрим, какие сертификаты X.509 встречаются в природе, если рассматривать их по расположению в пищевой цепочке доверия.
- Корневые сертификаты — изготовлены в корневом УЦ (удостоверяющий центр) и имеют следующие признаки: атрибуты
issue
иsubject
идентичны, а в расширенииbasicConstraints
атрибутcA
принимает значениеTRUE
. - Промежуточные сертификаты — расплывчатый термин, обозначающий сертификаты не подписанные корневым УЦ, которые могут формировать цепочку произвольной длины, начиная от корневого сертификата и заканчивая сертификатом конечного субъекта.
- Сертификаты конечного субъекта — конечные сертификаты в цепочке, которые не могут подписывать другие промежуточные сертификаты своим закрытым ключом.
По степени крутизны дороговизны и надежности сертификаты делятся на 3 вида: DV, OV и EV.
- DV — сертификаты удостоверения доменного имени получить проще простого. Они выдаются автоматически и моментально после того, как центр сертификации проверит, что заявитель имеет право на доменное имя. Чаще всего для этого достаточно открыть сообщение и перейти по указанной ссылке. Естественно, что сообщение будет отправлено на почтовый ящик с доменным именем, которое следует удостоверить.
- OV — в сертификате будет уже указано не доменное имя, а название самой организации заявителя. Тут уже ни а какой автоматической выдачи речи быть не может, это займет несколько рабочих дней. Проверке подлежит наличие в базе
whois
домена название организации заявителя. Могут проверить государственную регистрацию и валидность телефонного номера. - EV — эти сертификаты и получить сложно и стоят они недешево. Их можно опознать по названию организации на зеленом замочке на панели адресной строки.
Редко, кто на это готов раскошелиться. Навскидку Яндекс, StackOverflow.com и Хабр могут жить и без него. Но те, кто готов пойти ради этого на жертвы должны выполнить следующие требования:
- Аудит правовой, физической и операционной деятельности организации.
- Следует убедиться в том, что организация имеет эксклюзивное право на использование доменного имени.
- Следует убедиться в том, что организация авторизована для выпуска сертификата данного типа.
Более подробно можно прочитать в Хабрапоспе компании TutHost. Также атрибут subject
X.509 EV сертификата содержит значения jurisdictionOfIncorporationCountryName
, businessCategory
, и serialNumber
.
По свои свойствам сертификаты бывают следующих типов.
- Мульти-доменные сертификаты — сертификат может охватывать несколько доменных имен с помощью
SAN
— атрибутаsubjectAltName
. - Мульти-хостовые сертификаты — в тех случаях, когда атрибут
subject
содержит записьCN=example.net
, в время как DNS сервер может иметь несколько записейA / AAAA
типа, где одно имя узла может соответствовать нескольким IP адресам. В этом случае сертификат X.509 с одним и тем жеhostname
может быть успешно восстановлен на всех подобных узлах. - Сертификаты с возможностью подстановки, wildcard сертификаты — это когда атрибут
subject
содержит записьCN=*.example.net
. Действует так же, как и в привычных регулярных выражениях, то есть может быть использован на всех под-доменах*.example.net
. - Квалифицированные сертификаты — RFC 3739 определяет этот термин, как относящийся персональным сертификатам, ссылаясь на Директиву Европейского Союза об электронной подписи. В частности RFC позволяет в атрибуте
subject
содержать значения:
В России понятие КС квалифицированного сертификата определено законодательно в связи с доступом к ГосУслугам. По ссыске Хабрапост с былиной об извлечении персональных данных из КС.
Откуда берутся сертификаты?
Еще совсем недавно было всего 2 способа заполучить X.509 сертификат, но времена меняются и с недавнего времени есть и третий путь.
- Создать свой собственный сертификат и самому же его подписать. Плюсы — это бесплатно, минусы — сертификат будет принят лишь вами и, в лучшем случае, вашей организацией.
- Приобрести сертификат в УЦ. Это будет стоить денег в зависимости от различных его характеристик и возможностей, указанных выше.
- Получить бесплатный сертификат LetsEncrypt, доступны только самые простые DV сертификаты.
Для первого сценария достаточно пары команд и чтобы 2 раза не вставать создадим сертификат с алгоритмом эллиптических кривых. Первым шагом нужно создать закрытый ключ. Считается, что шифрование с алгоритмом эллиптических кривых дает больший выхлоп, если измерять в тактах CPU, либо байтах длины ключа. Поддержка ECC не определена однозначно в TLS < 1.2.
openssl ecparam -name secp521r1 -genkey -param_enc explicit -out private-key.pem
Далее, создает CSR — запрос на подписание сертификата.
openssl req -new -sha256 -key private.key -out server.csr -days 730
И подписываем.
openssl x509 -req -sha256 -days 365 -in server.csr -signkey private.key -out public.crt
Результат можно посмотреть командой:
openssl x509 -text -noout -in public.crt
Openssl
имеет огромное количество опций и команд. Man страница не очень полезна, справочник удобнее использовать так:
openssl -help
openssl x509 -help
openssl s_client -help
Ровно то же самое можно сделать с помощью java
утилиты keytool
.
keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048
Следует серия вопросов, чтобы было чем запомнить поля owner
и issuer
What is your first and last name?
What is the name of your organizational unit?
What is the name of your organization?
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit?
Is CN=Johnnie Walker, OU=Unknown, O=Unknown, L=Moscow, ST=Moscow, C=RU correct?
Конвертируем связку ключей из проприетарного формата в PKCS12.
keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.jks -deststoretype pkcs12
Смотрим на результат:
keytool -list -v -alias selfsigned -storepass password -keystore keystore.jks
Alias name: selfsigned
Creation date: 20.01.2018
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Johnnie Walker, OU=Unknown, O=Unknown, L=Moscow, ST=Moscow, C=RU
Issuer: CN=Johnnie Walker, OU=Unknown, O=Unknown, L=Moscow, ST=Moscow, C=RU
Serial number: 1f170cb9
Valid from: Sat Jan 20 18:33:42 MSK 2018 until: Tue Jan 15 18:33:42 MSK 2019
Certificate fingerprints:
MD5: B3:E9:92:87:13:71:2D:36:60:AD:B5:1F:24:16:51:05
SHA1: 26:08:39:19:31:53:C5:43:1E:ED:2E:78:36:43:54:9B:EA:D4:EF:9A
SHA256: FD:42:C9:6D:F6:2A:F1:A3:BC:24:EA:34:DC:12:02:69:86:39:F1:FC:1B:64:07:FD:E1:02:57:64:D1:55:02:3D
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 30 95 58 E3 9E 76 1D FB 92 44 9D 95 47 94 E4 97 0.X..v...D..G...
0010: C8 1E F1 92 ....
]
]
Значению ObjectId: 2.5.29.14
соответствует определение ASN.1, согласно RFC 3280 оно всегда non-critical
. Точно так же можно узнать смысл и возможные значения других ObjectId
, которые присутствуют в сертификате X.509.
subjectKeyIdentifier EXTENSION ::= {
SYNTAX SubjectKeyIdentifier
IDENTIFIED BY id-ce-subjectKeyIdentifier
}
SubjectKeyIdentifier ::= KeyIdentifier
LetsEncrypt
Можно бесплатно получить X.509 сертификат LetsEncrypt и для этого не нужно даже заходить на вебсайт, достаточно установить certbot
.
sudo emerge -av certbot #для Gentoo
sudo apt-get install certbot -t stretch-backports #Debian
sudo dnf install certbot #Fedora
sudo certbot certonly --standalone -d example.com -d www.example.com
Сценарий №1 — найти следующего в связке
Связка сертификатов — Объединение нескольких X.509 сертификатов в один файл, чаще всего в формате PEM
. Связка передается по сети в момент протокола рукопожатия SSL/TLS.
Самый сок начинается, когда имеете дело со связкой сертификатов, a. k. a certificate chain
. Часто просматривая лапшу в связке ключей jks
непросто понять как найти родительский сертификат, когда там россыпь новых и старых сертификатов на несколько доменных имен.
Рассмотрим связку сертификатов *.novell.com
. Расширение Authority Key Identifier (AKI)
должно совпадать с Subject Key Identifier (SKI)
старшего в связке.
Certificate Authority Key Identifier
Size: 20 Bytes / 160 Bits
51 68 ff 90 af 02 07 75 3c cc d9 65 64 62 a2 12 b8 59 72 3b
Так и есть, SKI
сертификат DigiCert имеет то же значение.
Certificate Subject Key ID
Size: 20 Bytes / 160 Bits
51 68 ff 90 af 02 07 75 3c cc d9 65 64 62 a2 12 b8 59 72 3b
Для корневого сертификата AKI = SKI
, а также isCa=true
Certificate Basic Constraints
Critical
Is a Certificate Authority
Сценарий №2 — используй subjectAltnName, Люк
Вот представьте у вас приложение, использующее веб сервер: вики, WordPress или Cacti. Вы настроили доступ по https
, приобрели или сами сгенерировали и подписали сертификат. Все должно быть в порядке, но зеленого замочка все равно нет. Браузер подозревает, что сертификат готовили неправильные пчелы, из-за того, что FQDN
сервера и hostname
, который указан в адресной строке не совпадают. Так иногда бывает, что DNS сервера указывает на mars.domain.com
, а веб-сервер настроен на venus.domain.com
.
Если администратору в силу перфекционизма нужны помимо езды нужны еще и шашечки — вожделенный зеленый замочек, то нужно переделать сертификат X.509, определив в нем subjectAltName
.
Откройте файл openssl.cnf
и в секции req
добавьте следующие линии.
[ alternate_names ]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = mail.example.com
DNS.4 = ftp.example.com
Далее, в секции [ v3_ca ]
укажите.
subjectAltName = @alternate_names
А дальше все как обычно, создаем закрытый ключ и подписываем сертификат.
openssl genrsa -out private.key 3072
openssl req -new -x509 -key private.key -sha256 -out certificate.pem -days 730
Использованные материалы
Цепочка сертификатов (CA Bundle): корневой, промежуточные
Центр сертификации предоставляет не просто сертификат — на деле это цепочка сертификатов (CA Bundle), каждое звено которой работает на повышение доверия конечного пользователя.
Каждый авторитетный центр сертификации предоставляет свой корневой сертификат. В большинстве случаев он уже «вшит» в браузеры — это относится в том числе к Comodo, GeoTrust, Thawte и VeriSign, представленные на нашем сайте. Сам по себе сертификат на ваш домен не будет считаться доверенным в браузере. Его нужно связать с корневым сертификатом Центра сертификации с помощью одного или нескольких промежуточных. В этой цепочке каждый сертификат является доверенным и подписанным вышестоящим сертификатом. Для каждого типа сертификата есть свои промежуточные элементы, последовательность которых указана ниже. Скачать корневой и промежуточный сертификат (-ы) можно и на сайтах самих центров. Перед тем, как купить SSL-сертификат, ознакомьтесь со следующей информацией:
Comodo
Корневой (Root) и промежуточный (Intermediate) сертификаты отправляются одним файлом вместе с основным сертификатом. В зависимости от типа сертификата, цепочка выглядит следующим образом:
EV SSL
- Root: AddTrustExternalCARoot.crt
- Intermediate 1: COMODOAddTrustServerCA.crt
- Intermediate 2: COMODOExtendedValidationSecureServerCA.crt
- End-Entity/Domain Certificate
InstantSSL
- Root: AddTrustExternalCARoot.crt
- Intermediate: ComodoHigh-AssuranceSecureServerCA.crt
- End-Entity/Domain Certificate
EssentialSSL
- Root: AddTrustExternalCARoot.crt
- Intermediate 1: UTNAddTrustSGCCA.crt
- Intermediate 2: ComodoUTNSGCCA.crt
- Intermediate 3: EssentialSSLCA_2.crt
- End-Entity/Domain Certificate
PositiveSSL
- Root: AddTrustExternalCARoot.crt
- Intermediate: PositiveSSLCA2.crt
- End-Entity/Domain Certificate
Скачать архив с цепочкой сертификатов можно на сайте Comodo. По умолчанию, начиная с 2014 года, новые сертификаты от данного центра выпускаются в алгоритме шифрования SHA-2, который является более безопасным. Так как не все клиентские программы поддерживают новый алгоритм, еще остается возможность получить цепочку сертификата в алгоритме SHA-1.
Примечание: Архивы с префиксом [OLD] относятся к сертификатам, выпущенным ранее 2012 гогда.
GeoTrust
Центр сертификации присылает сертификат не архивом, а в теле письма. Он расположен под заголовком INTERMEDIATE CA.
Скачать полную цепочку сертификата можно на следующих страницах официального сайта GeoTrust:
RapidSSL – на этой странице.
QuickSSL, QuickSSL Premium – здесь.
True BusinessID / True BusinessID Wildcard / True BusinessID with EV – здесь.
Thawte
Скачать Root сертификат Thawte можно с этой страницы.
Скачать Intermediate сертификат — с данной страницы.
VerySign
Предлагает скачать Root и Intermediate сертификаты на странице.
Примечание: Каждый центр сертификации может предлагать для скачивания промежуточные сертификаты в зависимости от года выпуска сертификата, длины ключа шифрования, алгоритма шифрования. Пожалуйста, обращайте внимание на эти параметры, иначе соединение в случае установки несоответствующего сертификата не будет доверенным.
Если же не установить промежуточный сертификат, шифрованное соединение может и вовсе не работать.
У нас вы можете купить разные типы сертификатов (DV, OV, EV, Wildcard SSL). При возникновении вопросов обращайтесь в поддержку.
Читайте здесь, зачем нужен SSL-сертификат.
Как локально проверить SSL-сертификат — Information Security Squad
Проверьте код возврата — вы можете безопасно использовать этот сертификат.
$ curl --silent --capath /etc/ssl/certs --resolve example.com:8282:127.0.0.1 https://example.com:8282/
<HTML><BODY BGCOLOR="#ffffff"> <pre> s_server -no_dhe -accept 8282 -www -key devel.key -cert devel.crt -CAfile devel.int.crt Secure Renegotiation IS supported Ciphers supported in s_server binary TLSv1/SSLv3:ECDHE-RSA-AES256-GCM-SHA384TLSv1/SSLv3:ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1/SSLv3:ECDHE-RSA-AES256-SHA384 TLSv1/SSLv3:ECDHE-ECDSA-AES256-SHA384 TLSv1/SSLv3:ECDHE-RSA-AES256-SHA TLSv1/SSLv3:ECDHE-ECDSA-AES256-SHA TLSv1/SSLv3:SRP-DSS-AES-256-CBC-SHA TLSv1/SSLv3:SRP-RSA-AES-256-CBC-SHA TLSv1/SSLv3:SRP-AES-256-CBC-SHA TLSv1/SSLv3:DH-DSS-AES256-GCM-SHA384 TLSv1/SSLv3:DHE-DSS-AES256-GCM-SHA384TLSv1/SSLv3:DH-RSA-AES256-GCM-SHA384 TLSv1/SSLv3:DHE-RSA-AES256-GCM-SHA384TLSv1/SSLv3:DHE-RSA-AES256-SHA256 TLSv1/SSLv3:DHE-DSS-AES256-SHA256 TLSv1/SSLv3:DH-RSA-AES256-SHA256 TLSv1/SSLv3:DH-DSS-AES256-SHA256 TLSv1/SSLv3:DHE-RSA-AES256-SHA TLSv1/SSLv3:DHE-DSS-AES256-SHA TLSv1/SSLv3:DH-RSA-AES256-SHA TLSv1/SSLv3:DH-DSS-AES256-SHA TLSv1/SSLv3:DHE-RSA-CAMELLIA256-SHA TLSv1/SSLv3:DHE-DSS-CAMELLIA256-SHA TLSv1/SSLv3:DH-RSA-CAMELLIA256-SHA TLSv1/SSLv3:DH-DSS-CAMELLIA256-SHA TLSv1/SSLv3:ECDH-RSA-AES256-GCM-SHA384 TLSv1/SSLv3:ECDH-ECDSA-AES256-GCM-SHA384TLSv1/SSLv3:ECDH-RSA-AES256-SHA384 TLSv1/SSLv3:ECDH-ECDSA-AES256-SHA384 TLSv1/SSLv3:ECDH-RSA-AES256-SHA TLSv1/SSLv3:ECDH-ECDSA-AES256-SHA TLSv1/SSLv3:AES256-GCM-SHA384 TLSv1/SSLv3:AES256-SHA256 TLSv1/SSLv3:AES256-SHA TLSv1/SSLv3:CAMELLIA256-SHA TLSv1/SSLv3:PSK-AES256-CBC-SHA TLSv1/SSLv3:ECDHE-RSA-AES128-GCM-SHA256TLSv1/SSLv3:ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1/SSLv3:ECDHE-RSA-AES128-SHA256 TLSv1/SSLv3:ECDHE-ECDSA-AES128-SHA256 TLSv1/SSLv3:ECDHE-RSA-AES128-SHA TLSv1/SSLv3:ECDHE-ECDSA-AES128-SHA TLSv1/SSLv3:SRP-DSS-AES-128-CBC-SHA TLSv1/SSLv3:SRP-RSA-AES-128-CBC-SHA TLSv1/SSLv3:SRP-AES-128-CBC-SHA TLSv1/SSLv3:DH-DSS-AES128-GCM-SHA256 TLSv1/SSLv3:DHE-DSS-AES128-GCM-SHA256TLSv1/SSLv3:DH-RSA-AES128-GCM-SHA256 TLSv1/SSLv3:DHE-RSA-AES128-GCM-SHA256TLSv1/SSLv3:DHE-RSA-AES128-SHA256 TLSv1/SSLv3:DHE-DSS-AES128-SHA256 TLSv1/SSLv3:DH-RSA-AES128-SHA256 TLSv1/SSLv3:DH-DSS-AES128-SHA256 TLSv1/SSLv3:DHE-RSA-AES128-SHA TLSv1/SSLv3:DHE-DSS-AES128-SHA TLSv1/SSLv3:DH-RSA-AES128-SHA TLSv1/SSLv3:DH-DSS-AES128-SHA TLSv1/SSLv3:DHE-RSA-SEED-SHA TLSv1/SSLv3:DHE-DSS-SEED-SHA TLSv1/SSLv3:DH-RSA-SEED-SHA TLSv1/SSLv3:DH-DSS-SEED-SHA TLSv1/SSLv3:DHE-RSA-CAMELLIA128-SHA TLSv1/SSLv3:DHE-DSS-CAMELLIA128-SHA TLSv1/SSLv3:DH-RSA-CAMELLIA128-SHA TLSv1/SSLv3:DH-DSS-CAMELLIA128-SHA TLSv1/SSLv3:ECDH-RSA-AES128-GCM-SHA256 TLSv1/SSLv3:ECDH-ECDSA-AES128-GCM-SHA256TLSv1/SSLv3:ECDH-RSA-AES128-SHA256 TLSv1/SSLv3:ECDH-ECDSA-AES128-SHA256 TLSv1/SSLv3:ECDH-RSA-AES128-SHA TLSv1/SSLv3:ECDH-ECDSA-AES128-SHA TLSv1/SSLv3:AES128-GCM-SHA256 TLSv1/SSLv3:AES128-SHA256 TLSv1/SSLv3:AES128-SHA TLSv1/SSLv3:SEED-SHA TLSv1/SSLv3:CAMELLIA128-SHA TLSv1/SSLv3:PSK-AES128-CBC-SHA TLSv1/SSLv3:ECDHE-RSA-RC4-SHA TLSv1/SSLv3:ECDHE-ECDSA-RC4-SHA TLSv1/SSLv3:ECDH-RSA-RC4-SHA TLSv1/SSLv3:ECDH-ECDSA-RC4-SHA TLSv1/SSLv3:RC4-SHA TLSv1/SSLv3:RC4-MD5 TLSv1/SSLv3:PSK-RC4-SHA TLSv1/SSLv3:ECDHE-RSA-DES-CBC3-SHA TLSv1/SSLv3:ECDHE-ECDSA-DES-CBC3-SHA TLSv1/SSLv3:SRP-DSS-3DES-EDE-CBC-SHA TLSv1/SSLv3:SRP-RSA-3DES-EDE-CBC-SHA TLSv1/SSLv3:SRP-3DES-EDE-CBC-SHA TLSv1/SSLv3:EDH-RSA-DES-CBC3-SHA TLSv1/SSLv3:EDH-DSS-DES-CBC3-SHA TLSv1/SSLv3:DH-RSA-DES-CBC3-SHA TLSv1/SSLv3:DH-DSS-DES-CBC3-SHA TLSv1/SSLv3:ECDH-RSA-DES-CBC3-SHA TLSv1/SSLv3:ECDH-ECDSA-DES-CBC3-SHA TLSv1/SSLv3:DES-CBC3-SHA TLSv1/SSLv3:PSK-3DES-EDE-CBC-SHA --- Ciphers common between both SSL end points: ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA ECDHE-ECDSA-AES256-SHA DH-DSS-AES256-GCM-SHA384 DHE-DSS-AES256-GCM-SHA384 DH-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA256 DHE-DSS-AES256-SHA256 DH-RSA-AES256-SHA256 DH-DSS-AES256-SHA256 DHE-RSA-AES256-SHA DHE-DSS-AES256-SHA DH-RSA-AES256-SHA DH-DSS-AES256-SHA DHE-RSA-CAMELLIA256-SHA DHE-DSS-CAMELLIA256-SHA DH-RSA-CAMELLIA256-SHA DH-DSS-CAMELLIA256-SHA ECDH-RSA-AES256-GCM-SHA384 ECDH-ECDSA-AES256-GCM-SHA384 ECDH-RSA-AES256-SHA384 ECDH-ECDSA-AES256-SHA384 ECDH-RSA-AES256-SHA ECDH-ECDSA-AES256-SHA AES256-GCM-SHA384 AES256-SHA256 AES256-SHA CAMELLIA256-SHA ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES128-SHA DH-DSS-AES128-GCM-SHA256 DHE-DSS-AES128-GCM-SHA256 DH-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-SHA256 DHE-DSS-AES128-SHA256 DH-RSA-AES128-SHA256 DH-DSS-AES128-SHA256 DHE-RSA-AES128-SHA DHE-DSS-AES128-SHA DH-RSA-AES128-SHA DH-DSS-AES128-SHA DHE-RSA-SEED-SHA DHE-DSS-SEED-SHA DH-RSA-SEED-SHA DH-DSS-SEED-SHA DHE-RSA-CAMELLIA128-SHA DHE-DSS-CAMELLIA128-SHA DH-RSA-CAMELLIA128-SHA DH-DSS-CAMELLIA128-SHA ECDH-RSA-AES128-GCM-SHA256 ECDH-ECDSA-AES128-GCM-SHA256 ECDH-RSA-AES128-SHA256 ECDH-ECDSA-AES128-SHA256 ECDH-RSA-AES128-SHA ECDH-ECDSA-AES128-SHA AES128-GCM-SHA256 AES128-SHA256 AES128-SHA SEED-SHA CAMELLIA128-SHA ECDHE-RSA-DES-CBC3-SHA ECDHE-ECDSA-DES-CBC3-SHA EDH-RSA-DES-CBC3-SHA EDH-DSS-DES-CBC3-SHA DH-RSA-DES-CBC3-SHA DH-DSS-DES-CBC3-SHA ECDH-RSA-DES-CBC3-SHA ECDH-ECDSA-DES-CBC3-SHA DES-CBC3-SHA Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1 Shared Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1 Supported Elliptic Curves: P-256:P-521:brainpoolP512r1:brainpoolP384r1:P-384:brainpoolP256r1:secp256k1:B-571:K-571:K-409:B-409:K-283:B-283 Shared Elliptic curves: P-256:P-521:brainpoolP512r1:brainpoolP384r1:P-384:brainpoolP256r1:secp256k1:B-571:K-571:K-409:B-409:K-283:B-283 --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 824C62C3468CD687000D4DEEA7967979681A68F724EA51BEA1F62BC756162D30 Session-ID-ctx: 01000000 Master-Key: 1FE48D580D50BD7936CA40CD20D0EAD44EB7B27ECDF13F0A1B0E6F7C76F4384638C4FC1869D8F1752BFD860805EF68F8 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Start Time: 1510259200 Timeout : 300 (sec) Verify return code: 0 (ok) --- 1 items in the session cache 0 client connects (SSL_connect()) 0 client renegotiates (SSL_connect()) 0 client connects that finished 1 server accepts (SSL_accept()) 0 server renegotiates (SSL_accept()) 1 server accepts that finished 0 session cache hits 0 session cache misses 0 session cache timeouts 0 callback cache hits 0 cache full overflows (128 allowed) --- no client certificate available </BODY></HTML>
Используйте подробный вывод для дальнейшей проверки всего процесса.
$ curl --silent --capath /etc/ssl/certs --output /dev/null --verbose --resolve example.com:8282:127.0.0.1 https://example.com:8282/
* Added example.com:8282:127.0.0.1 to DNS cache * Hostname example.com was found in DNS cache * Trying 127.0.0.1... * TCP_NODELAY set * Connected to example.com (127.0.0.1) port 8282 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.2 (OUT), TLS header, Certificate Status (22): } [5 bytes data] * TLSv1.2 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * TLSv1.2 (IN), TLS handshake, Server hello (2): { [94 bytes data] * TLSv1.2 (IN), TLS handshake, Certificate (11): { [3347 bytes data] * TLSv1.2 (IN), TLS handshake, Server key exchange (12): { [333 bytes data] * TLSv1.2 (IN), TLS handshake, Server finished (14): { [4 bytes data] * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): } [70 bytes data] * TLSv1.2 (OUT), TLS change cipher, Client hello (1): } [1 bytes data] * TLSv1.2 (OUT), TLS handshake, Finished (20): } [16 bytes data] * TLSv1.2 (IN), TLS change cipher, Client hello (1): { [1 bytes data] * TLSv1.2 (IN), TLS handshake, Finished (20): { [16 bytes data] * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server did not agree to a protocol * Server certificate: * subject: CN=example.com * start date: Oct 28 19:55:12 2017 GMT * expire date: Jan 26 19:55:12 2018 GMT * subjectAltName: host "example.com" matched cert's "example.com" * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. } [5 bytes data] > GET :/ HTTP/1.1 > Host: example.com:8282 > User-Agent: curl/7.55.1 > Accept: */* > { [5 bytes data] * HTTP 1.0, assume close after body < HTTP/1.0 200 ok < Content-type: text/html < { [7670 bytes data] * Closing connection 0 } [5 bytes data] * TLSv1.2 (OUT), TLS alert, Client hello (1): } [2 bytes data]
Пакет сертификатов HAproxy
После проверки сертификата необходимо создать комплект сертификатов domain.pem, который включает сертификат domain.crt, промежуточные сертификаты domain.intermediate.crt и закрытый ключ domain.key.
Именно в таком порядке.
Там больше ничего нет.
Дополнительные примечания
Вы можете использовать веб-браузер вместо curl для проверки локально сохраненного сертификата, но это не очень удобно.
Я отключил эфемерные комплекты алгоритмов DH, но вы можете указать файл параметров DH для использования.
Вы можете использовать openssl s_server для обслуживания файлов по сети, но это просто еще один лакомый кусочек.
Проверьте код возврата (он отличается от кода выхода), так как он четко покажет, что с предоставленными промежуточными сертификатами что-то не так.
Код возврата не является кодом выхода.
Коды возврата описаны на странице руководства verify.
0 X509_V_OK: ok the operation was successful. 2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate the issuer certificate of a looked up certificate could not be found. This normally means the list of trusted certificates is not complete. 3 X509_V_ERR_UNABLE_TO_GET_CRL: unable to get certificate CRL the CRL of a certificate could not be found. 4 X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: unable to decrypt certificate's signature the certificate signature could not be decrypted. This means that the actual signature value could not be determined rather than it not matching the expected value, this is only meaningful for RSA keys. 5 X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: unable to decrypt CRL's signature the CRL signature could not be decrypted: this means that the actual signature value could not be determined rather than it not matching the expected value. Unused. 6 X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: unable to decode issuer public key the public key in the certificate SubjectPublicKeyInfo could not be read. 7 X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure the signature of the certificate is invalid. 8 X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure the signature of the certificate is invalid. 9 X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid the certificate is not yet valid: the notBefore date is after the current time. 10 X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired the certificate has expired: that is the notAfter date is before the current time. 11 X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid the CRL is not yet valid. 12 X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired the CRL has expired. 13 X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: format error in certificate's notBefore field the certificate notBefore field contains an invalid time. 14 X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: format error in certificate's notAfter field the certificate notAfter field contains an invalid time. 15 X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: format error in CRL's lastUpdate field the CRL lastUpdate field contains an invalid time. 16 X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: format error in CRL's nextUpdate field the CRL nextUpdate field contains an invalid time. 17 X509_V_ERR_OUT_OF_MEM: out of memory an error occurred trying to allocate memory. This should never happen. 18 X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self signed certificate the passed certificate is self signed and the same certificate cannot be found in the list of trusted certificates. 19 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: self signed certificate in certificate chain the certificate chain could be built up using the untrusted certificates but the root could not be found locally. 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found. 21 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the first certificate no signatures could be verified because the chain contains only one certificate and it is not self signed. 22 X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long the certificate chain length is greater than the supplied maximum depth. Unused. 23 X509_V_ERR_CERT_REVOKED: certificate revoked the certificate has been revoked. 24 X509_V_ERR_INVALID_CA: invalid CA certificate a CA certificate is invalid. Either it is not a CA or its extensions are not consistent with the supplied purpose. 25 X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded the basicConstraints pathlength parameter has been exceeded. 26 X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose the supplied certificate cannot be used for the specified purpose. 27 X509_V_ERR_CERT_UNTRUSTED: certificate not trusted the root CA is not marked as trusted for the specified purpose. 28 X509_V_ERR_CERT_REJECTED: certificate rejected the root CA is marked to reject the specified purpose. 29 X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch the current candidate issuer certificate was rejected because its subject name did not match the issuer name of the current certificate. Only displayed when the -issuer_checks option is set. 30 X509_V_ERR_AKID_SKID_MISMATCH: authority and subject key identifier mismatch the current candidate issuer certificate was rejected because its subject key identifier was present and did not match the authority key identifier current certificate. Only displayed when the -issuer_checks option is set. 31 X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: authority and issuer serial number mismatch the current candidate issuer certificate was rejected because its issuer name and serial number was present and did not match the authority key identifier of the current certificate. Only displayed when the -issuer_checks option is set. 32 X509_V_ERR_KEYUSAGE_NO_CERTSIGN:key usage does not include certificate signing the current candidate issuer certificate was rejected because its keyUsage extension does not permit certificate signing. 50 X509_V_ERR_APPLICATION_VERIFICATION: application verification failure an application specific error. Unused.
Что такое цепочка сертификатов SSL?
Существует два типа центров сертификации (ЦС): корневых ЦС и промежуточных ЦС . Чтобы SSL-сертификат считался доверенным, этот сертификат должен быть выдан центром сертификации, который включен в доверенное хранилище устройства, подключающего .
Если сертификат не был выдан доверенным ЦС, подключающееся устройство (например, веб-браузер) проверяет, был ли сертификат выдающего ЦС выдан доверенным ЦС.Проверка продолжается до тех пор, пока либо не будет найден доверенный ЦС (после чего будет установлено доверенное безопасное соединение), либо не будет найден доверенный ЦС (в этот момент на устройстве обычно отображается ошибка).
Список сертификатов SSL, от корневого сертификата до сертификата конечного пользователя, представляет собой цепочку сертификатов SSL .
Пример цепочки сертификатов SSL
В качестве примера предположим, что вы приобрели сертификат у Awesome Authority для домена .обалденный
.
Awesome Authority не является корневым центром сертификации. Его сертификат не встроен непосредственно в ваш веб-браузер, поэтому ему нельзя явно доверять.
- Awesome Authority использует сертификат, выданный Intermediate Awesome CA Alpha .
- Intermediate Awesome CA Alpha использует сертификат, выданный Intermediate Awesome CA Beta .
- Intermediate Awesome CA Beta использует сертификат, выданный Intermediate Awesome CA Gamma .
- Intermediate Awesome CA Gamma использует сертификат, выданный The King of Awesomeness .
- The King of Awesomeness — это корневой центр сертификации. Его сертификат напрямую встроен в ваш веб-браузер, поэтому ему можно явно доверять.
В нашем примере цепочка сертификатов SSL представлена 6 сертификатами:
- Сертификат конечного пользователя — выдан по адресу: example.com; Выпущено: Awesome Authority
- Промежуточный сертификат 1 — выдан: Awesome Authority; Выпущено: Intermediate Awesome CA Alpha
- Промежуточный сертификат 2 — выдан: Intermediate Awesome CA Alpha; Выпущено: Intermediate Awesome CA Beta
- Промежуточный сертификат 3 — выдан: Intermediate Awesome CA Beta; Выпущено: Intermediate Awesome CA Gamma
- Промежуточный сертификат 4 — выдан: Intermediate Awesome CA Gamma; Выдано: Королем удивительности
- Корневой сертификат — выдан и получателем: Король удивительности
Сертификат 1, который вы покупаете в ЦС, является вашим сертификатом конечного пользователя .Сертификаты со 2 по 5 — это промежуточных сертификата . Сертификат 6, расположенный в верхней части цепочки (или в конце, в зависимости от того, как вы читаете цепочку), является корневым сертификатом .
Когда вы устанавливаете свой сертификат конечного пользователя для example.awesome
, вы должны объединить все промежуточные сертификаты и установить их вместе с вашим сертификатом конечного пользователя. Если цепочка сертификатов SSL недействительна или повреждена, некоторые устройства не будут доверять вашему сертификату.
Часто задаваемые вопросы
Нужно ли мне устанавливать корневой сертификат на моем сервере?
Нет. Корневой сертификат обычно встроен в подключенное устройство. В случае веб-браузеров корневые сертификаты поставляются вместе с программным обеспечением браузера.
Как установить промежуточные сертификаты SSL?
Процедура установки промежуточных сертификатов SSL зависит от веб-сервера и среды, в которой вы устанавливаете сертификат.
Например, Apache требует, чтобы вы связали промежуточные сертификаты SSL и назначили местоположение пакета конфигурации
SSLCertificateChainFile
. Однако NGINX требует, чтобы вы упаковали промежуточные сертификаты SSL в один комплект с сертификатом конечного пользователя.Мы предоставляем мастер установки сертификата, который содержит инструкции по установке для нескольких серверов и платформ. Если вы приобретете сертификат у нас, вы можете использовать этот мастер для получения и установки файлов, необходимых для вашего сервера.
Если на вашем сервере нет мастера, вы все равно можете получить с его помощью нужные файлы, а затем следуйте документации веб-сервера, чтобы определить, как правильно установить сертификат домена и промежуточные сертификаты.
Что произойдет, если я не установлю промежуточный сертификат SSL?
Если вы не установите один или несколько промежуточных сертификатов SSL, вы разорвете цепочку сертификатов. Это означает, что вы создаете разрыв между конкретным (конечным или промежуточным) сертификатом и его издателем.Когда устройству не удается найти доверенного поставщика сертификата, этому сертификату и всей цепочке, от промежуточного сертификата до окончательного сертификата, нельзя доверять.
В результате вашему окончательному сертификату нельзя будет доверять. Веб-браузеры будут отображать ошибку «Недействительный сертификат» или «Сертификат не доверяет».
Как я могу сократить цепочку сертификатов SSL в моем браузере?
Это невозможно. Единственный способ сократить цепочку — сделать промежуточный сертификат корневым.В идеале вы должны продвигать сертификат, который представляет ваш центр сертификации — тогда цепочка будет состоять всего из двух сертификатов.
Корневые сертификаты входят в комплект программного обеспечения браузера. Список может быть изменен только разработчиками браузера.
.
CERT_CHAIN_CONTEXT (wincrypt.h) — приложения Win32
- 2 минуты на чтение
В этой статье
Структура CERT_CHAIN_CONTEXT содержит массив простых цепочек сертификатов и структуру статуса доверия, которая указывает сводные данные о достоверности для всех подключенных простых цепочек.
Синтаксис
typedef struct _CERT_CHAIN_CONTEXT {
DWORD cbSize;
CERT_TRUST_STATUS TrustStatus;
DWORD cChain;
PCERT_SIMPLE_CHAIN * rgpChain;
DWORD cLowerQualityChainContext;
PCCERT_CHAIN_CONTEXT * rgpLowerQualityChainContext;
BOOL fHasRevocationFreshnessTime;
DWORD dwRevocationFreshnessTime;
DWORD dwCreateFlags;
GUID ChainId;
} CERT_CHAIN_CONTEXT, * PCERT_CHAIN_CONTEXT;
участников
куб Размер
Размер этой структуры в байтах.
TrustStatus
Структура, которая указывает объединенный статус доверия массива простых цепочек. Структура включает код состояния ошибки и код состояния информации. Для получения информации о значениях кодов состояния см.
CERT_TRUST_STATUS.
Цепь
Количество простых цепочек в массиве.
rgpChain
Массив указателей на простые цепочечные структуры. rgpChain [0] — это простая цепочка конечного сертификата, а rgpChain [ cChain –1] — конечная цепочка.Если конечный сертификат следует считать действительным, конечная цепочка должна начинаться с сертификата, содержащегося в корневом хранилище, или с доверенного самозаверяющего сертификата. Если исходная цепочка начинается с доверенного сертификата, в массиве будет только одна простая цепочка.
cLowerQualityChainContext
Количество цепочек в массиве rgpLowerQualityChainContext .
rgpLowerQualityChainContext
Массив указателей на структуры CERT_CHAIN_CONTEXT.Возвращается, когда CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS установлен в dwFlags.
fHasRevocationFreshnessTime
Логическое значение, равное TRUE , если доступно dwRevocationFreshnessTime .
dwRevocationFreshnessTime
Наибольшее значение CurrentTime в секундах за вычетом ThisUpdate списка отзыва сертификатов (CRL) всех проверенных элементов.
dwCreateFlags
Идентификатор цепи
Замечания
Когда создается CERT_CHAIN_CONTEXT , первая простая цепочка начинается с конечного сертификата и заканчивается самозаверяющим сертификатом.Если этот самозаверяющий сертификат не является корневым или другим доверенным сертификатом, делается попытка построить новую цепочку. CTL используются для создания новой цепочки, начиная с самозаверяющего сертификата исходной цепочки в качестве конечного сертификата новой цепочки. Этот процесс продолжает построение дополнительных простых цепочек до тех пор, пока первый самозаверяющий сертификат не станет доверенным сертификатом или пока не будет построена дополнительная простая цепочка.
Требования
Минимальный поддерживаемый клиент | Windows XP [только настольные приложения] |
Минимальный поддерживаемый сервер | Windows Server 2003 [только настольные приложения] |
Заголовок | wincrypt.h |
См. Также
CERT_SIMPLE_CHAIN
CERT_TRUST_STATUS
CertGetCertificateChain
.
CERT_CHAIN_ELEMENT (wincrypt.h) — приложения Win32
- 2 минуты на чтение
В этой статье
Структура CERT_CHAIN_ELEMENT — это отдельный элемент в простой цепочке сертификатов. Каждый элемент имеет указатель на контекст сертификата, указатель на структуру, которая указывает статус ошибки и информационный статус сертификата, и указатель на структуру, которая указывает статус отзыва сертификата.
Синтаксис
typedef struct _CERT_CHAIN_ELEMENT {
DWORD cbSize;
PCCERT_CONTEXT pCertContext;
CERT_TRUST_STATUS TrustStatus;
PCERT_REVOCATION_INFO pRevocationInfo;
PCERT_ENHKEY_USAGE pIssuanceUsage;
PCERT_ENHKEY_USAGE pApplicationUsage;
LPCWSTR pwszExtendedErrorInfo;
} CERT_CHAIN_ELEMENT, * PCERT_CHAIN_ELEMENT;
участников
куб Размер
Размер этой структуры в байтах.
pCertContext
Указатель на контекст сертификата.
TrustStatus
Структура, показывающая статус сертификата. Структура включает код состояния ошибки и код состояния информации. Для получения информации о значениях кода состояния см. CERT_TRUST_STATUS.
pRevocationInfo
Указатель на структуру CERT_REVOCATION_INFO с информацией о статусе отзыва сертификата.Если проверка отзыва не была включена, pRevocationInfo будет NULL .
РАСХОДЫ
Указатель на структуру CERT_ENHKEY_USAGE. Если NULL , приемлема любая политика выдачи.
p Применение Использование
Указатель на структуру CERT_ENHKEY_USAGE. Если NULL , допустимо использование любого расширенного ключа.
pwszExtendedErrorInfo
Указатель на строку широких символов с нулевым завершением, , которая содержит расширенную информацию об ошибках.Если NULL , расширенная информация об ошибке отсутствует.
Требования
Минимальный поддерживаемый клиент | Windows XP [только настольные приложения] |
Минимальный поддерживаемый сервер | Windows Server 2003 [только настольные приложения] |
Заголовок | wincrypt.h |
См. Также
CERT_REVOCATION_INFO
CERT_SIMPLE_CHAIN
CERT_TRUST_STATUS
.
CERT_CHAIN_POLICY_STATUS (wincrypt.h) — приложения Win32
- 3 минуты на чтение
В этой статье
Структура CERT_CHAIN_POLICY_STATUS содержит информацию о состоянии цепочки сертификатов, возвращаемую
функция CertVerifyCertificateChainPolicy при проверке цепочек сертификатов.
Синтаксис
typedef struct _CERT_CHAIN_POLICY_STATUS {
DWORD cbSize;
DWORD dwError;
LONG lChainIndex;
LONG lElementIndex;
void * pvExtraPolicyStatus;
} CERT_CHAIN_POLICY_STATUS, * PCERT_CHAIN_POLICY_STATUS;
участников
куб Размер
Размер этой структуры в байтах.
dwError
Значение, указывающее, что во время процесса проверки обнаружена ошибка или недопустимое условие. Значения этого члена зависят от типа политики, как указано значением параметра pszPolicyOID функции CertVerifyCertificateChainPolicy.
Ошибки базовой политики ( CERT_CHAIN_POLICY_BASE )
Значение | Значение |
---|---|
| Подпись сертификата не может быть проверена. |
| Сертификат или подпись отозваны. |
| Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия. |
| Корневой сертификат — это тестовый сертификат, а настройки политики запрещают тестовые сертификаты. |
| Цепочка сертификатов была создана неправильно. |
| Сертификат недействителен для запрошенного использования. |
| Срок действия необходимого сертификата истек. |
| У сертификата неверное имя. Имя либо не включено в список разрешенных, либо исключено явно. |
| Сертификат имеет недопустимую политику. |
| Основные ограничения сертификата недействительны или отсутствуют. |
| Сертификат используется для целей, отличных от целей, указанных его ЦС. |
| Сроки действия цепочки сертификации не вложены правильно. |
| Функция отзыва не смогла проверить отзыв сертификата. |
| Функция отзыва не смогла проверить отзыв, поскольку сервер отзыва был отключен. |
Ошибки политики основных ограничений ( CERT_CHAIN_POLICY_BASIC_CONSTRAINTS ).
Значение | Значение |
---|---|
| Основные ограничения сертификата недействительны или отсутствуют. |
Ошибки политики Authenticode ( CERT_CHAIN_POLICY_AUTHENTICODE и CERT_CHAIN_POLICY_AUTHENTICODE_TS ).
Эти ошибки являются дополнительными к ошибкам базовой политики.
Значение | Значение |
---|---|
| Сертификат используется не для одной цели, указанной выдающим ЦС. |
| Сертификат явно отозван издателем. |
| Не удалось продолжить процесс отзыва и проверить сертификат. |
Ошибки политики SSL ( CERT_CHAIN_POLICY_SSL ).
Эти ошибки являются дополнительными к ошибкам базовой политики.
Значение | Значение |
---|---|
| Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия. |
| CN-имя сертификата не соответствует переданному значению. |
| Сертификат используется для целей, отличных от целей, указанных его ЦС. |
| Сертификат, который может использоваться только как конечный объект, используется как CA или наоборот. |
Ошибки политики корневого каталога Microsoft ( CERT_CHAIN_POLICY_MICROSOFT_ROOT ).
Значение | Значение |
---|---|
| Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия. |
EV Ошибки политики.
Значение | Значение |
---|---|
| Невозможно построить цепочку сертификатов до доверенного корневого центра. |
| Сертификат недействителен для запрошенного использования. |
lChainIndex
Индекс, который указывает цепочку, в которой обнаружена ошибка или недопустимое условие. Для получения дополнительной информации см. Примечания.
Индекс элемента
Индекс, который указывает элемент в цепочке, в котором обнаружена ошибка или недопустимое условие.Для получения дополнительной информации см. Примечания.
pvExtraPolicyStatus
Указатель на структуру. Тип структуры определяется значением параметра pszPolicyOID функции CertVerifyCertificateChainPolicy. В дополнение к ошибкам dwError здесь также может быть возвращен дополнительный статус, связанный с OID политики, для предоставления дополнительной информации о статусе цепочки. Этот указатель можно дополнительно настроить так, чтобы он указывал на
Структура AUTHENTICODE_EXTRA_CERT_CHAIN_POLICY_STATUS.
Замечания
Если для lChainIndex и lElementIndex установлено значение –1, ошибка или недопустимое условие применяется ко всему контексту цепочки. Если только lElementIndex установлено на –1, ошибка или недопустимое условие применяется к цепочке, проиндексированной lChainIndex . В противном случае ошибка или недопустимое условие применяется к элементу сертификата в pChainContext-> rgpChain [ lChainIndex ] -> rgpElement [ lElementIndex ].
Требования
Минимальный поддерживаемый клиент | Windows XP [только настольные приложения] |
Минимальный поддерживаемый сервер | Windows Server 2003 [только настольные приложения] |
Заголовок | wincrypt.h |
.