Проверьте цепочку сертификатов с помощью openssl verify

128

Я создаю собственную цепочку сертификатов со следующими компонентами:

Root Certificate - Intermediate Certificate - User Certificate

Корневой сертификат - это самоподписанный сертификат, промежуточный сертификат подписан корневым сертификатом, а пользователь - промежуточным звеном.

Теперь я хочу проверить, привязан ли сертификат пользователя к корневому сертификату.

С участием

openssl verify -verbose -CAfile RootCert.pem Intermediate.pem

проверка в порядке. На следующем этапе я подтверждаю сертификат пользователя с помощью

openssl verify -verbose -CAfile Intermediate.pem UserCert.pem

и проверка показывает

error 20 at 0 depth lookup:unable to get local issuer certificate

Что случилось?

Индра
источник

Ответы:

165

Из verifyдокументации:

Если найден сертификат, который является его собственным издателем, предполагается, что это корневой ЦС.

Другими словами, корневой ЦС должен самоподписаться для работы проверки. Вот почему ваша вторая команда не сработала. Попробуйте вместо этого:

openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem

Он проверит всю вашу цепочку с помощью одной команды.

Priyadi
источник
2
Я поддерживаю этот ответ, так как недавно мне пришлось это сделать, и, попробовав различные перечисленные параметры man verify, я обнаружил, что этот -untrustedпараметр является правильным для использования при указании промежуточного сертификата.
Энтони Геогхеган
Думаю, второй ответ: stackoverflow.com/a/31205833/173062 точнее - он передает цепочку сертификатов в параметр -CAfile.
Гленджамин
2
-untrustedне проверяет, является ли цепочка сертификатов полностью действительной. Пожалуйста, подумайте о том, чтобы передать как промежуточный, так и root в команду, -CAfileкак предлагает другие вопросы.
Envek
2
Используйте -untrusted для Intermediate.pem, если возможно следующее: mail.python.org/pipermail/cryptography-dev/2016-August/…
Грег Сметеллс
2
Это не то, о чем просил OP, но если вы хотите проверить НЕ самоподписанную цепочку, используйте файл CA системы / браузера вместо своего собственного. Например, в OS X с openssl из домашнего использования:openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
Грег Дубицки,
50

Это одна из немногих законных вакансий для cat:

openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem

Обновить:

Как указывает в комментариях Грег Сметеллс, эта команда неявно доверяет Intermediate.pem . Я рекомендую прочитать первую часть поста Ссылки Грега (вторая часть специально посвящена pyOpenSSL и не имеет отношения к этому вопросу).

На случай, если пост уйдет, процитирую важные абзацы:

К сожалению, «промежуточный» сертификат, который на самом деле является корневым / самозаверяющим, будет рассматриваться как доверенный ЦС при использовании указанной выше рекомендованной команды:

$ openssl verify -CAfile <(cat geotrust_global_ca.pem rogue_ca.pem) fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem: ОК

Кажется, openssl перестанет проверять цепочку, как только будет обнаружен корневой сертификат, который также может быть Intermediate.pem, если он самоподписанный. В этом случае RootCert.pem не рассматривается. Поэтому убедитесь, что Intermediate.pem исходит из надежного источника, прежде чем полагаться на приведенную выше команду.

Питер
источник
Будет ли это действительно проверять промежуточный сертификат на соответствие корневому сертификату?
augurar
Оно делает. Я просто повторно запустил команды с цепочкой, которая, как я знаю, верна (она обслуживает производственный трафик для моего работодателя), а затем снова с другим, не связанным корневым сертификатом. См. Суть стенограммы .
Питер
8
ВНИМАНИЕ: НЕ используйте это, если Intermediate.pem вообще ненадежен. Подробнее читайте здесь: mail.python.org/pipermail/cryptography-dev/2016-August/…
Грег Сметеллс
1
Спасибо, что указали на это, Грег. Когда я дал ответ, я загрузил как корневые, так и промежуточные файлы с домашних страниц эмитентов, поэтому эта мысль мне не пришла в голову. Я обновил ответ, чтобы прояснить, что эта команда напрямую доверяет промежуточному звену.
Питер
1
@somenickname, см. комментарий Тони. В любом случае предпочтительнее использовать параметр -untrusted. Я предлагаю вам задать свой вопрос, если вам нужна дополнительная помощь. Комментарии - не лучшее место для отладки вашей проблемы.
Питер
17

