Для получения сертификатов HTTPS-сервера использую openssl s_client -showcerts с явным SNI. Команда показывает сертификаты, которые сервер прислал этому клиенту; она не достраивает цепочку и не доказывает подлинность сертификатов. Это различие прямо отмечено в документации OpenSSL: -showcerts.
Посмотреть цепочку
Команды ниже предназначены для Bash: Linux, macOS или Git Bash на Windows. Нужны уже доступные openssl, sed и, для разделения файла, awk. В PowerShell перенаправление </dev/null не работает: приложение терминала и оболочка внутри него — разные вещи.
openssl s_client -showcerts -connect www.example.com:443 -servername www.example.com </dev/null-connect задаёт адрес соединения, -servername — имя SNI для выбора виртуального HTTPS-сервера. Нужно прочитать раздел Certificate chain: s: — subject сертификата, i: — issuer. В выводе также есть сроки действия и отдельные блоки PEM. Корневой CA сервер может не прислать. Опции OpenSSL s_client.
Для ручного сохранения скопировать весь нужный блок от -----BEGIN CERTIFICATE----- до -----END CERTIFICATE-----, включая границы, и сохранить текст с расширением .crt. Если блоков несколько, это несколько сертификатов, а не один длинный сертификат.
Сохранить все присланные сертификаты
Имя server-chain.crt учебное. Перенаправление > перезаписывает существующий файл, поэтому для нового поступления нужно выбрать свободное имя или сначала сохранить прежнюю версию.
openssl s_client -showcerts -connect www.example.com:443 -servername www.example.com </dev/null | sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > server-chain.crtСообщения проверки OpenSSL могут остаться на экране: в файл попадают PEM-блоки из stdout. Пустой файл или ошибка соединения не являются успешно скачанным сертификатом. Нужно проверить число блоков и состав:
grep -c '^-----BEGIN CERTIFICATE-----' server-chain.crt
openssl crl2pkcs7 -nocrl -certfile server-chain.crt | openssl pkcs7 -print_certs -nooutПоследняя команда выводит subject и issuer всех сертификатов сохранённого комплекта. Это просмотр состава, а не проверка доверия. OpenSSL crl2pkcs7 и pkcs7.
Выделить сертификаты по отдельности
Для импорта в Java truststore удобнее сохранить каждый нужный CA отдельно. Ниже пример, в котором после проверки состава установлено, что второй блок — нужный промежуточный CA. Номер нельзя переносить вслепую на другой сервер или новую выдачу.
awk '/-----BEGIN CERTIFICATE-----/{n++} n==2{print}' server-chain.crt | openssl x509 -out intermediate-ca.crt
openssl x509 -in intermediate-ca.crt -noout -subject -issuer -serial -dates -fingerprint -sha256Для другого блока заменить n==2 фактическим номером. openssl x509 читает первый PEM-сертификат из выбранного участка и записывает отдельный файл; затем нужно проверить его subject, issuer и SHA-256. OpenSSL x509.
Перед установкой доверия сверить отпечатки CA с администратором или другим доверенным источником. Совпадение имени CA, hostname или наличие сертификата в сетевом ответе недостаточно. Далее — импорт и проверка сертификатов в JVM.
Если разные клиенты получают разные сертификаты
Браузер, Java и OpenSSL могут видеть разные сертификаты одного hostname. Сравнивать нужно issuer, serial и SHA-256, а не только subject. Возможные причины включают разные прокси, сетевые пути и TLS-перехват, но результат сравнения сам по себе не устанавливает конкретную причину.
Java позволяет посмотреть сертификаты без импорта:
& "C:\Program Files\Java\jdk-21\bin\keytool.exe" -printcert -sslserver www.example.com:443 -vОднако отдельный запуск keytool не гарантирует тот же путь соединения, что у приложения. Если ошибка воспроизводится только в Gradle, нужно сравнивать ещё и сертификаты из его SSL-лога. Java keytool: -printcert и диагностика JVM.
Если сервер прислал неполную цепочку
Ошибки unable to get local issuer certificate и unable to verify the first certificate означают, что OpenSSL в этом запуске не смог проверить цепочку. По одному этому сообщению нельзя объявлять сервер неверно настроенным: у клиента могут отсутствовать нужные CA. Если -showcerts действительно показывает только сертификат сайта, промежуточные CA из этого ответа получить невозможно.
Предпочтительно получить доверенный комплект CA у администратора или исправить серверную выдачу цепочки. Если комплект найден на другом сервисе организации, одинаковое имя издателя ещё не доказывает совпадение ключа: нужно проверить сертификаты и подписи. Для диагностики с заранее проверенным корневым и набором промежуточных сертификатов:
openssl verify -CAfile root-ca.crt -untrusted intermediates.crt server.crtОжидаемый результат — server.crt: OK; это проверка построения цепочки с переданными файлами. Для отдельной проверки hostname добавить -verify_hostname www.example.com. OpenSSL verify.
У s_client по умолчанию ошибки верификации могут не останавливать соединение. CONNECTED и завершённая выдача сертификатов не означают успешную проверку TLS. Для проверки с явным CA используются -CAfile, -verify_return_error и -verify_hostname. Документация s_client.