c# - ¿Alguien puede explicar cómo BCrypt verifica un hash?
bcrypt.net (2)
¿Cómo está BCrypt verificando la contraseña con el hash si no está guardando sal en ninguna parte?
Claramente, no está haciendo tal cosa. La sal debe ser salvada en alguna parte.
Busquemos esquemas de encriptación de contraseñas en Wikipedia. De http://en.wikipedia.org/wiki/Crypt_(Unix) :
El resultado de la función no es simplemente el hash: es una cadena de texto que también codifica la sal e identifica el algoritmo hash utilizado.
Alternativamente, una respuesta a su pregunta anterior sobre este tema incluye un enlace al código fuente . En lugar de pedirle a Internet que lea el código fuente para usted, siempre puede elegir leerlo usted mismo. Eso probablemente obtendría tu respuesta más rápido. La sección relevante del código fuente es:
StringBuilder rs = new StringBuilder();
rs.Append("$2");
if (minor >= ''a'') {
rs.Append(minor);
}
rs.Append(''$'');
if (rounds < 10) {
rs.Append(''0'');
}
rs.Append(rounds);
rs.Append(''$'');
rs.Append(EncodeBase64(saltBytes, saltBytes.Length));
rs.Append(EncodeBase64(hashed,(bf_crypt_ciphertext.Length * 4) - 1));
return rs.ToString();
Claramente, la cadena devuelta es la información de la versión, seguida de la cantidad de rondas utilizadas, seguida de la sal codificada como base64, seguida de la codificación codificada como base64.
Estoy usando C # y BCrypt.Net para hash mis contraseñas.
Por ejemplo:
string salt = BCrypt.Net.BCrypt.GenerateSalt(6);
var hashedPassword = BCrypt.Net.BCrypt.HashPassword("password", salt);
//This evaluates to True. How? I''m not telling it the salt anywhere, nor
//is it a member of a BCrypt instance because there IS NO BCRYPT INSTANCE.
Console.WriteLine(BCrypt.Net.BCrypt.Verify("password", hashedPassword));
Console.WriteLine(hashedPassword);
¿Cómo es BCrypt que verifica la contraseña con el hash si no guarda la sal en ningún lugar? La única idea que tengo es que de alguna manera se agrega la sal al final del hash.
¿Es esta una suposición correcta?
Una cadena de hash BCrypt se ve así:
$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$==$==$======================-------------------------------
Dónde
-
2a
: Identificador de Algoritmo (BCrypt, contraseña codificada UTF8, nulo terminado) -
10
: Factor de costo (210
= 1,024 rondas) -
Ro0CUfOqk6cXEKf3dyaM7O
: Sal codificada de OpenBSD-Base64 (22 caracteres, 16 bytes) -
hSCvnwM9s4wIX9JeLapehKK5YdLxKcm
: hash codificado de OpenBSD-Base64 (31 caracteres, 24 bytes)
Editar : acabo de notar que estas palabras encajan exactamente. tuve que compartir:
$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash $==$==$======================-------------------------------
BCrypt crea un hash binario de 24 bytes, usando sal de 16 bytes. Puedes guardar el hash binario y la sal como quieras; nada dice que tienes que codificar en base a 64 en una cadena.
Pero BCrypt fue creado por tipos que estaban trabajando en OpenBSD. OpenBSD ya define un formato para su archivo de contraseña:
$ [HashAlgorithmIdentifier]
$ [AlgorithmSpecificData]
Esto significa que la "especificación bcrypt" está inexorablemente vinculada al formato de archivo de contraseña de OpenBSD. Y cada vez que alguien crea un "hash bcrypt" siempre lo convierten en una cadena ISO-8859-1 del formato:
$ 2a
$ [Cost]
$ [Base64Salt][Base64Hash]
Algunos puntos importantes:
-
2a
es el identificador de alogitmo- 1: MD5
- 2: early bcrypt, que tenía confusión sobre las contraseñas de codificación que están en (obsoletas)
- 2a: bcrypt actual, que especifica las contraseñas como codificadas en UTF-8
- El costo es un factor de costo utilizado al calcular el hash. El valor "actual" es 10, lo que significa que la configuración de la clave interna pasa por 1.024 rondas
- 10: 2 10 = 1.024 iteraciones
- 11: 2 11 = 2.048 iteraciones
- 12: 2 12 = 4.096 iteraciones
el algoritmo base64 utilizado por el archivo de contraseñas de OpenBSD no es la misma codificación Base64 que todos los demás ; ellos tienen los suyos:
Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
Entonces, cualquier implementación de bcrypt no puede usar ninguna biblioteca base64 incorporada o estándar
Armado con este conocimiento, ahora puede verificar una contraseña correctbatteryhorsestapler
contra el hash guardado:
$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km