2011-03-22 11 views
21

Estoy usando C# y BCrypt.Net para hash mis contraseñas.¿Alguien puede explicar cómo BCrypt verifica un hash?

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 se Bcrypt la verificación de la contraseña con el hash si no es el ahorro de la sal en cualquier lugar. La única idea que tengo es que de alguna manera se agrega la sal al final del hash.

¿Es esto una suposición correcta?

Respuesta

25

¿Cómo está BCrypt verificando la contraseña con el hash si no está guardando la sal en algún lugar?

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

Busquemos esquemas de cifrado de contraseñas en Wikipedia. De http://en.wikipedia.org/wiki/Crypt_(Unix):

La salida de la función no es meramente el hash: es una cadena de texto que también codifica la sal e identifica el algoritmo hash utilizado.

Alternativamente, una respuesta a su previous question sobre este tema incluye un enlace al source code. En lugar de pedirle a Internet que lea el código fuente para usted, siempre puede elegir leerlo usted mismo. Eso probablemente obtenga tu respuesta más rápido. La sección pertinente 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 información de versión, seguido por el número de rondas utilizados, seguido de la sal codificado como base64, seguido por el hash codificado como base64.

+0

Así que mi suposición era correcta que está añadiendo la sal y utilizando un delimitador de som e tipo de identificar donde los seres salinos y los extremos corrigen? –

+0

Gracias por la edición, no vi ese enlace antes. : D –

73

Un Bcrypt de hash cadena parece:

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

Dónde

  • 2a: Algoritmo Identificador (Bcrypt, UTF8 contraseña codificada, terminada en nulo)
  • 10: factor de costo (2 10 = 1,024 rondas)
  • Ro0CUfOqk6cXEKf3dyaM7O: OpenBSD-Base64 sal codificada (22 caracteres, 16 bytes)
  • hSCvnwM9s4wIX9JeLapehKK5YdLxKcm: OpenBSD-Base64 hash codificado (31 caracteres, 24 bytes)

Editar : acabo de notar que estas palabras encajan exactamente.que tenía que compartir:

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

Bcrypt qué crear un hash binario de 24 bytes, el uso de sal de 16 bytes. Puedes guardar el hash binario y la sal como quieras; nada dice tiene a base-64 codificarlo en una cadena.

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

$[HashAlgorithmIdentifier]$[AlgorithmSpecificData]

Esto significa que el "especificación bcrypt" está inexorablemente ligado al formato de archivo de contraseñas de OpenBSD. Y cada vez que alguien crea un "hash de bcrypt" siemprela convierten en una cadena ISO-8859-1 del formato:

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

Un algunos puntos importantes:

  • 2a es la identificador alogithm
    • 1: MD5
    • 2: bcrypt temprano, que tenía confusión sobre qué contraseñas que codifican están en (obsoleto)
    • 2a: bcrypt actual, que especifica las contraseñas como codificación UTF-8
  • El costo es un factor de costo utilizado al calcular el hash.El valor "actual" es 10, es decir, la configuración de la clave interna pasa a través de 1.024 rondas
    • 10: 2 = 1024 iteraciones
    • 11: 2 = 2048 iteraciones
    • 12: 2 = 4096 iteraciones
  • el algoritmo base64 utilizado por el archivo de contraseña OpenBSD no es la misma codificación Base64 que todos los demás usos; tienen su propia:

    Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/ 
        BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
    

    Así que cualquier implementación de bcrypt no se puede utilizar cualquiera, o estándar incorporado, biblioteca de base 64


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

$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km 
+4

+1 para la respuesta y para la referencia a 'rightbatteryhorsestapler' de xkcd :-) – MaxiWheat

+23

+1 por' $ 2a $ 10 $ TwentytwocharactersaltThirtyonecharacterspasswordhash' - eso es increíble :) –

+2

Cheater: TwentyTwoCharacter vs. ThirtyOneCharacter ** s ** (plural) . Afortunadamente, Salt comienza con ** **, por lo que podría argumentar que se comparte entre las dos palabras. Aunque sigue siendo impresionante ... – TTT

Cuestiones relacionadas