воскресенье, 30 октября 2016 г.

OpenSSL: Ручная проверка сертификата по CRL

Перевод: OpenSSL: Manually verify a certificate against a CRL
Автор: Реми ван Элст (Remy van Elst)

Содержание
  1. Получение сертификата с CRL
  2. Получение цепочки сертификатов
  3. Соединение CRL и цепочки
  4. Проверка OpenSSL
  5. Отозванный сертификат
В этой статье будет показано, как можно вручную проверить сертификат по CRL. CRL означает Certificate Revocation List - список отозванных сертификатов - и является одним из способов проверки статуса сертификата. Этот способ является альтернативой для OCSP - Online Certificate Status Protocol - протокола интерактивного статуса сертификата.

Больше о CRL можно прочитать на Википедии.

Если нужно проверить сертификат по OCSP, обратитесь к другой моей статье.

Воспользуемся OpenSSL. Я использую такую версию:
$ openssl version
OpenSSL 1.0.2 22 Jan 2015
Получение сертификата с CRL

Для начала нужно получить сертификат проверяемого веб-сайта. Возьмём в качестве примера Википедию. Получить сертификат можно при помощи следующей команды:

openssl s_client -connect wikipedia.org:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p'
Сохраним вывод в файл, например, wikipedia.pem:
openssl s_client -connect wikipedia.org:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > wikipedia.pem
Теперь проверим, есть ли у этого сертификата URI CRL:
openssl x509 -noout -text -in wikipedia.pem | grep -A 4 'X509v3 CRL Distribution Points'
X509v3 CRL Distribution Points: # Точки распространения X509v3 CRL
    Full Name:                                                                           # Полное имя
      URI:http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl
Если ничего не выведено, значит у сертификата нет URI CRL. Его нельзя проверить по CRL.

Скачиваем CRL:
wget -O crl.der http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl
CRL имеет двоичный формат DER. Команде OpenSSL нужен файл в формате PEM (base64-кодированный DER), поэтому преобразуем его:
openssl crl -inform DER -in crl.der -outform PEM -out crl.pem
Получение цепочки сертификатов

Кроме проверяемого сертификата нужна цепочка сертификатов. Поэтому нужно получить цепочку сертификатов для проверяемого домена - wikipedia.org. Воспользовавшись опцией -showcerts команды openssl s_client, можно увидеть все сертификаты, принадлежащие цепочке:
openssl s_client -connect wikipedia.org:443 -showcerts 2>&1 < /dev/null
Будет выведено много текста, но нас интересует в нём следующее:
1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
-----BEGIN CERTIFICATE-----
MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB
hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln
aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME
GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB
INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a
vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j
CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X
dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE
JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY
Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E=
-----END CERTIFICATE-----
Как можно увидеть, это номер 1. Номер 0 - это сертификат Википедии, который у нас уже есть. Если у проверяемого сайта в цепочке имеется больше сертификатов, они все будут отображены. Сохраним все сертификаты в том порядке, в котором их вывел OpenSSL (первый, который непосредственно выпустил сертификат проверяемого сервера, затем тот, который выпустил этот сертификат и так далее с корневым или самым корневым в конце файла) в файл с именем chain.pem.

Можно использовать следующую команду для сохранения всех сертификатов, выведенных командой OpenSSL, в файл с именем chain.pem. Обратитесь к этой статье за более подробной информацией.
OLDIFS=$IFS; \
IFS=':' certificates=$(openssl s_client -connect wikipedia.org:443 -showcerts -tlsextdebug -tls1 2>&1 < /dev/null \
                         | sed -n '/-----BEGIN/,/-----END/ {/-----BEGIN/ s/^/:/; p}'); \
for certificate in ${certificates#:}; do \
  echo $certificate | tee -a chain.pem ; \
done; \
IFS=$OLDIFS
Объединение CRL и цепочки

Команде openssl для проверки нужны цепочка сертификатов и CRL в формате PEM, соединённые вместе. Можно пропустить CRL, но тогда проверка по CRL не будет выполнена, произойдёт проверка только сертификата по цепочке.
cat chain.pem crl.pem > crl_chain.pem
Проверка OpenSSL
Теперь у нас есть все данные, необходимые для проверки сертификата.
$ openssl verify -crl_check -CAfile crl_chain.pem wikipedia.pem
wikipedia.pem: OK
Результат показывает, что сертификат действительный.

Отозванный сертификат

Если имеется отозванный сертификат, его так же можете проверить способом, описанным выше. Ответ будет выглядеть следующим образом:
$ openssl verify -crl_check -CAfile crl_chain.pem revoked-test.pem
revoked-test.pem: OU = Domain Control Validated, OU = PositiveSSL, CN = xs4all.nl
error 23 at 0 depth lookup:certificate revoked                                    # ошибка 23 на 0 глубине поиска: сертификат отозван
Имея сертификат и цепочку, эти проверки можно выполнить странице Verisign для проверки отозванных сертификатов: https://test-sspev.verisign.com:2443/test-SSPEV-revoked-verisign.html.

6 комментариев:

Анонимный комментирует...

Это проверка локально, то есть подсунуть ему и CA_crt.pem и CRL.pem, но как организовать проверку, чтобы CRL он сам закачивал из CDP который указан в сертификате?

morbo комментирует...

Попробуйте написать скрипт.

Анонимный комментирует...

суть не в том как преобразовать выше указанный механизм проверки, а как проверить работу CDP?

Я разобрал относительно большой объём информации по этому поводу, но тем не менее у меня возникает вопрос как убедиться что система отозванных сертификатов действительно будет у меня работать и как она вообще в целом работает.

Если в сертификате есть расширение CDP, то программы перед работой с сертификатом ВСЕГДА В ОБЯЗАТЕЛЬНОМ ПОРЯДКЕ будут пытаться скачать CRL? Если у них не вдруг получиться (например ресурс не работает) они будут считать сертификат не действительным?

Вот создал я сертификат, отозвал его, создал список CRL и выложил его на ресурсе, который указан в CDP и к которому проверил доступ через браузер. Хотелось бы провести проверку при которой я буду уверен, что я всё сделал правильно, что CRL лежит в должном виде, нужном месте и программы будут проверять CRL перед работой с сертификатом? То есть хотелось бы знать возможность проверить сертификат так как будто это делает одна из программ перед работой с ним.

morbo комментирует...

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

Анонимный комментирует...

смысл тогда вообще в CDP если предлогается CRL на каждый сервер выкладывать?

morbo комментирует...

>смысл тогда вообще в CDP если предлогается CRL на каждый сервер выкладывать?

А вы документацию почитайте на сервер, которым собираетесь пользоваться. Большинство серверов только из локальных файлов умеет брать CRL. Вот, например, описана настройка CRL на сервере OpenVPN:

http://mdex-nn.ru/page/blokirovka-sertifikat-openvpn.html

Там для обновления CRL используется скрипт revoke-full. Подобным же образом это делается и в случае других серверов - почтовых серверов, веб-серверов и т.п.

В общем случае библиотека SSL не содержит в себе HTTP-клиента, который мог бы учесть все нюансы: наличие HTTP-прокси, SOCKS-прокси, состояние коммутируемого подключения и команду для его установления, адреса DNS-серверов и т.п.

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

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