Изменения OpenSSL в PHP 5.6.x
Обертки потоков теперь по умолчанию проверяют сертификаты узлов и имена хостов при использовании SSL/TLS
Все шифруемые клиентские потоки теперь по умолчанию включают проверку пиров. По умолчанию используется OpenSSL CA пакет для проверки сертификата пира. В большинстве случаев не требуется ничего делать для соединения с серверами с правильным SSL сертификатом, так как обычно OpenSSL уже настроен для использования хороших CA пакетов.
Стандартный CA пакет может быть переопределен глобально с помощью
установки или openssl.cafile или openssl.capath строк конфигурации,
или же на уровне каждого запроса используя опции контекста
cafile
или
capath
.
Хотя это и не рекомендуется, но можно отклчить проверку сертификата пира
для запроса, установив verify_peer
опцию контекста в false
, и можно отключить проверку имени пира, установив
verify_peer_name
в false
.
Сигнатура сертификата
Была добавлена поддержка извлечения и проверки сигнатуры сертификата.
Для извлечения сигнатур сертификатов X.509 добавлена функция
openssl_x509_fingerprint(). Также были добавлены две
опции контекста потока SSL:
capture_peer_cert
для захвата узлового сертификата X.509,
и peer_fingerprint
для проверки сертификата на соответствие
заданной сигнатуре.
Обновлены шифры по умолчанию
Список шифров по умолчанию, используемых PHP, был обновлен на более безопасный в соответствии с » рекомендациями по шифрам от Mozilla, с двумя дополнительными исключениями: анонимные шифры Диффи-Хеллмана и RC4.
Этот список доступен через новую константу
OPENSSL_DEFAULT_STREAM_CIPHERS
, и может быть переопределен
(как и в предыдущих версиях PHP) установкой опцией контекста
ciphers
.
Сжатие запрещено по умолчанию
Сжатие SSL/TLS было запрещено по умолчанию для compression уменьшения
вероятности атаки типа CRIME. В PHP 5.4.13 была добавлена опция контекста
disable_compression
для возможности запретить компрессию и теперь она по умолчанию установлена
как true
(то есть компрессия запрещена).
Разрешение серверу определять свой собственный порядок шифров
Была добавлена опция контекста honor_cipher_order
,
которая позволяет серверу обслуживающему зашифрованный поток самому
определять шифры, которыми будет пользоваться клиент. Это позволить снизить
риск атаки типа BEAST.
Доступ к согласованному протоколу и шифру
Протокол и шифр, согласованные для шифрованного потока, доступны
с помощью функций stream_get_meta_data() или
stream_context_get_options(), если опция контекста SSL
capture_session_meta
установлена как true
.
<?php
$ctx = stream_context_create(['ssl' => [
'capture_session_meta' => TRUE
]]);
$html = file_get_contents('https://google.com/', FALSE, $ctx);
$meta = stream_context_get_options($ctx)['ssl']['session_meta'];
var_dump($meta);
?>
Результат выполнения данного примера:
array(4) { ["protocol"]=> string(5) "TLSv1" ["cipher_name"]=> string(20) "ECDHE-RSA-AES128-SHA" ["cipher_bits"]=> int(128) ["cipher_version"]=> string(11) "TLSv1/SSLv3" }
Новые возможности для совершенной прямой секретности (PFS) для серверов, обслуживающих шифрованные потоки
Шифрованные потоки клиента уже поддерживают совершенную прямую секретность, поскольку она, как правило, контролируется сервером. Серверы PHP, обслуживающие шифрованные потоки, использующие сертификаты поддерживающие совершенную прямую секретность не нужнаются в каких либо дополнительных действиях для включения PFS; однако, было добавлено некоторое количество новых опций контекста SSL для более точного контроля над PFS и для решения возможных проблем.
-
ecdh_curve
-
Эта опция позволяет выбрать кривую для использования в шифрах ECDH. Если не задано, то будет использоваться
prime256v1
. -
dh_param
-
Путь к файлу, содержащему параметры для обмена ключами Диффи-Хеллмана, созданного, например, с помощью такой команды:
openssl dhparam -out /path/to/my/certs/dh-2048.pem 2048
-
single_dh_use
-
Если установлено как
true
, новая пара ключей будет создана, используя параметры Диффи-Хеллмана, тем самым улучшая прямую секретность. -
single_ecdh_use
-
Если установлено как
true
, новая пара ключей будет гненерироваться всегда, при согласовании шифра ECDH. Это улучшает прямую секретность.
Выбор версии SSL/TLS
Теперь возможно выбирать конкретную версию SSL и TLS с помощью опции
контекста crypto_method
или указывая конкретный
транспорт при создании обертки потока (например с помощью вызова
stream_socket_client() или
stream_socket_server()).
Опция контекста SSL crypto_method
принимает битовую
маску, перечисляющую допустимые протоколы, также как это задается в
параметре crypto_type
функции
stream_socket_enable_crypto().
Протокол | Флаг клиента | Флаг сервера | Транспорт |
---|---|---|---|
Любые версии TLS или SSL | STREAM_CRYPTO_METHOD_ANY_CLIENT |
STREAM_CRYPTO_METHOD_ANY_SERVER |
ssl:// |
Любая версия TLS | STREAM_CRYPTO_METHOD_TLS_CLIENT |
STREAM_CRYPTO_METHOD_TLS_SERVER |
tls:// |
TLS 1.0 | STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT |
STREAM_CRYPTO_METHOD_TLSv1_0_SERVER |
tlsv1.0:// |
TLS 1.1 | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
STREAM_CRYPTO_METHOD_TLSv1_1_SERVER |
tlsv1.1:// |
TLS 1.2 | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT |
STREAM_CRYPTO_METHOD_TLSv1_2_SERVER |
tlsv1.2:// |
SSL 3 | STREAM_CRYPTO_METHOD_SSLv3_CLIENT |
STREAM_CRYPTO_METHOD_SSLv3_SERVER |
sslv3:// |
<?php
// Требуется TLS 1.0 или выше для использования file_get_contents():
$ctx = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
],
]);
$html = file_get_contents('https://google.com/', false, $ctx);
// Требуется TLS 1.1 или 1.2:
$ctx = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
],
]);
$html = file_get_contents('https://google.com/', false, $ctx);
// Соединяемся с использованием транспорта потокового сокета tlsv1.2://
$sock = stream_socket_client('tlsv1.2://google.com:443/');
?>
Добавлена функция openssl_get_cert_locations()
Была добавлена функция openssl_get_cert_locations(): она возвращает расположения, в которых PHP будет искать пакеты CA по умолчанию.
<?php
var_dump(openssl_get_cert_locations());
?>
Результат выполнения данного примера:
array(8) { ["default_cert_file"]=> string(21) "/etc/pki/tls/cert.pem" ["default_cert_file_env"]=> string(13) "SSL_CERT_FILE" ["default_cert_dir"]=> string(18) "/etc/pki/tls/certs" ["default_cert_dir_env"]=> string(12) "SSL_CERT_DIR" ["default_private_dir"]=> string(20) "/etc/pki/tls/private" ["default_default_cert_area"]=> string(12) "/etc/pki/tls" ["ini_cafile"]=> string(0) "" ["ini_capath"]=> string(0) "" }
Поддержка SPKI
Была добавлена поддержка для создания, извлечения и проверки подписанных
публичных ключей и опознавательных строк (SPKAC).
Были добавлены функции openssl_spki_new(),
openssl_spki_verify(),
openssl_spki_export_challenge() и
openssl_spki_export() для создания, проверки экспорта PEM
публичных ключей и соответствующих опозновательных строк из SPKAC,
созданных из элементов HTML5 KeyGen
.
-
openssl_spki_new
-
Генерация нового SPKAC с использованием приватного ключа, опозновательной строки и алгоритма хеширования.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
?>Результат выполнения данного примера:
SPKAC=MIIBXjCByDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3L0IfUijj7+A8CPC8EmhcdNoe5fUAog7OrBdhn7EkxFButUp40P7+LiYiygYG1TmoI/a5EgsLU3s9twEz3hmgY9mYIqb/rb+SF8qlD/K6KVyUORC7Wlz1Df4L8O3DuRGzx6/+3jIW6cPBpfgH1sVuYS1vDBsP/gMMIxwTsKJ4P0CAwEAARYkYjViMzYxMTktNjY5YS00ZDljLWEyYzctMGZjNGFhMjVlMmE2MA0GCSqGSIb3DQEBAwUAA4GBAF7hu0ifzmjonhAak2FhhBRsKFDzXdKIkrWxVNe8e0bZzMrWOxFM/rqBgeH3/gtOUDRS5Fnzyq425UsTYbjfiKzxGeCYCQJb1KJ2V5Ij/mIJHZr53WYEXHQTNMGR8RPm7IxwVXVSHIgAfXsXZ9IXNbFbcaLRiSTr9/N4U+MXUWL7
-
openssl_spki_verify
-
Проверка предоставленного SPKAC.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
var_dump(openssl_spki_verify($spkac));
?> -
openssl_spki_export_challenge
-
Экспорт связанной опознавательной строки из предоставленного SPKAC.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
$challenge = openssl_spki_export_challenge($spkac):
echo $challenge;
?>Результат выполнения данного примера:
challenge string
-
openssl_spki_export
-
Экспорт публичного ключа RSA в формате из SPKAC.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
echo openssl_spki_export($spkac);
?>Результат выполнения данного примера:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcvQh9SKOPv4DwI8LwSaFx02h7 l9QCiDs6sF2GfsSTEUG61SnjQ/v4uJiLKBgbVOagj9rkSCwtTez23ATPeGaBj2Zg ipv+tv5IXyqUP8ropXJQ5ELtbXPUN/gvw7cO5EbPHr/7eMhbpw8Gl+AfWxW5hLW8 MGw/+AwwjHBOwong/QIDAQAB -----END PUBLIC KEY-----