Разное

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

  1. Аудит правовой, физической и операционной деятельности организации.
  2. Следует убедиться в том, что организация имеет эксклюзивное право на использование доменного имени.
  3. Следует убедиться в том, что организация авторизована для выпуска сертификата данного типа.

Более подробно можно прочитать в Хабрапоспе компании 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 сертификат, но времена меняются и с недавнего времени есть и третий путь.

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

  2. Приобрести сертификат в УЦ. Это будет стоить денег в зависимости от различных его характеристик и возможностей, указанных выше.
  3. Получить бесплатный сертификат 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 сертификатами:

  1. Сертификат конечного пользователя — выдан по адресу: example.com; Выпущено: Awesome Authority
  2. Промежуточный сертификат 1 — выдан: Awesome Authority; Выпущено: Intermediate Awesome CA Alpha
  3. Промежуточный сертификат 2 — выдан: Intermediate Awesome CA Alpha; Выпущено: Intermediate Awesome CA Beta
  4. Промежуточный сертификат 3 — выдан: Intermediate Awesome CA Beta; Выпущено: Intermediate Awesome CA Gamma
  5. Промежуточный сертификат 4 — выдан: Intermediate Awesome CA Gamma; Выдано: Королем удивительности
  6. Корневой сертификат — выдан и получателем: Король удивительности

Сертификат 1, который вы покупаете в ЦС, является вашим сертификатом конечного пользователя .Сертификаты со 2 по 5 — это промежуточных сертификата . Сертификат 6, расположенный в верхней части цепочки (или в конце, в зависимости от того, как вы читаете цепочку), является корневым сертификатом .

Когда вы устанавливаете свой сертификат конечного пользователя для example.awesome , вы должны объединить все промежуточные сертификаты и установить их вместе с вашим сертификатом конечного пользователя. Если цепочка сертификатов SSL недействительна или повреждена, некоторые устройства не будут доверять вашему сертификату.

Часто задаваемые вопросы

  1. Нужно ли мне устанавливать корневой сертификат на моем сервере?

    Нет. Корневой сертификат обычно встроен в подключенное устройство. В случае веб-браузеров корневые сертификаты поставляются вместе с программным обеспечением браузера.

  2. Как установить промежуточные сертификаты SSL?

    Процедура установки промежуточных сертификатов SSL зависит от веб-сервера и среды, в которой вы устанавливаете сертификат.

    Например, Apache требует, чтобы вы связали промежуточные сертификаты SSL и назначили местоположение пакета конфигурации SSLCertificateChainFile . Однако NGINX требует, чтобы вы упаковали промежуточные сертификаты SSL в один комплект с сертификатом конечного пользователя.

    Мы предоставляем мастер установки сертификата, который содержит инструкции по установке для нескольких серверов и платформ. Если вы приобретете сертификат у нас, вы можете использовать этот мастер для получения и установки файлов, необходимых для вашего сервера.

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

  3. Что произойдет, если я не установлю промежуточный сертификат SSL?

    Если вы не установите один или несколько промежуточных сертификатов SSL, вы разорвете цепочку сертификатов. Это означает, что вы создаете разрыв между конкретным (конечным или промежуточным) сертификатом и его издателем.Когда устройству не удается найти доверенного поставщика сертификата, этому сертификату и всей цепочке, от промежуточного сертификата до окончательного сертификата, нельзя доверять.

    В результате вашему окончательному сертификату нельзя будет доверять. Веб-браузеры будут отображать ошибку «Недействительный сертификат» или «Сертификат не доверяет».

  4. Как я могу сократить цепочку сертификатов 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 )

Значение Значение
TRUST_E_CERT_SIGNATURE
0x80096004L
Подпись сертификата не может быть проверена.
CRYPT_E_REVOKED
0x80092010L
Сертификат или подпись отозваны.
CERT_E_UNTRUSTEDROOT
0x800B0109L
Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия.
CERT_E_UNTRUSTEDTESTROOT
0x800B010DL
Корневой сертификат — это тестовый сертификат, а настройки политики запрещают тестовые сертификаты.
CERT_E_CHAINING
0x800B010AL
Цепочка сертификатов была создана неправильно.
CERT_E_WRONG_USAGE
0x800B0110L
Сертификат недействителен для запрошенного использования.
CERT_E_EXPIRED
0x800B0101L
Срок действия необходимого сертификата истек.
CERT_E_INVALID_NAME
0x800B0114L
У сертификата неверное имя. Имя либо не включено в список разрешенных, либо исключено явно.
CERT_E_INVALID_POLICY
0x800B0113L
Сертификат имеет недопустимую политику.
TRUST_E_BASIC_CONSTRAINTS
0x80096019L
Основные ограничения сертификата недействительны или отсутствуют.
CERT_E_CRITICAL
0x800B0105L
Сертификат используется для целей, отличных от целей, указанных его ЦС.
CERT_E_VALIDITYPERIODNESTING
0x800B0102L
Сроки действия цепочки сертификации не вложены правильно.
CRYPT_E_NO_REVOCATION_CHECK
0x80092012L
Функция отзыва не смогла проверить отзыв сертификата.
CRYPT_E_REVOCATION_OFFLINE
0x80092013L
Функция отзыва не смогла проверить отзыв, поскольку сервер отзыва был отключен.

Ошибки политики основных ограничений ( CERT_CHAIN_POLICY_BASIC_CONSTRAINTS ).

Значение Значение
TRUST_E_BASIC_CONSTRAINTS
0x80096019L
Основные ограничения сертификата недействительны или отсутствуют.

Ошибки политики Authenticode ( CERT_CHAIN_POLICY_AUTHENTICODE и CERT_CHAIN_POLICY_AUTHENTICODE_TS ).

Эти ошибки являются дополнительными к ошибкам базовой политики.

Значение Значение
CERT_E_PURPOSE
0x800B0106L
Сертификат используется не для одной цели, указанной выдающим ЦС.
CERT_E_REVOKED
0x800B010CL
Сертификат явно отозван издателем.
CERT_E_REVOCATION_FAILURE
0x800B010EL
Не удалось продолжить процесс отзыва и проверить сертификат.

Ошибки политики SSL ( CERT_CHAIN_POLICY_SSL ).

Эти ошибки являются дополнительными к ошибкам базовой политики.

Значение Значение
CERT_E_UNTRUSTEDROOT
0x800B0109L
Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия.
CERT_E_CN_NO_MATCH
0x800B010FL
CN-имя сертификата не соответствует переданному значению.
CERT_E_PURPOSE
0x800B0106L
Сертификат используется для целей, отличных от целей, указанных его ЦС.
CERT_E_ROLE
0x800B0103L
Сертификат, который может использоваться только как конечный объект, используется как CA или наоборот.

Ошибки политики корневого каталога Microsoft ( CERT_CHAIN_POLICY_MICROSOFT_ROOT ).

Значение Значение
CERT_E_UNTRUSTEDROOT
0x800B0109L
Цепочка сертификации обработана правильно, но завершена корневым сертификатом, которому не доверяет поставщик доверия.

EV Ошибки политики.

Значение Значение
CERT_E_CHAINING
0x800B010AL
Невозможно построить цепочку сертификатов до доверенного корневого центра.
CERT_E_WRONG_USAGE
0x800B0110L
Сертификат недействителен для запрошенного использования.

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

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *