php - password_bcrypt - password_verify no funciona
Validar una contraseƱa contra un hash SSHA256 en PHP (2)
Necesita almacenar la sal junto con el valor hash.
Cuando necesite validar la contraseña, simplemente vuelva a calcular el hash con la contraseña ingresada por el usuario + la sal almacenada. Si los valores hash coinciden, el usuario ingresó la contraseña correcta.
Para su formato, use base64_decode
primero, los últimos 4 bytes del resultado serán sal.
Para la autenticación con Dovecot, utilizo hashes SSHA256 pero no tengo ni idea de cómo validar una contraseña dada contra el hash existente. Las siguientes funciones de PHP (que se encuentran en la web) se utilizan para crear el hash SSHA256:
function ssha256($pw) {
$salt = make_salt();
return "{SSHA256}" . base64_encode( hash(''sha256'', $pw . $salt, true ) . $salt );
}
function make_salt() {
$len = 4;
$bytes = array();
for ($i = 0; $i < $len; $i++ ) {
$bytes[] = rand(1,255);
}
$salt_str = '''';
foreach ($bytes as $b) {
$salt_str .= pack(''C'', $b);
}
return $salt_str;
}
Ejemplo de salida: {SSHA256}lGq49JTKmBC49AUrk7wLyQVmeZ7cGl/V13A9QbY4RVKchckL
¿Tengo que extraer la sal, pero cómo? Perdí totalmente el camino para resolver el problema, ¿alguien tiene una pista para esto?
Gracias a todos por ayudar!
Ah, y lo siento, tengo que usar SSHA256, porque Dovecot 1.2.15 solo admite esos esquemas: CRYPT MD5 MD5-CRYPT SHA SHA1 SHA256 SMD5 SSHA SSHA256 PLAIN CLEARTEXT CRAM-MD5 HMAC-MD5 DIGEST-MD5 PLAIN-MD4 PLAIN-MD5 LDAP-MD5 LANMAN NTLM OTP SKEY RPA
No debe usar la familia SHA para el hashing de contraseñas. Son rápidos y están diseñados para almacenar archivos a velocidad . Necesita hash pashword para ser costoso . Use bcrypt, PHPass o simplemente use esta clase, que rodé yo mismo (pero no hasta que aprenda a hacer agujeros en ella):
class PassHash {
public static function rand_str($length) {
$total = $length % 2;
$output = "";
if ($total !== 0) {
$count = floor($length / 2);
$output .= ".";
} else $count = $length / 2;
$bytes = openssl_random_pseudo_bytes($count);
$output .= bin2hex($bytes);
// warning: prepending with a dot if the length is odd.
// this can be very dangerous. no clue why you''d want your
// bcrypt salt to do this, but /shrug
return $output;
}
// 2y is an exploit fix, and an improvement over 2a. Only available in 5.4.0+
public static function hash($input) {
return crypt($input, "$2y$13$" . self::rand_str(22));
}
// legacy support, add exception handling and fall back to <= 5.3.0
public static function hash_weak($input) {
return crypt($input, "$2a$13$" . self::rand_str(22));
}
public static function compare($input, $hash) {
return (crypt($input, $hash) === $hash);
}
}
Tienes que hash el texto claro dado y comparar ese hash con uno que has almacenado. Las sales se almacenan en hash y deben ser aleatorias. Si lo desea, agregue un pimiento. También debe hacer que la tasa de trabajo sea variable, de modo que pueda cambiar la tasa de trabajo en cualquier momento cuando sea necesario y que el sistema siga funcionando.
Si, como dices, no tienes forma de implementar esto, puedes descomprimir el hash de la siguiente manera:
function unpack_hash($hash) {
$hash = base64_decode($hash);
$split = str_split($hash, 64);
return array("salt" => $split[1], "hash" => $split[0]);
Esto se debe a que SHA256 tiene 256 bits o 64 caracteres hexadecimales. Siempre puedes asumir que los primeros 64 caracteres son el hash