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.
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
}