Получение цепочки или эмитента CA из сертификата x509 с помощью OpenSSL CLI
Я пытаюсь построить цепочку (или просто получить ее откуда-то) из сертификата с использованием OpenSSL, предпочтительно с использованием интерфейса командной строки.
Я нашел несколько примеров в Интернете, но я застрял в вопросе "Где я могу получить сертификат CA, выдавший сертификат?"
Например, проверьте этот веб-сайт с таблицей команд openssl, вы найдете команду
openssl s_client -showcerts -host example.com -port 443
получить цепочку. Вы можете попробовать это, используяwww.google.com
вместо того example.com
. Результат должен дать вам цепочку. Другие веб-сайты рано или поздно используют ту же команду...
Итак, я не могу получить цепочку напрямую из сертификата, но я должен где-то попросить цепочку.
Теперь моя проблема: где мне взять имя хоста, куда я могу отправить свой запрос на цепочку?
Я взглянул на два сертификата.
- stackexchange.com
- google.com
С помощью OpenSSL
, Я могу спросить эмитента с помощью команды
openssl x509 -in certFile -noout -issuer
и я получаю соответственно
- эмитент =C = США, O = Let's Encrypt, CN = Let's Encrypt Authority X3
- эмитент =C = США, O = Google Trust Services, CN = GTS CA 1O1
Честно говоря, я не знаю, что мне делать с этими результатами....
Затем, исследуя с помощью команды
openssl x509 -text -in certFile
Я нашел расширения AIA:
- Эмитенты CA - URI:http://cert.int-x3.letsencrypt.org/
- Эмитенты CA - URI:http://pki.goog/gsr2/GTS1O1.crt
Хорошо, в первом примере я наконец могу использовать команду
openssl s_client -showcerts -host http://cert.int-x3.letsencrypt.org/ -port 443
а с гуглом я не знаю как скачать цепочку с помощью openssl
.... я мог бы использовать wget
может быть, но у меня нет того формата, который я получил от stackexchange...
Итак, напоследок мои вопросы:
- Как мне работать с этими различиями?
- Есть ли лучший способ получить цепочку из сертификата, не спрашивая эмитента CA?
- CA Issuer - это расширение от AIA, и я думаю, что это не обязательно, могу ли я на него положиться?
- Как я могу получить CA Issuer, используя
OpenSSL
, без разбора вывода самостоятельно? (что-то типаopenssl x509 -caIssuer -in certFile
)
PS: То, что я пытаюсь достичь в самом конце, - это проверить сертификат, пройти всю цепочку и проверить все OCSP или CRL для каждого сертификата в цепочке... Если у вас есть рабочий пример на C++ или просто используя OpenSSL CLI, буду очень благодарен:)
РЕДАКТИРОВАТЬ:
Сейчас я создаю цепочку самостоятельно.
Используя расширения AIA, я получаю URI CA Issuer, загружаю сертификат CA Issuer (при необходимости конвертирую в PEM) и так далее, пока я больше не найду CA Issuer. Тогда, вероятно, это корневой ЦС.
После этого я вручную собираю весь пем и создаю цепочку.
3 ответа
Кажется, много примеров в Интернете имеют в виду сертификат SSL. В сертификате SSL вы можете просто подключиться к сайту и загрузить полную цепочку. Я думаю, что именно в самом протоколе SSL сервер должен предоставить вам полную цепочку.
Я делал это для сертификатов SMIME, поэтому меня смутил, потому что я не могу использовать тот же метод, который они используют для сертификатов SSL.
После разговора с моими коллегами, а также сравнения того, что я делал с некоторыми похожими программами, найденными в Интернете, кажется, что расширение AIA - правильный способ сделать это. Возможно, это не обязательно в стандарте X509, но похоже, что оно широко используется (я никогда не видел сертификата SMIME без расширения AIA).
Затем я создаю цепочку вручную, возвращаюсь, используя расширение AIA, пока не найду сертификат без такого расширения.
На этом этапе это должен быть корневой сертификат, и я попытаюсь просто проверить его, используя сертификаты, установленные на машине.
(Конечно, не забудьте проверить статус отзыва через CRL или OCSP)
Пока все работает хорошо:)
Знайте, что это немного устарело, и это было решено, но я подумал, что добавлю небольшой скрипт, который я пишу, чтобы проанализировать CA Issuer из вывода x509:
getcaissuer() {
openssl x509 -noout -text -in $1 | awk '/^[ \t]+CA Issuers[ \t]+-[ \t]+URI:/ { print gensub(/^.*URI:(.*)$/,"\\1","g",$0); }'
}
# usage: getcaissuer <certificate>
Бонус от ответа @bng44270, этот скрипт будет подниматься по цепочке, захватывая сертификаты в текущий каталог.
#!/bin/bash
# get-cert-chain.sh
machine=${1?No address passed}
machine_cert=${machine}.pem
# from https://stackoverflow.com/a/68637388/5401366
getcaissuer() {
openssl x509 -noout -text -in $1 -ext authorityInfoAccess | awk '/^[ \t]+CA Issuers[ \t]+-[ \t]+URI:/ { print gensub(/^.*URI:(.*)$/,"\\1","g",$0); }'
}
if [ ! -e "${machine_cert}" ];
then
openssl s_client -connect ${machine}:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM >${machine_cert}
fi;
cur_cert=$machine_cert
while :;
do
# Get the first matching http line to grab the next cert loc
nextca=$(getcaissuer ${cur_cert} | grep -m1 http)
# ran out of stuff to retrieve
[ -z "${nextca}" ] && break
echo "Trying to get '${nextca}'"
nextfile=$(basename ${nextca})
if [ ! -e ${nextfile} ];
then
echo "Getting $nextca"
curl -sO $nextca
else
echo "Found ${nextfile}"
fi
# Convert
cat $nextfile | openssl x509 -inform DER -outform PEM > ${nextfile}.pem
# down the rabbit hole...
cur_cert=${nextfile}.pem
done