file_get_contents: невозможно установить локальный файл цепочки сертификатов
Мы используем composer для обновления зависимостей с помощью Satis. После недавнего обновления сервера мы не смогли этого сделать. Сужая возможные причины, мы обнаружили, что php-функция file_get_contents не работает при попытке установить ssl-соединение.
Мы используем следующий скрипт для тестирования нашего ssl:
<?php
$url = 'https://satis.work.com/packages.json';
$contextOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'local_cert' => '/home/work/.ssl/deployer.pem',
]
];
$sslContext = stream_context_create($contextOptions);
$result = file_get_contents($url, false, $sslContext);
echo $result, "\n";
Это брошено:
Предупреждение PHP: file_get_contents(): невозможно установить файл локальной цепочки сертификатов `/home/work/.ssl/deployer.pem'; Убедитесь, что в настройках вашего cafile / capath указаны данные вашего сертификата и его эмитента в /home/omlook/test-ssl.php в строке 12 Предупреждение PHP: file_get_contents(): не удалось включить шифрование в /home/work/test-ssl.php on line 12 Предупреждение PHP: file_get_contents ( https://satis.work.com/packages.json): не удалось открыть поток: сбой операции в /home/work/test-ssl.php в строке 12
Это определенно не проблема с правами или владением файлами, скрипт может читать.pem просто отлично. Что удивляет, так это то, что один и тот же сценарий и ключ.pem отлично работают в моей локальной среде, и различия в версиях не так существенны, как кажется.
Местная среда:
PHP 7.0.18-0ubuntu0.16.04.1 (cli) (NTS) Copyright (c) 1997-2017 PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies с Zend OPcache v7.0.18-0ubuntu0.16.04.1, Copyright (c) 1999-2017, Zend Technologies
OpenSSL 1.0.2g 1 марта 2016
Сервер:
PHP 7.1.7-1 + ubuntu14.04.1 + deb.sury.org + 1 (cli) (сборка: 7 июля 2017 г., 10:07:42) ( NTS) Copyright (c) 1997-2017 PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies с Zend OPcache v7.1.7-1+ubuntu14.04.1+deb.sury.org+1, Copyright (c) 1999-2017, Zend Technologies
OpenSSL 1.1.0f 25 мая 2017
1 ответ
Похоже, это происходит только в том случае, если вы пропустите метаданные открытого текста (Issuer, Validity и т. Д.) Перед частью "BEGIN CERTIFICATE" в файле PEM. Для более новых сборок PHP (включая 7.0) эта часть кажется обязательной. До сих пор я не узнал больше, но я думаю, что это скорее openssl-проблема. Обновление сертификата, включая часть метаданных, сгенерированную openssl, решило проблему для меня.
Решил за себя ту же проблему. Кажется, что метаданные в открытом виде не имеют значения. Подобный код работал у меня на php 7.0 с openssl 1.1.0j и был сломан на php 7.3 с openssl 1.1.1c - у меня такой же текст ошибки. Добавление метаданных в виде открытого текста мне не помогло. Добавлениеcafile
Параметр контекста с текущим сертификатом CA мне тоже не помог.
Когда я попытался сделать тот же запрос с помощью curl, у меня возникла ошибка:
curl -k --cert cert.pem https://myservice.com/soap/ShopService/
curl: (58) could not load PEM client certificate, OpenSSL error error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak, (no key found, wrong pass phrase, or wrong file format?)
Итак, я обнаружил, что существующий старый сертификат клиента был подписан слабым алгоритмом sha1WithRsaEncryption. Приватный ключ был длиной 2048 бит - это нормально (если у вас 1024 бит - сейчас это небезопасно, и вам также нужен новый более длинный ключ)
Я перевыпустил свой клиентский сертификат с фактическим хешем sha256 (опция openssl -sha256). У моего сертификата CA был такой же слабый хэш sha1, но менять его не нужно было, только сертификат клиента. Команды:
# here:
# cert.pem - my old client certificate with private key
# ca.pem - service's current CA certificate for signing client certificates with it's private key
# cert2.pem - my new working client certificate with the same old private key
#
# make new certificate request from current client certificate
openssl x509 -x509toreq -in cert.pem -out cert2.csr -signkey cert.pem -sha256
# make new certificate
openssl x509 -req -in cert2.csr -out cert2.pem -CA ca.pem -sha256 -days 730 -set_serial 0x51ca170d
# append private key
openssl rsa -in cert.pem >> cert2.pem
Часы боли и теперь все в порядке) Кажется, php отправляет неверное сообщение об ошибке для этой ошибки.