проверка SSL сертификата на соответствие корневому


Итак, у нас, например, имеется сертификат для установки, выданный кем-то, кто не предоставил корневой сертификат.

Нам нужно, чтоб при использовании этого сертификата не было ошибок. Таких, например, как эта:

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

Нам не хватает правильно сформированной цепочки корневых сертификатов.

Исходный сертификат проверяется по первому сертификату в этой цепочке, а далее тот первый проверяется по второму в цепочке и т.д., пока не упремся в доверенный корневой сертификат, хранящийся в локальном хранилище сертификатов (для Debian это /etc/ssl/certs/).

Для начала, узнаем, кто выдал наш сертификат:

openssl x509 -in <certificate.pem> -text -noout | grep -i issuer

Для примера возьмем групповой серификат *.google.com.

Можно скачать его вот так или же другим путем:

echo -n | openssl s_client -connect google.com:443 2>/dev/null |
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > wildcard.google.crt

Узнаем эмитента:

openssl x509 -in wildcard.google.com.crt -text -noout | grep -i issuer

Issuer: C=US, O=Google Inc, CN=Google Internet Authority
CA Issuers - URI:http://www.gstatic.com/GoogleInternetAuthority/GoogleInternetAuthority.crt

Проверим только что скачанный сертификат:

openssl verify wildcard.google.com.crt
wildcard.google.com.crt: C = US, ST = California, L = Mountain View, O = Google Inc, CN = *.google.com.ph
error 20 at 0 depth lookup:unable to get local issuer certificate

Пройдем по ссылке эмитента и получим первый сертификат в будущей цепочке:

wget http://www.gstatic.com/GoogleInternetAuthority/GoogleInternetAuthority.crt

Проверим его:

openssl verify GoogleInternetAuthority.crt
GoogleInternetAuthority.crt: OK

Значит второго сертификата в цепочке не будет. Кто же выдал сертификат эмитенту?

openssl x509 -in GoogleInternetAuthority.crt -text -noout | grep -i issuer
Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority

Ага, значит этот корневой сертификат должен лежать в нашем хранилище. Проверим:

ll /etc/ssl/certs/578d5c04.0
lrwxrwxrwx 1 root root 21 Sep  3 06:27 /etc/ssl/certs/578d5c04.0 -> Equifax_Secure_CA.pem
ls -la /etc/ssl/certs/Equifax_Secure_CA.pem
lrwxrwxrwx 1 root root 56 Sep  3 06:26 /etc/ssl/certs/Equifax_Secure_CA.pem -> /usr/share/ca-certificates/mozilla/Equifax_Secure_CA.crt

Попробуем проверить с директивой CApath на текущую директорию, чтобы убедиться, что это именно тот сертификат:

openssl verify -CApath ./ GoogleInternetAuthority.crt
GoogleInternetAuthority.crt: C = US, O = Google Inc, CN = Google Internet Authority
error 20 at 0 depth lookup:unable to get local issuer certificate

Ожидаемая, ошибка. Ну что ж, воссоздадим кусочек хранилища:

cp /usr/share/ca-certificates/mozilla/Equifax_Secure_CA.crt .

Посчитаем hash и сделаем символьную ссылку на него:

openssl x509 -noout -hash -in Equifax_Secure_CA.crt
578d5c04
ln -s Equifax_Secure_CA.crt 578d5c04.0

Проверям еще раз

openssl verify -CApath ./ GoogleInternetAuthority.crt
GoogleInternetAuthority.crt: OK

Теперь мы убедились, что это тот самый самый корневой сертификат.

Теперь проверим наш исходный групповой сертификат на соответствие цепочке.

openssl verify -CAfile GoogleInternetAuthority.crt wildcard.google.com.crt
wildcard.google.com.crt: OK

Всё отлично, можно устанавливать, если, конечно, ключ имеется :-)