PHP 5.6.x 中的 OpenSSL 更改

使用 SSL/TLS 时,流包装器现在默认情况下会验证对等证书和主机名

所有加密的客户端流现在默认情况下都会启用对等验证。默认情况下,这将使用 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 密码套件时将始终生成新的密钥对。这将提高前向保密性。

SSL/TLS 版本选择

现在可以通过 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() 已添加

已添加 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() 已被添加,用于从 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-----
添加注释

用户贡献的注释

此页面没有用户贡献的注释。
To Top