¿Cómo node.bcrypt.js compara las contraseñas de hash y de texto sin formato sin el salt?

Desde github :

Para hash una contraseña:

var bcrypt = require('bcrypt'); bcrypt.genSalt(10, function(err, salt) { bcrypt.hash("B4c0/\/", salt, function(err, hash) { // Store hash in your password DB. }); }); 

Para comprobar una contraseña:

 // Load hash from your password DB. bcrypt.compare("B4c0/\/", hash, function(err, res) { // res == true }); bcrypt.compare("not_bacon", hash, function(err, res) { // res = false }); 

Desde arriba, ¿cómo puede no haber valores de sal involucrados en las comparaciones? ¿Que me estoy perdiendo aqui?

La sal se incorpora en el hash (como texto simple). La función de comparación simplemente extrae la sal del hash y luego la utiliza para modificar la contraseña y realizar la comparación.

Tuve la misma pregunta también que el póster original y eché un vistazo para mirar alrededor e intentar diferentes cosas para entender el mecanismo. Como ya se ha señalado por otros, la sal se concatena al hash final. Entonces esto significa un par de cosas:

  1. El algoritmo debe conocer la longitud de la sal.
  2. También debe saber la posición de la sal en la cadena final. por ejemplo, si está compensado por un número específico de izquierda o derecha.

Estas dos cosas están generalmente codificadas en la implementación, por ejemplo, la fuente de implementación bcrypt para bcryptjs define la longitud de sal como 16

 /** * @type {number} * @const * @private */ var BCRYPT_SALT_LEN = 16; 

Entonces, para ilustrar el concepto básico detrás de la idea, si uno quisiera hacerlo manualmente, se vería similar al siguiente. No recomiendo implementar este tipo de cosas cuando hay bibliotecas que puedes obtener para hacerlo.

 var salt_length = 16; var salt_offset = 0; var genSalt = function(callback) { var alphaNum = '0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ'; var salt = ''; for (var i = 0; i < salt_length; i++) { var j = Math.floor(Math.random() * alphaNum.length); salt += alphaNum[j]; } callback(salt); } // cryptographic hash function of your choice eg shar2 // preferably included from an External Library (dont reinvent the wheel) var shar2 = function(str) { // shar2 logic here // return hashed string; } var hash = function(passwordText, callback) { var passwordHash = null; genSalt(function(salt){ passwordHash = salt + shar2(passwordText + salt); }); callback(null, passwordHash); } var compare = function(passwordText, passwordHash, callback) { var salt = passwordHash.substr(salt_offset, salt_length); validatedHash = salt + shar2(passwordText + salt); callback(passwordHash === validatedHash); } // sample usage var encryptPassword = function(user) { // user is an object with fields like username, pass, email hash(user.pass, function(err, passwordHash){ // use the hashed password here user.pass = passwordHash; }); return user; } var checkPassword = function(passwordText, user) { // user has been returned from database with a hashed password compare(passwordText, user.pass, function(result){ // result will be true if the two are equal if (result){ // succeeded console.log('Correct Password'); } else { // failed console.log('Incorrect Password'); } }); }