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 отправляет неверное сообщение об ошибке для этой ошибки.

Другие вопросы по тегам