所有加密的客户端流现在默认情况下都会启用对等验证。默认情况下,这将使用 OpenSSL 的默认 CA 捆绑包验证对等证书。在大多数情况下,不需要对与具有有效 SSL 证书的服务器进行通信进行任何更改,因为分发商通常会将 OpenSSL 配置为使用已知的良好 CA 捆绑包。
可以通过设置 openssl.cafile 或 openssl.capath 配置设置在全局范围内覆盖默认 CA 捆绑包,也可以通过使用 cafile 或 capath 上下文选项在每个请求的基础上覆盖默认 CA 捆绑包。
虽然一般不推荐,但可以通过将 verify_peer 上下文选项设置为 false
来禁用对某个请求的对等证书验证,并且可以通过将 verify_peer_name 上下文选项设置为 false
来禁用对等名称验证。
已添加对提取和验证证书指纹的支持。 openssl_x509_fingerprint() 已被添加以从 X.509 证书中提取指纹,并且已添加两个 SSL 流上下文 选项:capture_peer_cert
用于捕获对等的 X.509 证书,peer_fingerprint
用于断言对等的证书应与给定的指纹匹配。
PHP 使用的默认密码已更新为基于 » Mozilla 密码建议 的更安全的列表,并具有两个额外的排除:匿名 Diffie-Hellman 密码和 RC4。
可以通过新的 OPENSSL_DEFAULT_STREAM_CIPHERS
常量访问此列表,并且可以通过设置 ciphers
上下文选项来覆盖此列表(与以前的 PHP 版本一样)。
默认情况下已禁用 SSL/TLS 压缩以减轻 CRIME 攻击。PHP 5.4.13 添加了 disable_compression
上下文选项以允许禁用压缩:现在默认情况下将其设置为 true
(即,禁用压缩)。
已添加 honor_cipher_order
SSL 上下文选项以允许加密的流服务器通过优先考虑服务器的密码而不是客户端的密码来减轻 BEAST 漏洞。
现在可以通过 stream_get_meta_data() 或 stream_context_get_options() 访问加密流的协商协议和密码,前提是 capture_session_meta
SSL 上下文选项设置为 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" }
加密的客户端流已经支持完美前向保密,因为它通常由服务器控制。使用能够实现完美前向保密的证书的 PHP 加密的服务器流不需要采取任何额外措施来启用 PFS;但是,已添加了许多新的 SSL 上下文选项以允许对 PFS 进行更多控制,并处理可能出现的任何兼容性问题。
ecdh_curve
此选项允许选择特定曲线以与 ECDH 密码一起使用。如果未指定,将使用 prime256v1
。
dh_param
包含 Diffie-Hellman 密钥交换参数的文件的路径,例如由以下命令创建的文件
openssl dhparam -out /path/to/my/certs/dh-2048.pem 2048
single_dh_use
如果设置为 true
,则在使用 Diffie-Hellman 参数时将创建一个新的密钥对,从而提高前向保密性。
single_ecdh_use
如果设置为 true
,则在协商 ECDH 密码套件时将始终生成新的密钥对。这将提高前向保密性。
现在可以通过 crypto_method
SSL 上下文选项或通过在创建流包装器时指定特定传输来选择特定版本的 SSL 和 TLS(例如,通过调用 stream_socket_client() 或 stream_socket_server())。
crypto_method
SSL 上下文选项接受枚举允许的协议的位掩码,stream_socket_enable_crypto() 的 crypto_type
也是如此。
协议 | 客户端标志 | 服务器标志 | 传输 |
---|---|---|---|
任何 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
// 使用 file_get_contents() 时要求 TLS 1.0 或更高版本:
$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() 函数:它返回 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) "" }
添加了生成、提取和验证签名公钥和挑战 (SPKAC) 的支持。openssl_spki_new()、openssl_spki_verify()、openssl_spki_export_challenge() 和 openssl_spki_export() 已被添加,用于从 KeyGen
HTML5 元素生成的 SPKAC 创建、验证导出 PEM 公钥和相关挑战。
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
从 SPKAC 导出 PEM 格式的 RSA 公钥。
<?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-----