Сейчас будет много текста про HTTPS, SSL/TLS и сертификаты.
Вот есть у нас сайт https://voronezh.rt.ru/ Если зайти на него браузером и посмотреть на сертификат, то мы увидим цепочку из 3-х сертификатов.
Если же проверить сертификат через openssl s_client -connect habr.com:443
, то там тоже 3 сертификата:
Certificate chain
0 s:/C=RU/ST=Moscow/L=Moscow/O=PJSC Rostelecom/OU=IT Department/CN=*.rt.ru
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
2 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
Вроде всё понятно и логично - к чему тут вопросы? Количество сертификатов совпадает, названия тоже - всё прекрасно.
Но мне этого мало. Идём дальше.
Давайте посмотрим на https://github.com/
В браузере мы увидим цепочку из 3-х сертификатов.
А вот через openssl
уже только два:
Certificate chain
0 s:/businessCategory=Private Organization/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/serialNumber=5157550/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=github.com
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
И тут уже появляется вопрос - почему браузер показываем мне в цепочке 3 сертификата (до корневого), хотя сам их видит только два?
Ну да ладно - они есть в трастах он от туда их и получил, да?
А давайте заглянем ещё глубже?
Откроем для себя https://www.goszakup.gov.kz/
В браузере мы увидим цепочку из 3-х сертификатов, хотя он верещит что они не валидные и совершенно верно - корневой сертификат Казахстанского УЦ мало кто себе ставит.
Ну три так три, да? Всё красиво, по мануалам - есть корневой ЦС, есть промежуточные (один, но всё же) - красота.
Пока не спустишься на сетевой уровень: openssl
считает что сервер возвращает всего 1 сертификат:
Certificate chain
0 s:/CN=*.GOSZAKUP.GOV.KZ/serialNumber=IIN810603350142/C=KZ/L=\xD0\x90\xD0\xA1\xD0\xA2\xD0\x90\xD0\x9D\xD0\x90/ST=\xD0\x90\xD0\xA1\xD0\xA2\xD0\x90\xD0\x9D\xD0\x90/O=\xD0\xA0\xD0\x95\xD0\xA1\xD0\x9F\xD0\xA3\xD0\x91\xD0\x9B\xD0\x98\xD0\x9
A\xD0\x90\xD0\x9D\xD0\xA1\xD0\x9A\xD0\x9E\xD0\x95 \xD0\x93\xD0\x9E\xD0\xA1\xD0\xA3\xD0\x94\xD0\x90\xD0\xA0\xD0\xA1\xD0\xA2\xD0\x92\xD0\x95\xD0\x9D\xD0\x9D\xD0\x9E\xD0\x95 \xD0\xA3\xD0\xA7\xD0\xA0\xD0\x95\xD0\x96\xD0\x94\xD0\x95\xD0\x9D\x
D0\x98\xD0\x95 "\xD0\x9C\xD0\x98\xD0\x9D\xD0\x98\xD0\xA1\xD0\xA2\xD0\x95\xD0\xA0\xD0\xA1\xD0\xA2\xD0\x92\xD0\x9E \xD0\xA4\xD0\x98\xD0\x9D\xD0\x90\xD0\x9D\xD0\xA1\xD0\x9E\xD0\x92 \xD0\xA0\xD0\x95\xD0\xA1\xD0\x9F\xD0\xA3\xD0\x91\xD0\x9B\xD
0\x98\xD0\x9A\xD0\x98 \xD0\x9A\xD0\x90\xD0\x97\xD0\x90\xD0\xA5\xD0\xA1\xD0\xA2\xD0\x90\xD0\x9D"/OU=BIN201040000013/[email protected]
i:/C=KZ/CN=\xD2\xB0\xD0\x9B\xD0\xA2\xD0\xA2\xD0\xAB\xD2\x9A \xD0\x9A\xD0\xA3\xD3\x98\xD0\x9B\xD0\x90\xD0\x9D\xD0\x94\xD0\xAB\xD0\xA0\xD0\xA3\xD0\xA8\xD0\xAB \xD0\x9E\xD0\xA0\xD0\xA2\xD0\x90\xD0\x9B\xD0\xAB\xD2\x9A (RSA)
---
И тут вопрос "откуда браузер взял остальные 2" для меня становится уже ребром.
Дело в том что если выполнять подключение Java-клиентом, например через OkHttp, то к моменту валидации мы получим ровно столько сертификатов сколько видно на сетевом уровне.
В случае ГосЗакупок РК - один сертификат. И если у нас в трастах лежит сертификат УЦ РК, то валидацию серверный сертификат не пройдёт, так как мы не можем построить цепочку до доверяемого сертификата.
Спрашивается - откуда браузер вытащил остальные 2 сертификата?
Изначальный вопрос не касается сайт ГосЗакупок РК. Вопрос касается сайта заказчика в закрытой сети так что его я упоминать не могу, но смысл тот же: на сетевом уровне сертификат один, а браузер показывает 3 и, так как доверяет этому УЦ, то считает их валидными, а приложение не может построить цепочку и отказывает в коннекте.
Где-то скрыта магия.
И вроде я нашёл где эта магия скрыта Есть поля "Authority Information Access"/"Доступ к сведениям центра сертификации" и там под ключом "Certification Authority Issuer"/"Поставщик центра сертификации" (1.3.6.1.5.5.7.48.2) прописан адрес сертификата, который выпустил наше сертификат. Скорее всего это сделано для уменьшение трафика при выполнении "рукопожатия": вместо того чтобы отправлять нам всю цепочку, сервер отправляет только один сертификат, а клиент уже докачивает нужное сам, в том числе используя внутренний кеш.
P.S. Возможно кто-то скажет "я это и раньше знал" - я рад. Я не знал :)