2024 日本 PHP 研討會

PHP 5.6.x 中 OpenSSL 的變更

使用 SSL/TLS 時,串流包裝器現在預設會驗證對等憑證和主機名稱

現在所有加密的用戶端串流都預設啟用對等驗證。預設情況下,這將使用 OpenSSL 的預設 CA 捆綁包來驗證對等憑證。在大多數情況下,與具有有效 SSL 憑證的伺服器通訊不需要進行任何更改,因為發行商通常會將 OpenSSL 配置為使用已知的良好 CA 捆綁包。

可以透過設定 openssl.cafile 或 openssl.capath 設定,在全域範圍內覆寫預設的 CA 捆綁包,或者透過使用 cafilecapath 上下文選項,在每個請求的基礎上覆寫。

雖然一般不建議,但可以透過將 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 版本)。

預設停用壓縮

為了減輕 CRIME 攻擊,SSL/TLS 壓縮預設已停用。PHP 5.4.13 新增了 disable_compression 上下文選項以允許停用壓縮:現在預設設定為 true(即停用壓縮)。

允許伺服器優先使用其加密套件順序

已新增 honor_cipher_order SSL 上下文選項,以允許加密資料流伺服器透過優先使用伺服器的加密套件而非用戶端的加密套件來減輕 BEAST 漏洞。

存取協商的通訊協定和加密套件

capture_session_meta SSL 上下文選項設定為 true 時,現在可以透過 stream_get_meta_data()stream_context_get_options() 存取已為加密資料流協商的通訊協定和加密套件。

<?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),因為它通常由伺服器控制。使用支援 PFS 的憑證的 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 上下文選項或在建立串流包裝器時指定特定傳輸方式(例如,透過呼叫 stream_socket_client()stream_socket_server())來選擇特定版本的 SSL 和 TLS。

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() 函式,用於從 HTML5 KeyGen 元素產生的 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 匯出相關的 challenge。

<?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