Проблема в том, что openssl -verifyэто не работает.

Как упоминал Прияди , openssl -verifyостанавливается на первом самоподписанном сертификате, поэтому вы на самом деле не проверяете цепочку, так как часто промежуточный сертификат самозаверяющий.

Я предполагаю, что вы хотите быть на 101% уверены, что файлы сертификатов верны, прежде чем пытаться установить их в продуктивной веб-службе. Этот рецепт выполняет именно эту предполетную проверку.

Обратите внимание, что ответ Питера правильный , однако вывод openssl -verifyне указывает на то, что после этого все действительно работает. Да, могут возникнуть некоторые проблемы, но не все.

Вот сценарий, который проверяет цепочку сертификатов перед ее установкой в ​​Apache. Возможно, это можно улучшить с помощью более мистической магии OpenSSL, но я не гуру OpenSSL и следующие работы:

#!/bin/bash
# This Works is placed under the terms of the Copyright Less License,
# see file COPYRIGHT.CLL.  USE AT OWN RISK, ABSOLUTELY NO WARRANTY. 
#
# COPYRIGHT.CLL can be found at http://permalink.de/tino/cll
# (CLL is CC0 as long as not covered by any Copyright)

OOPS() { echo "OOPS: $*" >&2; exit 23; }

PID=
kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; }
trap 'kick' 0

serve()
{
kick
PID=
openssl s_server -key "$KEY" -cert "$CRT" "$@" -www &
PID=$!
sleep .5    # give it time to startup
}

check()
{
while read -r line
do
    case "$line" in
    'Verify return code: 0 (ok)')   return 0;;
    'Verify return code: '*)    return 1;;
#   *)  echo "::: $line :::";;
    esac
done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/)
OOPS "Something failed, verification output not found!"
return 2
}

ARG="${1%.}"
KEY="$ARG.key"
CRT="$ARG.crt"
BND="$ARG.bundle"

for a in "$KEY" "$CRT" "$BND"
do
    [ -s "$a" ] || OOPS "missing $a"
done

serve
check && echo "!!! =========> CA-Bundle is not needed! <========"
echo
serve -CAfile "$BND"
check
ret=$?
kick

echo
case $ret in
0)  echo "EVERYTHING OK"
    echo "SSLCertificateKeyFile $KEY"
    echo "SSLCertificateFile    $CRT"
    echo "SSLCACertificateFile  $BND"
    ;;
*)  echo "!!! =========> something is wrong, verification failed! <======== ($ret)";;
esac

exit $ret

Обратите внимание, что вывод после EVERYTHING OK- это настройка Apache, потому что люди, использующие NginXили haproxyобычно могут читать и понимать это в совершенстве;)

Существует GitHub Gist, в котором могут быть некоторые обновления

Предпосылки для этого скрипта:

  • У вас есть данные доверенного корневого центра сертификации, /etc/ssl/certsкак обычно, например, в Ubuntu
  • Создайте каталог, в DIRкотором вы храните 3 файла:
    • DIR/certificate.crt который содержит сертификат
    • DIR/certificate.key который содержит секретный ключ для вашего веб-сервиса (без парольной фразы)
    • DIR/certificate.bundleкоторый содержит CA-Bundle. О том, как подготовить связку, читайте ниже.
  • Теперь запустите скрипт: ./check DIR/certificate(предполагается, что скрипт назван checkв текущем каталоге)
  • Это очень маловероятный случай, когда скрипт выводит CA-Bundle is not needed. Это означает, что вы (читайте /etc/ssl/certs/:) уже доверяете сертификату подписи. Но в WWW это маловероятно.
  • Для этого тестового порта 4433 не должен использоваться на вашей рабочей станции. И лучше запускать это только в безопасной среде, поскольку он вскоре откроет порт 4433 для публики, которая может увидеть внешние подключения во враждебной среде.

