Как перечислить сертификаты, которым доверяет OpenSSL?

Насколько я понимаю, любое программное обеспечение, работающее с сертификатами X.509, может иметь собственную основу для принятия решения, является ли сертификат доверенным или нет.

AFAIK OpenSSL просто просматривает список (например,/etc/ssl/certs) и проверяет наличие сертификата там.

Есть ли способ OpenSSL перечислить все сертификаты, которым он доверяет? Я знаю, что могу сам проконсультироваться с этим файлом (по моей конкретной установке OpenSSL), но есть ли (не зависящий от установки) способ получить доверенный список из самого OpenSSL?

Ответ 1

AFAIK OpenSSL просто просматривает список (например,/etc/ssl/certs) и проверяет наличие сертификата там.

Нет, OpenSSL ничего не доверяет по умолчанию. Вы должны проинструктировать его, чему доверять. Там даже раздел часто задаваемых вопросов: " Почему <SSL program> не работает с ошибкой проверки сертификата? :

Обычно эта проблема указывается в сообщениях журналов, в которых говорится о "неспособности получить сертификат локального эмитента" или "сам подписанный сертификат". Когда сертификат проверяется, его корневой ЦС должен быть "доверен" OpenSSL, это обычно означает, что сертификат ЦС должен быть помещен в каталог или файл, а соответствующая программа настроена для его чтения. Программа OpenSSL "проверяет" ведет себя аналогичным образом и выдает аналогичные сообщения об ошибках: проверьте страницу проверки программы проверки (1) для получения дополнительной информации.

Вы также можете проверить свое соединение с Google, чтобы узнать, как работает OpenSSL:

$ openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
...
Start Time: 1407377002
Timeout   : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)

Обратите внимание, что вышеописанное не работает, потому что OpenSSL по умолчанию не доверяет GeoTrust Global CA. На самом деле, есть еще одна точка доверия в цепочке и Google Internet Authority G2.

Вы можете исправить ситуацию, сообщив OpenSSL, чему доверять. Ниже я использую параметр -CAfile с Google Internet Authority G2:

$ openssl s_client -connect google.com:443 -CAfile google-ca.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377196
Timeout   : 300 (sec)
Verify return code: 0 (ok)

Затем вы можете действовать как браузер, перейдя в cURL и загрузите cacert.pem. cacert.pem есть много cacert.pem сертификации:

$ openssl s_client -connect google.com:443 -CAfile cacert.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377356
Timeout   : 300 (sec)
Verify return code: 0 (ok)

Вы не так уж плохи, как браузер с его сотнями ЦС и подчиненными ЦС, но вы приближаетесь:

$ cat cacert.pem | grep -o "\-\-\-\-\-BEGIN" | wc -l
     153

Модель безопасности OpenSSL отличается от модели безопасности веб-приложений/браузера, где браузер содержит список доверенных привязок или точек доверия, известных как центры сертификации (CA). Примечание: в этой модели неправильный CA может претендовать на сертификацию сайта, и браузер не будет более мудрее.

Это произошло в прошлом, и, скорее всего, это произойдет в будущем. Для хорошей истории забавного бизнеса PKIX см. " История рисков CAcert". Например, вы знаете, что Google Internet Authority G2 и GeoTrust Global CA сертифицируют сайты Google. Нет никаких оснований для того, чтобы голландский CA, названный Diginotar, требовал, чтобы удостоверить их, или французское Агентство кибернетической защиты, чтобы требовать их удостоверения.

Связано с моделями безопасности: еще одна проблема с моделью веб-приложений/браузеров заключается в том, что вы не можете упаковать один якорь доверия или CA, необходимый для вашего приложения, и использовать его (при условии, что у вас есть доверенный канал распространения). Ваши сертификаты попадают в кучу в CA Zoo. Другие могут претендовать на сертификацию вашего сайта, и вы можете претендовать на сертификацию других сайтов.

Модель безопасности - одна из причин, по которой веб-приложения отсылаются к данным с низким значением. Веб-приложения не должны обрабатывать данные среднего или высокого значения, потому что мы не можем размещать необходимые элементы управления безопасностью.


Есть ли способ OpenSSL перечислить все сертификаты, которым он доверяет?

Нет необходимости, так как в списке есть 0 участников :)


Также см. Как узнать путь для доверенного сертификата openssl? ,

Ответ 2

Недавно я изучил это и не нашел способа получить OpenSSL для списка сертификатов в его доверенном наборе. Лучшим способом, который я нашел, было, как вы заметили, "сам проконсультироваться с этим файлом [/etc/ssl/certs] (при моей конкретной установке OpenSSL)".

Вы можете быть более независимыми от установки в поиске каталога, с которым справляется OpenSSL. openssl version -d печатает путь к ней.

% openssl version -d
OPENSSLDIR: "/opt/local/etc/openssl"

OpenSSL ищет здесь файл с именем cert.pem и подкаталог certs/. Сертификаты он находит там рассматриваются как доверяют openssl s_client и openssl verify (источник: статья, Что сертификат власти признает, OpenSSL).

Итак, вы можете сделать что-то вроде:

% find -H 'openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/''/(cert.pem|certs) \ 
-type f -exec cat {} \+  

Это отображает все содержимое файлов, которые OpenSSL ожидает содержать сертификаты. Если вы хотите меньше, чем весь файл, замените cat соответствующими командами.

Ответ 3

Мне интересно, изменилось ли это с момента ответа.

Если я отправлю: $ openssl s_client -connect google.com:443

Он успешно работает, извлекает 4 общих сертификата и возвращает:

Start Time: 1484661709
Timeout   : 300 (sec)
Verify return code: 0 (ok)

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