PHP 5.6.x における OpenSSL 関連の変更
ストリームラッパーが、SSL/TLS を使っている場合のピア証明書とホスト名の検証にデフォルトで対応
暗号化されたすべてのクライアントストリームで、ピア検証がデフォルトで有効になりました。 デフォルトでは、OpenSSL のデフォルト CA バンドルを使ってピア証明書を検証します。 たいていの場合は、正しい SSL 証明書を持つサーバーと通信するならこれを変更する必要はありません。 OpenSSL が、よく知られた CA バンドルを使うように設定されているからです。
デフォルトの CA バンドルを上書きすることもできます。
openssl.cafile あるいは openssl.capath を設定すればグローバルに変更でき、コンテキストオプション
cafile
あるいは
capath
を使えばリクエスト単位で変更できます。
一般的にはおすすめできませんが、
コンテキストオプション
verify_peer
を false
にしてリクエストでのピア証明書の検証を無効化することもできます。
また同じく、ピア名の検証も、コンテキストオプション
verify_peer_name
を false
にすれば無効化できます。
証明書のフィンガープリント
証明書のフィンガープリントの抽出と、その検証に対応しました。
新たに追加された openssl_x509_fingerprint() 関数が、
X.509 証明書からフィンガープリントを抽出します。また、
SSL ストリームコンテキスト
に二つのオプションが追加されました。
capture_peer_cert
はピアの X.509 証明書を取り込み、
peer_fingerprint
はピアの証明書が指定したフィンガープリントにマッチすることを確かめます。
デフォルトの暗号の更新
PHP がデフォルトで使う暗号が更新され、 » Mozilla cipher recommendations に基づいた、よりセキュアなリストになりました。 リストにない例外は、anonymous Diffie-Hellman ciphers と RC4 です。
新しい定数
OPENSSL_DEFAULT_STREAM_CIPHERS
で、この一覧にアクセスできます。
また、(過去のバージョンの PHP のように) 上書きもできます。上書きをするには、コンテキストオプション
ciphers
を設定します。
デフォルトでの圧縮の無効化
SSL/TLS の圧縮が、デフォルトで無効になりました。これは、CRIME 攻撃への対応です。
PHP 5.4.13 で新たにコンテキストオプション
disable_compression
が加わり、圧縮を無効にできるようになりました。そのデフォルト値が true
(つまり圧縮が無効になっている)
に変わったのです。
サーバーの暗号の優先が可能に
SSL コンテキストオプション 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" }
暗号化ストリームサーバーでの前方秘匿性に関する新たなオプション
暗号化クライアントストリームはすでに前方秘匿性に対応しています。 というのも、一般に前方秘匿性は、サーバーが制御するものだからです。 PHP の暗号化サーバーストリームが使っている証明書は前方秘匿性に対応しており、 何もしなくても有効になっています。 しかし、前方秘匿性に関してより決め細やかな制御をしたり、 互換性に関する問題に対応したりするために、 新たな SSL コンテキストオプションがいくつか追加されました。
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 のバージョンの選択
SSL や TLS の、特定のバージョンを指定できるようになりました。SSL コンテキストオプション
crypto_method
を利用するか、
あるいはストリームラッパーの作成時に
(stream_socket_client() あるいは
stream_socket_server() を呼んで)
トランスポートを指定します。
SSL コンテキストオプション crypto_method
には、
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() で、
SPKAC が HTML5 の KeyGen
要素から生成した
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
-
PEM フォーマットされた 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-----