Как создать certificate.bundleфайл?

В WWW цепочка доверия обычно выглядит так:

  • доверенный сертификат от /etc/ssl/certs
  • неизвестные промежуточные сертификаты, возможно, перекрестно подписанные другим ЦС
  • ваш сертификат ( certificate.crt)

Теперь оценка происходит снизу вверх, это означает, что сначала ваш сертификат считывается, затем требуется неизвестный промежуточный сертификат, затем, возможно, сертификат с перекрестной подписью, а затем /etc/ssl/certsпроводится консультация для поиска правильного доверенного сертификата.

Пакет ca-bundle должен быть составлен в точном соответствии с правильным порядком обработки, это означает, что первый необходимый сертификат (промежуточный сертификат, который подписывает ваш сертификат) идет первым в пакете. Тогда потребуется сертификат с перекрестной подписью.

Обычно ваш CA (орган, подписавший ваш сертификат) уже предоставляет такой правильный файл ca-bundle. Если нет, вам нужно собрать все необходимые промежуточные сертификаты и catих вместе в один файл (в Unix). В Windows вы можете просто открыть текстовый редактор (например, notepad.exe) и вставить сертификаты в файл, первый из которых должен быть поверх остальных, а после остальных.

Есть еще кое-что. Файлы должны быть в формате PEM. Некоторые центры сертификации выдают формат DER (двоичный). PEM легко обнаружить: он читается в кодировке ASCII. Подробнее о том, как преобразовать что-либо в PEM, см. В разделе Как преобразовать .crt в .pem и следовать по дороге из желтого кирпича.

Пример:

У тебя есть:

  • intermediate2.crt промежуточный сертификат, который подписал ваш certificate.crt
  • intermediate1.crt еще один промежуточный сертификат, который подписал intermediate2.crt
  • crossigned.crt который является сертификатом перекрестной подписи от другого центра сертификации, который подписал intermediate1.crt
  • crossintermediate.crtкоторый является еще одним промежуточным звеном от другого подписанного CA crossigned.crt(вы, вероятно, никогда не увидите такого)

Тогда правильный catбудет выглядеть так:

cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle

А как узнать, какие файлы нужны или нет и в какой последовательности?

Что ж, экспериментируйте, пока checkвсе в порядке. Это похоже на компьютерную головоломку, в которой нужно разгадывать загадку. Каждый. Не замужем. Время. Даже для профи. Но каждый раз, когда вам нужно это делать, вы будете поправляться. Так что вы определенно не одиноки со всей этой болью. Это SSL, понимаешь? SSL, вероятно, является одним из худших проектов, которые я когда-либо видел за более чем 30 лет профессионального системного администрирования. Вы когда-нибудь задумывались, почему криптовалюта не стала мейнстримом за последние 30 лет? Поэтому. 'достаточно.

