Todos los flujos encriptados de clientes ahora habilitan la verificación del par por omisión. De manera predeterminada se usará el paquete de CA predeterminado de OpenSSL para verificar el certificado del par. En la mayoría de los casos no será necesario realizar ningún cambio para comunicarse con servidores que posean certificados SSL válidos, ya que los distribuidores generalmente configuran OpenSSL para que emplee paquetes de CA bien conocidos.
El paquete de CA podría ser sobrescrito globalmente estableciendo
la opción de configuración openssl.cafile u openssl.capath, o en función de
cada petición, usando las opciones de contexto
cafile
o
capath
.
Aunque no se recomienda en general, es posible deshabilitar la verificación
del certificado del par para una petición estableciendo la opción de contexto
verify_peer
a false
, y para deshabilitar la validación del nombre del par estableciendo
a false
la opción de contexto
verify_peer_name
.
Se ha añadido soporte para extraer y verificar las huellas digitales de los
certificados. openssl_x509_fingerprint() se ha añadido para
extraer una huella digital de un certificado X.509 y dos
opciones de contexto de flujo SSL han sido
añadidas: capture_peer_cert
para capturar el certificado X.509
del par y peer_fingerprint
para asegurar que el
certificado del par debe coincidir con la huella digital dada.
Los cifrados por defecto usados por PHP han sido actualizados a una lista más segura basada en las » recomendaciones de cifrado de Mozilla, con dos exclusiones adicionales: cifrados Diffie-Hellman anónimos y RC4.
Esta lista es accesible a través de la nueva constante
OPENSSL_DEFAULT_STREAM_CIPHERS
y puede ser reemplazada
(como en versiones anteriores de PHP) definiendo la opción de contexto
cifrados
.
La compresión SSL/TLS ha sido desactivada por defecto para mitigar el ataque CRIME.
PHP 5.4.13 añadió una opción de contexto
disable_compression
para permitir que la compresión sea desactivada: ahora está establecida en
true
(es decir, la compresión está desactivada) por defecto.
La opción de contexto SSL honor_cipher_order
ha sido
añadida para permitir a los servidores de flujos cifrados mitigar las
vulnerabilidades de BEAST prefiriendo los cifrados del servidor sobre el cliente.
El protocolo y el cifrado que han sido negociados para un flujo cifrado
ahora pueden ser accedidos a través de stream_get_meta_data()
o stream_context_get_options() cuando la opción de
contexto SSL capture_session_meta
está establecida en 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);
?>
El resultado del ejemplo sería:
array(4) { ["protocol"]=> string(5) "TLSv1" ["cipher_name"]=> string(20) "ECDHE-RSA-AES128-SHA" ["cipher_bits"]=> int(128) ["cipher_version"]=> string(11) "TLSv1/SSLv3" }
Los flujos de clientes cifrados ya soportan la confidencialidad persistente, ya que generalmente es controlado por el servidor. Los flujos de servidores cifrados en PHP usando certificados capaces de confidencialidad persistente no necesitan tomar medidas adicionales para habilitar PFS; sin embargo, se han añadido varias nuevas opciones de contexto SSL para permitir un mayor control sobre PFS y manejar problemas de compatibilidad que puedan surgir.
ecdh_curve
Esta opción permite seleccionar una curva específica para usar con
los cifrados ECDH. Si no se especifica, se usará prime256v1
.
dh_param
Ruta a un archivo que contiene parámetros para el intercambio de claves Diffie-Hellman, como el creado por el siguiente comando:
openssl dhparam -out /path/to/my/certs/dh-2048.pem 2048
single_dh_use
Si se establece en true
, se creará un nuevo par de claves al usar los
parámetros Diffie-Hellman, mejorando así la confidencialidad persistente.
single_ecdh_use
Si se establece en true
, siempre se generará un nuevo par de claves al
negociar las suites de cifrado ECDH. Esto mejora la confidencialidad persistente.
Ahora es posible seleccionar versiones específicas de SSL y
TLS a través de la opción de contexto SSL crypto_method
o
especificando un transporte específico al crear un manejador de flujo
(por ejemplo, llamando a stream_socket_client() o
stream_socket_server()).
La opción de contexto SSL crypto_method
acepta una máscara de bits
enumerando los protocolos que están permitidos, como lo hace el
crypto_type
de stream_socket_enable_crypto().
Protocolo(s) | Bandera cliente | Bandera servidor | Transporte |
---|---|---|---|
Cualquier versión TLS o SSL | STREAM_CRYPTO_METHOD_ANY_CLIENT |
STREAM_CRYPTO_METHOD_ANY_SERVER |
ssl:// |
Cualquier versión 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
// Requiriendo TLS 1.0 o mejor al usar file_get_contents():
$ctx = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
],
]);
$html = file_get_contents('https://google.com/', false, $ctx);
// Requiriendo TLS 1.1 o 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);
// Conexión usando el transporte de socket tlsv1.2://.
$sock = stream_socket_client('tlsv1.2://google.com:443/');
?>
Se ha añadido la función openssl_get_cert_locations(): devuelve las ubicaciones por defecto donde PHP buscará al buscar paquetes CA.
<?php
var_dump(openssl_get_cert_locations());
?>
El resultado del ejemplo sería:
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) "" }
Se ha añadido soporte para generar, extraer y verificar claves y desafíos públicos firmados (SPKAC).
openssl_spki_new(),
openssl_spki_verify(),
openssl_spki_export_challenge() y
openssl_spki_export() han sido añadidas para crear, verificar
la clave pública PEM de exportación y el desafío asociado de SPKAC generados
a partir de un elemento HTML5 KeyGen
.
openssl_spki_new
Genera un nuevo SPKAC usando la clave privada, string de desafío y el algoritmo de hashing.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
?>
El resultado del ejemplo sería:
SPKAC=MIIBXjCByDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3L0IfUijj7+A8CPC8EmhcdNoe5fUAog7OrBdhn7EkxFButUp40P7+LiYiygYG1TmoI/a5EgsLU3s9twEz3hmgY9mYIqb/rb+SF8qlD/K6KVyUORC7Wlz1Df4L8O3DuRGzx6/+3jIW6cPBpfgH1sVuYS1vDBsP/gMMIxwTsKJ4P0CAwEAARYkYjViMzYxMTktNjY5YS00ZDljLWEyYzctMGZjNGFhMjVlMmE2MA0GCSqGSIb3DQEBAwUAA4GBAF7hu0ifzmjonhAak2FhhBRsKFDzXdKIkrWxVNe8e0bZzMrWOxFM/rqBgeH3/gtOUDRS5Fnzyq425UsTYbjfiKzxGeCYCQJb1KJ2V5Ij/mIJHZr53WYEXHQTNMGR8RPm7IxwVXVSHIgAfXsXZ9IXNbFbcaLRiSTr9/N4U+MXUWL7
openssl_spki_verify
Verifica el SPKAC proporcionado.
<?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
Exporta el desafío asociado al SPKAC proporcionado.
<?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;
?>
El resultado del ejemplo sería:
challenge string
openssl_spki_export
Exporta la clave pública RSA en formato PEM del SPKAC.
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
echo openssl_spki_export($spkac);
?>
El resultado del ejemplo sería:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcvQh9SKOPv4DwI8LwSaFx02h7 l9QCiDs6sF2GfsSTEUG61SnjQ/v4uJiLKBgbVOagj9rkSCwtTez23ATPeGaBj2Zg ipv+tv5IXyqUP8ropXJQ5ELtbXPUN/gvw7cO5EbPHr/7eMhbpw8Gl+AfWxW5hLW8 MGw/+AwwjHBOwong/QIDAQAB -----END PUBLIC KEY-----