Cifrado de contraseñas

Para gestionar la seguridad de nuestros usuarios, nunca almacenamos sus contraseñas en formato de texto plano, en su lugar almacenamos el hash de la contraseña. El hash no es una operación reversible, la contraseña no puede recuperarse. Sin embargo, la contraseña puede ser descifrada y para hacer que el descifrado sea lo más difícil posible tenemos que utilizar un algoritmo seguro. La clase Nette\Security\Passwords nos ayudará con eso.

Instalación y requisitos

El framework añade automáticamente un servicio Nette\Security\Passwords al contenedor DI bajo el nombre security.passwords, que se obtiene pasándolo mediante inyección de dependencias:

use Nette\Security\Passwords;

class Foo
{
	public function __construct(
		private Passwords $passwords,
	) {
	}
}

__construct($algo=PASSWORD_DEFAULT, array $options=[])string

Elige qué algoritmo seguro se utiliza para el hash y cómo configurarlo.

Por defecto es PASSWORD_DEFAULT, por lo que la elección del algoritmo se deja a PHP. El algoritmo puede cambiar en nuevas versiones de PHP cuando se soporten algoritmos hash más fuertes. Por lo tanto, debe tener en cuenta que la longitud del hash resultante puede cambiar. Por lo tanto debe almacenar el hash resultante de manera que pueda almacenar suficientes caracteres, 255 es el ancho recomendado.

Así es como usarías el algoritmo bcrypt y cambiarías la velocidad del hash usando el parámetro coste desde el 10 por defecto. En el año 2020, con coste 10, el hashing de una contraseña tarda aproximadamente 80ms, coste 11 tarda 160ms, coste 12 entonces 320ms, la escala es logarítmica. Cuanto más lento mejor, coste 10–12 se considera lo suficientemente lento para la mayoría de los casos de uso:

// we will hash passwords with 2^12 (2^cost) iterations of the bcrypt algorithm
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Con inyección de dependencia:

services:
	security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])

hash(string $passwords): string

Genera el hash de la contraseña.

$res = $passwords->hash($password); // Hashes the password

El resultado $res es una cadena que, además del propio hash, contiene el identificador del algoritmo utilizado, su configuración y la sal criptográfica (datos aleatorios para garantizar que se genera un hash diferente para la misma contraseña). Por lo tanto, es compatible con versiones anteriores; por ejemplo, si se cambian los parámetros, se pueden verificar los hashes almacenados con la configuración anterior. Todo este resultado se almacena en la base de datos, por lo que no es necesario almacenar la sal o la configuración por separado.

verify(string $password, string $hash)bool

Averigua si la contraseña dada coincide con el hash dado. Obtiene la $hash de la base de datos por nombre de usuario o dirección de correo electrónico.

if ($passwords->verify($password, $hash)) {
	// Correct password
}

needsRehash(string $hash): bool

Averigua si el hash coincide con las opciones dadas en el constructor.

Utiliza este método cuando, por ejemplo, estés cambiando los parámetros del hash. La verificación de contraseñas utilizará los parámetros almacenados con el hash y si needsRehash() devuelve true, tendrás que calcular el hash de nuevo, esta vez con los parámetros actualizados, y almacenarlo de nuevo en la base de datos. Esto asegura que los hashes de las contraseñas se “actualizarán” automáticamente cuando los usuarios estén iniciando sesión.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// store $hash to database
}
versión: 4.0