Pregunta

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 está verificando la contraseña bcrypt con el hash si no está guardando la sal en ningún lado? La única idea que tengo es que de alguna manera está agregando la sal al final del hash.

¿Es esta una suposición correcta?

¿Fue útil?

Solución

¿Cómo verifica BCRYPT la contraseña con el hash si no está guardando la sal en ningún lado?

Claramente no está haciendo tal cosa. La sal debe salvarse en alguna parte.

Busquemos esquemas de cifrado de contraseña en Wikipedia. De http://en.wikipedia.org/wiki/crypt_(unix) :

La salida 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 incluía un enlace al código fuente. En lugar de pedirle a Internet que lea el código fuente por 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 por el número de rondas utilizadas, seguida de la sal codificada como base64, seguida por el hash codificado como base64.

Otros consejos

Un hash bcrypt cuerda parece:

$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$==$==$======================-------------------------------

Dónde

  • 2a: Identificador de algoritmo (Bcrypt, contraseña codificada UTF8, NULL terminado)
  • 10: Factor de costo (210 = 1,024 rondas)
  • Ro0CUfOqk6cXEKf3dyaM7O: Salt codificada OpenBSD-Base64 (22 caracteres, 16 bytes)
  • hSCvnwM9s4wIX9JeLapehKK5YdLxKcm: Hash codificado OpenBSD-Base64 (31 caracteres, 24 bytes)

Editar: Acabo de notar que estas palabras encajan exactamente. Tuve que compartir:

$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash
$==$==$======================-------------------------------

Bcrypt lo hace Cree un hash binario de 24 bytes, usando sal de 16 bytes. Eres libre de almacenar el hash binario y la sal como quieras; Nada te dice tener a la base-64 lo codifica en una cadena.

Pero Bcrypt fue creado por tipos que trabajaban en OpenBSD. Abre ya define un formato para su archivo de contraseña:

$[HashAlgorithmIdentifier]$[AlgorithmSpecificData]

Esto significa que el "Especificación bcrypt" está inexorablemente vinculado al formato de archivo de contraseña OpenBSD. Y cada vez que alguien crea un "Bcrypt hash" ellos siempre Conviertalo en una cadena ISO-8859-1 del formato:

$2a$[Cost]$[Base64Salt][Base64Hash]

Algunos puntos importantes:

  • 2a es el identificador alogithm
    • 1: MD5
    • 2: Bcrypt temprano, que tenía confusión sobre qué contraseñas de codificación están (obsoletas)
    • 2A: BCRYPT actual, que especifica las contraseñas como UTF-8 codificadas
  • Costo es un factor de costo utilizado al calcular el hash. El valor "actual" es 10, lo que significa que la configuración de clave interna pasa por 1,024 rondas
    • 10: 210 = 1,024 iteraciones
    • 11: 211 = 2,048 iteraciones
    • 12: 212 = 4.096 iteraciones
  • El algoritmo Base64 utilizado por el archivo de contraseña OpenBSD no es el mismo Base64 que codifica que todos los demás usos; Tienen el suyo:

    Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
        BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
    

    Por lo tanto, cualquier implementación de BCRYPT no puede usar ninguna biblioteca incorporada o estándar, Base64


Armado con este conocimiento, ahora puede verificar una contraseña correctbatteryhorsestapler contra el hash guardado:

$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top