c# salt bcrypt bcrypt.net

c# - ¿Por qué BCrypt.net GenerateSalt(31) regresa de inmediato?



(2)

Me encontré con BCrypt.net después de leer la publicación de Jeff Atwood sobre el almacenamiento de contraseñas, lo que me llevó a la recomendación de Thomas Ptacek de utilizar BCrypt para almacenar contraseñas. Lo que finalmente me llevó a esta implementación en C # de BCrypt.

En los comentarios en el último enlace anterior, alguien preguntó: "¿Por qué GenerateSalt (30) se toma para siempre, pero GenerateSalt (31) parece que no toma tiempo en absoluto?"

Ejecuté BCrypt.HashPassword (contraseña, BCrypt.GenerateSalt (31)) y obtuve mi resultado en 0 milisegundos.

He estado ejecutando BCrypt.HashPassword ("contraseña", BCrypt.GenerateSalt (30)) durante más de 5 minutos y aún no tengo un resultado.

Me doy cuenta de que probablemente no necesitaremos una sal de 30 caracteres generada aleatoriamente para crear nuestros hash de contraseña (o cifrado irreversible en el caso de BCrypt ) durante años. EDITAR Debería haber leído el código un poco, logRounds no tiene nada que ver con la longitud de sal. Gracias Aaronaught.

Entonces, ¿por qué GenerateSalt (31) devuelve un valor casi instantáneamente (cuando debería tomar aproximadamente el doble de tiempo que GenerateSalt (30)?

ACTUALIZAR

Aquí está la solución:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) { // ... snip ... uint rounds = 1U << logRounds; // ... snip }


Si el hashing con GenerateSalt(31) devuelve casi instantáneamente, eso es un error. Usted debe informar que upstream (tengo, para jBCrypt). :-)

Por defecto, las rondas de registro son 10. Esto significa que (si recuerdo bien), se usan 1024 rondas. Cada vez que incrementa las rondas de registro, el número de rondas se duplica.

En 30 rondas de registro, estás haciendo 1073741824 rondas. Eso legítimamente lleva mucho tiempo. En 31 rondas de registro, se deben realizar 2147483648 rondas, pero sospecho que la implementación en particular está utilizando desbordamientos. :-(


Sospecho que el error está aquí:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) { // ... snip ... int rounds = 1 << logRounds; // ... snip }

Cuando se especifica 31 para los logRounds , se calcula que como 2 ^ 32, que no cabe en un int y se desborda, por lo que el hash se realiza en ... er, cero pasa. El autor debería haber usado uint lugar. ¡Fácil de arreglar!

También quería comentar sobre esto:

Me doy cuenta de que probablemente no necesitaremos una sal de 30 caracteres generada al azar para crear nuestros hashes de contraseña ...

Tenga en cuenta que el parámetro logRounds no se refiere al número de caracteres / bytes en el salt, que siempre es 16. Se refiere a la base logarítmica del número de pases que el hash tardará en calcular; en otras palabras, es una forma de hacer bcrypt a escala con la Ley de Moore, lo que hace que la función sea varios órdenes de magnitud más costosa de computar si las computadoras llegan a ser lo suficientemente rápidas para romper los hashes existentes.