Проблема с сертификатом SSL: невозможно получить сертификат эмитента

В настоящее время я тестирую API на веб-сайте с сертификатом, выполняя php-скрипт, который использует curl, в командной строке на моем локальном компьютере с Windows. Но скрипту так и не удается добраться до сервера. Я искал решения для этой, по-видимому, частой ошибки и безуспешно пробовал следующее:

  • Убедился, что сертификат еще действителен.
  • Убедитесь, что расширение openssl php включено в php.ini и что .dll действительно существует.
  • Загружен последний пакет сертификатов с https://curl.haxx.se/docs/caextract.html, как объяснено в ответе на этот вопрос и добавил его в php.ini. Я также проверил, что центр сертификации веб-сайта, с которым я пытаюсь связаться, действительно находится в этом комплекте (в моем случае это Comodo).
  • Скачал более старый пакет сертификатов, срок действия которого ближе к началу срока действия сертификата веб-сайта.
  • Скачал сертификат непосредственно из центра сертификации по этой ссылке и добавил .crt в свой php .ini-файл.
  • Преобразовал полученный выше файл .crt в .pem с помощью этого инструмента, а затем добавил его в php.ini (заменив указанный выше).

Вот скрипт, который я использую для тестирования (я выполняю его с помощью php только в командной строке):

$data = 'username=myuser&password=mypassword';
$ch = curl_init('https://my.website.com/auth');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_VERBOSE, true);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_exec($ch);
curl_close($ch);

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

Во всех случаях я пробовал путь как с косой чертой, так и с обратной косой чертой, я уверен, что используется правильный php.ini и что php имеет доступ к местоположению файла .pem. Это подтверждается выводом php-скрипта (я заменил фактический URL-адрес, который я использую):

> *   Trying 192.168.200.11...
> * TCP_NODELAY set
> * Connected to my.website.com (192.168.200.11) port 443 (#0)
> * ALPN, offering http/1.1
> * successfully set certificate verify locations:   
> CAfile: C:\Development\examples\COMODORSADomainValidationSecureServerCA.pem  
> CApath: none
> * NPN, negotiated HTTP1.1
> * SSL certificate problem: unable to get issuer certificate
> * stopped the pause stream!
> * Closing connection 0

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


person Michaël Vreux    schedule 14.03.2019    source источник
comment
невозможность получить сертификат эмитента всегда означает, что вы получаете с удаленного конца сертификат, для которого локально вы не можете найти сертификат, подписывающий его. Сначала вам нужно будет точно узнать, какой именно сертификат вы получили и кто его выдал. Затем вам нужно обязательно добавить этот сертификат эмитента в соответствующее хранилище доверенных сертификатов.   -  person Patrick Mevzek    schedule 15.03.2019
comment
Трудная часть состоит в том, чтобы действительно знать, как на самом деле предполагается получить сертификат, необходимый curl. И теперь я могу поблагодарить Firefox за инструменты для этого.   -  person Michaël Vreux    schedule 15.03.2019
comment
Обновление 2020: firefox больше не может предоставлять необходимую мне функциональность, см. мой ответ ниже, чтобы найти более стабильный способ сделать это.   -  person Michaël Vreux    schedule 21.04.2020


Ответы (2)


Итак, в конце концов, вот как мне, наконец, удалось это сделать: как предполагает ошибка, и пара ответов также указывает на то, что цепочка сертификатов центра сертификации отсутствует в моей конфигурации и отсутствует в пакете, загруженном из https://curl.haxx.se/docs/caextract.html.

Действительно, для успешного подключения по HTTPS к веб-сайту помимо сертификата вашего собственного веб-сайта вам также потребуются дополнительные сертификаты, связанные с вашим центром сертификации. Это можно проверить в пути сертификации после экспорта сертификата веб-сайта и его визуализации с помощью предназначенного для этого инструмента. В Windows есть такой инструмент, который будет использоваться по умолчанию с файлами .cer, а не текстовый редактор.

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

Sectigo
   |_____Sectigo RSA Domain Validation Secure Server CA
            |_____*.example.com 

Мне пришлось получить по одному сертификату для каждой из 3 частей моего пути сертификации (всего 3 сертификата).

Итак, в конце концов, я нашел этот вопрос, который указал мне в правильном направлении: мне пришлось экспортировать сертификат моего веб-сайта в формате .cer (тот же формат, что и PEM, просто другое расширение), открыть мой сертификат в Windows и экспортировать каждую часть пути сертификации отдельно, чтобы получить все 3 сертификата.

Затем я скопировал все 3 сертификата в конец файла, загруженного с https://curl.haxx.se/docs/caextract.html , который я нашел в C:/Development/examples/cacert.pem (вы, вероятно, захотите поместить этот файл ближе к папке установки php).

Затем я изменил конфигурацию php.ini на

curl.cainfo=C:/Разработка/примеры/cacert.pem openssl.cafile=C:/Разработка/примеры/cacert.pem

И это сделало свое дело! Теперь я могу подключиться к сайту без проблем.

person Michaël Vreux    schedule 15.03.2019
comment
Подсказка: при экспорте сертификата выберите формат X.509 (.CER) с кодировкой Base-64, иначе вы не сможете скопировать его в файл .pem - person Jing He; 13.11.2020

Вы можете подключиться к серверу из командной строки с помощью curl?

curl -vs https://my.website.com/auth --cacert C:\Development\examples\COMODORSADomainValidationSecureServerCA.pem 

Возможно, есть несоответствие между сертификатом сервера и пакетом, который вы скачали, т.е. сертификата нет в пакете.

Если у вас установлен openssl, вы можете извлечь сертификат CA со своего сервера с помощью

openssl s_client -showcerts -servername server -connect server:443 > cacert.pem

Описание похожей проблемы можно найти здесь

person da-sha1    schedule 14.03.2019
comment
К сожалению, у меня нет среды Linux или cygwin, чтобы проверить это, но это дало важную подсказку о том, что проблема, возможно, в том, что вся цепочка сертификатов полностью или частично отсутствует, что действительно имело место! - person Michaël Vreux; 15.03.2019