Cambios de OpenSSL en PHP 5.6.x

Las envolturas de flujos ahora verifican los certificados del par y los nombres de host por omisión al utilizar SSL/TLS

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.

Huellas digitales de certificados

Se ha añadido soporte para extraer y verificar huellas digitales de certificados. Se ha añadido openssl_x509_fingerprint() para extraer una huella digital de un certificado X.509, y se han añadido dos opciones de contexto de flujo SSL: capture_peer_cert para capturar el certificado X.509 del par, y peer_fingerprint para confirmar que el certificado del par debería coincidir con la huella digital dada.

Cifradores predeterminados actualizados

Los cifradores predeterminados empleados por PHP han sido actualizados a una lista más segura basada en las » recomendaciones de cifradores de Mozilla, con dos exclusiones adicionales: cifradores Diffie-Hellman anónimos, y RC4.

Se puede acceder a la lista mediante la nueva constante OPENSSL_DEFAULT_STREAM_CIPHERS, y se puede sobrescribir (como en versiones anteriores de PHP) estableciendo la opción de contexto ciphers.

Compresión deshabilitada de forma predeterminada

La compresión SSL/TLS ha sido deshabilitada de forma predeterminada para mitigar el ataque CRIME. PHP 5.4.13 añadió la opción de contexto disable_compression para poder deshabilitar la compresión: ahora está establecida a TRUE (es decir, la compresión está deshabilitada) de forma predeterminada.

Permitir que los servidores prefieran su orden de cifradores

Se ha añadido la opción de contexto honor_cipher_order de SSL para que los servidores de flujos encriptados mitiguen las vulnerabilidades BEAST prefiriendo los cifradores del servidor a los del cliente.

Acceder al cifrador y protocolo negociados

Ahora se puede acceder al protocolo y cifrador que eran negociados para un flujo encriptado mediante stream_get_meta_data() o stream_context_get_options() cuando la opción de contexto capture_session_meta de SSL está establecida a 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"
}

Nuevas opciones para secreto hacia adelante perfecto en servidores de flujos encriptados

Los flujos de clientes encriptados ya admiten secreto hacia adelante perfecto (PFS por sus siglas en inglés), ya que está generalmente controlado por el servidor. Los flujos encriptados de servidores de PHP emplean certificados capaces del secreto hacia adelante perfecto no necesitan tomar ninguna acción adicional para habilitar PFS; sin embargo, se han añadido varias opciones de contexto de SSL para permitir un mayor control sobre PFS y tratar con cualquier problema de compatibilidad que pudiera surgir.

ecdh_curve

Esta opción permite la selección de una curva específica a emplear con cifradores ECDH. Si no se especifca, se empleará prime256v1.

dh_param

Una ruta a un fichero que contiene parámetros para el intercambio de claves Diffie-Hellman, tal como el creado por el siguiente comando:

openssl dhparam -out /path/to/my/certs/dh-2048.pem 2048
single_dh_use

Si se establece a TRUE, se creará un nuevo par de claves cuando se emplean parámetros Diffie-Hellman, mejorando así el secreto hacia adelante.

single_ecdh_use

Si se establece a TRUE, se generará siempre un nuevo par de claves cuando se negocian cifradores ECDH. Esto mejora el secreto hacia adelante.

Selección de la versión de SSL/TLS

Ahora es posible seleccionar versiones específicas de SSL y TLS mediante la opción de contexto crypto_method de SSL o estableciendo un transporte esepecífico al crear una envoltura de flujos (por ejemplo, llamando a stream_socket_client() o stream_socket_server()).

La opción de contexto crypto_method de SSL acepta una máscara de bit que enumere los protocolos que están permitidos, como lo hace crypto_type de stream_socket_enable_crypto().

Versiones de protocolo seleccionadas y opciones correspondientes
Protocolo/s Indicador del cliente Indicador del servidor Transporte
Cualquier versión de TLS o SSL STREAM_CRYPTO_METHOD_ANY_CLIENT STREAM_CRYPTO_METHOD_ANY_SERVER ssl://
Cualquier versión de 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

// Requerir TLS 1.0 o superior al emplear file_get_contents():
$ctx stream_context_create([
    
'ssl' => [
        
'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
    ],
]);
$html file_get_contents('https://google.com/'false$ctx);

// Requerir 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);

// Conectar usando el transoporte de socket de flujo tlsv1.2:// .
$sock stream_socket_client('tlsv1.2://google.com:443/');

?>

Se ha añadido openssl_get_cert_locations()

Se ha añadido la función openssl_get_cert_locations(): devuelve las ubicaciones predeterminadas en las cuales PHP buscará paquetes de 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) ""
}

Soporte para SPKI

Se ha añadido soporte para generar, extraer y verificar claves públicas firmadas y retos (SPKAC por sus siglas en inglés). Se han añadido openssl_spki_new(), openssl_spki_verify(), openssl_spki_export_challenge(), y openssl_spki_export() para crear, verificar y exportar claves públicas PEM y retos asociados de SPKAC generadas desde un elemento KeyGen de HTML5.

openssl_spki_new

Genera una nueva SPKAC usando una clave privada, un string con un reto y un algoritmo de hash.

<?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 la SPKAC provista.

<?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 retos asociados desde la SPKAC provista.

<?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 con formato PEM desde la 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-----