Tino
источник
Голосующему против: Пожалуйста, объясните, что не так с моим ответом. Спасибо.
Тино
2
Я один из тех, кто проголосовал против. Вот что вызвало отрицательный голос: «А как узнать, какие файлы нужны или нет и в какой последовательности? Ну, экспериментируйте, пока проверка не покажет, что все в порядке». Я не думаю, что SSL - это особый случай. У подобных проблем должно быть детерминированное решение.
ychaouche
2
@ychaouche Спасибо! Как и вы, мне нравятся детерминированные вещи. Вопрос был в том, «Что не так» и как это сделать с помощью «openssl verify». Поскольку мы находимся в stackoverflow, я объяснил это, после чего последовал программный (таким образом детерминированный) ответ да / нет. Вы даже можете использовать его для автоматизации проверок нового пакета перед его установкой в ​​производство. Это полностью отвечает на вопрос. Что вам не нравится, так это то, что я рассказал о разочаровании на тему «Как создать правильный пакет?». Поскольку я думаю, что на это не может быть короткого детерминированного ответа, ответ на этот вопрос был бы оффтопом в данном контексте.
Тино
6
«Как упоминал Прияди, openssl -verify останавливается на первом самоподписанном сертификате, поэтому вы на самом деле не проверяете цепочку, так как часто промежуточный сертификат самоподписанный». Очевидно, что промежуточные сертификаты никогда не являются самоподписанными (если бы они были корневыми сертификатами). И весь смысл проверки заключается в том, чтобы убедиться, что вы включили все сертификаты в цепочку до доверенного корневого сертификата. Именно это и делает openssl verify. Однако openssl имеет тенденцию быть довольно консервативным со своей политикой доверия ...
Тимо
4
«часто промежуточный сертификат самозаверяющий». Это неверно, и из-за такой путаницы в терминологии новичкам сложно понять тему, которая на самом деле довольно проста, если ее правильно объяснить. Из RFC 5280: «[...] сертификаты CA могут быть дополнительно разделены на три класса: перекрестные сертификаты, самовыданные сертификаты и самоподписанные сертификаты. Перекрестные сертификаты - это сертификаты CA, в которых эмитент и субъект являются разными объектами. . Перекрестные сертификаты описывают доверительные отношения между двумя центрами сертификации. [...] ".
Доктор Ян-Филип Герке
8

Мне нужно было проверить сертификат letsencrypt, и я сделал это так:

  1. Загрузите корневой сертификат и промежуточный сертификат из цепочки доверия letsencrypt .
  2. Выполните эту команду:

    $ openssl verify -CAfile letsencrypt-root-cert/isrgrootx1.pem.txt -untrusted letsencrypt-intermediate-cert/letsencryptauthorityx3.pem.txt /etc/letsencrypt/live/sitename.tld/cert.pem 
    /etc/letsencrypt/live/sitename.tld/cert.pem: OK
    
Майкл
источник
1
Что ж, кажется, Джону не понравилось то, что я сказал спасибо. Я настаиваю на жесте «Спасибо», поэтому вот удаленный текст: Надеюсь, это поможет вам с вашими сертификатами letsencrypt. Спасибо Прияди, ваше решение помогло мне найти эту команду. Пожалуйста, не забудьте проголосовать за его решение.
Майкл
5

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

Скриншот :

введите описание изображения здесь

praveen.chandran
источник
1
Не пытается ответить на вопрос о том, как пользоваться openssl verify.
binki
да, но этот вид инструментов может дать вам необходимую визуализацию такого рода вещей, если вы не понимаете загадочную информацию инструментов командной строки openssl :) Итак, вот мой голос за, могут быть некоторые онлайн-материалы, которые также делают это.
Дэвид 天宇 Вонг 01
2

Если вы хотите , чтобы убедиться , что эмитент в UserCert.pem действительности Intermediate.pem сделать следующее (пример использования: OpenSSL 1.1.1):

openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pem

и вы получите:

UserCert.pem: OK

или

UserCert.pem: verification failed
Маринос Ан
источник
есть ли эквивалентная команда openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pemв Python 3.7?
Богота
-5

Вы можете легко проверить цепочку сертификатов с помощью openssl. Полная цепочка будет включать сертификат CA, поэтому вы должны увидеть подробную информацию о CA и самом сертификате.

openssl x509 -in fullchain.pem -text -noout

jorfus
источник
4
1) Это совершенно без каких-либо объяснений. 2) это ответ на вопрос, который не задавал, без какого-либо контекста.
Шадур