Проверка ЦС PHP и SSL - Не зависит от операционной системы


Вот простой PHP-скрипт, который открывает SSL-сокет, готовый для отправки HTTP-запросов:

$contextOptions = array();

$socketUrl = 'ssl://google.com:443';
$streamContext = stream_context_create($contextOptions);
$socket = stream_socket_client($socketUrl, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $streamContext);

if (!$socket || $errno !== 0) {
    var_dump($socket, $errstr);
    exit;
}

var_dump($socket);
exit('Socket created.');

Это работает - я только что протестировал его, - но нет проверки в доверенном хранилище ЦС.

Мы можем изменить этот скрипт, чтобы использовать параметры контекста SSL PHP :

$contextOptions = array(
    'ssl' => array(
        'cafile' => 'C:\xampp\cacerts.pem',
        'CN_match' => '*.google.com',  // CN_match will only be checked if 'verify_peer' is set to TRUE.  See https://bugs.php.net/bug.php?id=47030.
        'verify_peer' => TRUE,
    )
);

$socketUrl = 'ssl://google.com:443';
$streamContext = stream_context_create($contextOptions);
$socket = stream_socket_client($socketUrl, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $streamContext);

if (!$socket || $errno !== 0) {
    var_dump($socket, $errstr);
    exit;
}

var_dump($socket);
exit('Socket created.');

Пока "cafile" существует и имеет правильный CA, этот пример также работает...

...но как мы можем сделать это без жесткого кодирования имени файла/пути к файлу CA? Мы пытаемся создать что-то, что проверяет сертификаты SSL независимо от операционной системы, не требуя отдельной настройки для каждого сервера, на котором выполняется этот сценарий.

Я знаю, что в Linux есть каталог для CAS, который мы могли бы поместить как "capath". А как насчет Окон? Где он хранит свои доверенные центры сертификации? Я искал, и они, к сожалению, оказались в реестре, так что мы никак не можем получить к ним доступ с PHP? Как насчет других операционных систем?

Author: Pete171, 2013-04-30

1 answers

Проигранная битва...

Невозможно выполнить безопасную зашифрованную передачу в PHP без ручной настройки параметров контекста "cafile" и "CN_match" до PHP 5.6. И, к сожалению, даже если вы правильно установите эти значения, ваши передачи все равно с большой вероятностью завершатся неудачей, потому что версии до 5.6 не консультируются со все более популярным расширением SAN (subjectAltName), присутствующим в одноранговых сертификатах при проверке имен хостов. В результате "безопасное" шифрование встроенные в PHP обертки потоков в значительной степени являются неправильным названием. Ваша самая безопасная ставка (буквально) с более старыми версиями PHP - это расширение curl.

Что касается сертификатов Windows...

Windows использует собственное хранилище сертификатов и кодирует свои сертификаты в формате, отличном от OpenSSL. Для сравнения, приложения openssl используют open.Формат PEM. Версии PHP до версии 5.6 не могут каким-либо образом взаимодействовать с хранилищем сертификатов Windows. По этой причине невозможно иметь надежные и безопасное шифрование в кросс-операционной системе с использованием встроенной функции оболочки потока.

PHP 5.6 - это важный шаг вперед

  • Новые директивы openssl.cafile и openssl.capath php.ini позволяют глобально назначать местоположения сертификатов, не устанавливая их в каждом контексте потока

  • Все зашифрованные потоки по умолчанию проверяют сертификаты одноранговых узлов и имена хостов, и имя хоста автоматически анализируется из URI, если параметр контекста "CN_match" отсутствует предоставленный.

  • Потоковые криптографические операции теперь проверяют записи SAN однорангового сертификата при проверке имен хостов

  • Если в контексте потока не указан файл/путь CA или директив php.ini, PHP автоматически возвращается в хранилища сертификатов операционной системы (в Windows тоже!)

В качестве примера, это все, что вам нужно сделать, чтобы безопасно подключиться к github.com в PHP-5.6:

<?php
$socket = stream_socket_client("tls://github.com:443");

Да. Это действительно так. Никакой суеты по поводу настройки контекста и параметры проверки. В этом отношении PHP теперь работает так же, как ваш браузер.

Больше чтения на эту тему

Эти изменения PHP 5.6 являются лишь верхушкой айсберга в отношении улучшений SSL/TLS. Мы упорно трудились, чтобы сделать 5.6 самым безопасным выпуском PHP на сегодняшний день в отношении зашифрованных сообщений.

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

Примечание о соответствии SAN в 5.4/5.5

Мы работаем над тем, чтобы перенести, по крайней мере, соответствие SAN в ветви 5.4 и 5.5, поскольку без этой функции чрезвычайно сложно использовать оболочки шифрования каким-либо значимым образом (в качестве клиента). Хотя эта работа по бэкпорту в значительной степени зависит от моего свободного времени в качестве волонтера, и этот ответ, безусловно, может помочь этому произойти раньше:)

 13
Author: rdlowrey, 2014-02-25 12:48:09