Este documento discute diferentes métodos para encriptar contraseñas en PHP y las ventajas del uso de password_hash() y password_verify() introducidos en PHP 5.5. Explica que password_hash() genera hashes seguros usando bcrypt de forma predeterminada y que password_verify() verifica hashes de forma segura, a diferencia de comparar cadenas directamente. También muestra un ejemplo de cómo implementar estos métodos en un objeto de valor para encriptar y verificar contraseñas de forma segura.
4. … o alguna variante del estilo ...
Meetups
<?php
$password = '123456';
$salt = time();
$encryptedPassword = md5($password . $salt);
var_dump($encryptedPassword);
/*
string(32) "19d1a77319c0ca4dba950ff796849177"
*/
5. … hay quien se lo “curra” y usa sha1() ...
Meetups
<?php
$password = '123456';
$encryptedPassword = sha1($password);
var_dump($encryptedPassword);
/*
string(40)
"7c4a8d09ca3762af61e59520943dc26494f8941b"
*/
7. El old-path para los hash en PHP es crypt()
Meetups
<?php
$password = '123456';
$salt =
'$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$encryptedPassword = crypt($password, $salt);
var_dump($encryptedPassword);
/*
string(60)
"$2y$04$usesomesillystringforeQEfwKz1L9ksKh8.24s7LiFZFXDb9Ijq"
*/
8. “Problemas” del crypt()
Meetups
● Puedes usar métodos de encriptación poco seguros: md5, sha…
● Tienes que encargarte de generar un salt válido y fuerte.
● Puedes llamar a crypt() sin enviarle un salt… y generará uno DÉBIL.
● Existe la mala costumbre de validar el resultado comparando cadenas.
● Debes compararlo con hash_equals(), pero para eso necesitas almacenar el salt.
$en1 = crypt($password, $salt);
$en2 = crypt($password);
var_dump(hash_equals( $en1, $en2));
/* bool(false) */
$en1 = crypt($password, $salt);
$en2 = crypt($password, $salt );
var_dump(hash_equals( $en1, $en2));
/* bool(true) */
9. Welcome password_hash() !!
Meetups
● >= PHP 5.5.0
● Es un wrapper de crypt()
● Por defecto usa el algoritmo bcrypt
● Está preparado para cambiar en el futuro el algoritmo por defecto, sin que afecte a los hash ya
generados.
● Si no se le facilita un salt, genera uno SEGURO
● Desde PHP 7.0.0 pasarle el salt es una opción obsoleta.
● Por defecto, el coste del algoritmo es 10, pero se le puede pasar un valor mayor como opción.
● Se verifica de forma segura con password_verify()
● Con password_needs_rehash() podrás comprobar si existe un nuevo algoritmo de hash o ha
cambiado el coste, para así poder generar un nuevo hash para la misma contraseña.
11. Ejemplo de Value Object con password_hash() y password_verify()
Meetups
<?php
namespace AppDomainValueObject ;
class Password
{
private $password;
public function __construct(string $password)
{
$this->validate($password);
$this->password = password_hash( $password, PASSWORD_DEFAULT);
}
12. Ejemplo de Value Object con password_hash() y password_verify()
Meetups
private function validate(string $password)
{
if (strlen($password) > 72) {
throw new Exception("The password exceeds the max. characters: 72" );
}
}
public function isEqualTo(string $password) : bool
{
return password_verify( $password, $this->password);
}
public function isNeedleRehash () : bool
{
return password_needs_rehash( $this->password ,PASSWORD_DEFAULT);
}
}