所有加密的客户端流现在默认情况下都启用对等验证。默认情况下,这将使用 OpenSSL 的默认 CA 证书捆绑包来验证对等证书。在大多数情况下,无需进行任何更改即可与具有有效 SSL 证书的服务器通信,因为发行版通常将 OpenSSL 配置为使用已知的良好 CA 证书捆绑包。
可以通过设置 openssl.cafile 或 openssl.capath 配置设置在全局范围内覆盖默认的 CA 证书捆绑包,或者可以通过使用 cafile 或 capath 上下文选项在每个请求的基础上覆盖。
虽然通常不建议这样做,但可以通过将 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 并处理可能出现的任何兼容性问题。
现在可以通过 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() 已添加,用于创建、验证导出 PEM 公钥以及从 KeyGen HTML5 元素生成的 SPKAC 中关联的挑战。
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-----