简体   繁体   中英

Node bcrypt's compare always returns false

I am stumped trying to get my passwords to successfully compare with bcrypt using node. Maybe I missed something, but on account creation, I do the following within the signup method (with some code abbreviated):

bcrypt.genSalt(10, function(err, salt) {
               if(err) {

               }
               bcrypt.hash(user.Password, salt, function(err, hash) {
                           console.log('hashing and saving');
                           db.query(db insert code, function (error, rows, fields) {
                                    if(error) {
                                    console.log(error);
                                    res.setHeader('500', { 'Content-Type': 'x-application/json'});
                                    res.send({UserId: 0, ErrorMessage: 'Something terrible happened.'});
                                    } else {
                                    console.log('User created : ' + rows.insertId);
                                    res.setHeader('200', { 'Content-Type': 'x-application/json'});
                                    res.send({UserId: rows.insertId});
                                    }
                                    });
                           });
               });

return next();

This all works fine. My db has the encrypted password. But when a user signs in, I cannot get a successful result from bcrypt.compare:

db.query(get account code, function(error, rows, fields) {
         if(rows.length == 1) {
           bcrypt.compare(request.params.password, rows[0].Password, function(err,res) {
              if(err) { console.log(err.toString()); }
              if(res == true)
              {
                        response.setHeader('200', { 'Content-Type': 'x-application/json' });
                        response.send({result: true});
              } else {
                        response.setHeader('401', { 'Content-Type': 'x-application/json' });
                        console.log('invalid password');
                        response.send({result:false});
                     }
              });
         }
        });

return next();

And I always end up with invalid password. Do I need to take the cleartext password and re-encrypt it before comparing to what I pull out of the database?

you can skip doing bcrypt.genSalt and use bcrypt.hash(password, 10, function(err, hash) {..});

your compare function seems good to me.

this is working fine for me:

var bcrypt = require('bcrypt');

bcrypt.hash('mypassword', 10, function(err, hash) {
    if (err) { throw (err); }

    bcrypt.compare('mypassword', hash, function(err, result) {
        if (err) { throw (err); }
        console.log(result);
    });
});

I dont know if you have the same as I did, I had the same problem because my table had the length of 45 chars and bcrypt compares if the hash lenght is diferent from 60 it returns false. Just increase the length of characters in your table

Mine was due to my database column not having a large enough varchar length. A good place to check.

Arguments for bcrypt's compare method should be

bcrypt.compare(actual_password, encrypted_password)

instead of

bcrypt.compare(encrypted_password, actual_password)

=> the encrypted_password should be the second argument.

For me it was just an arguments disorder

The right order

bcrypt.compare(plainPasswordToCheck, hashedPasswordOnStorage)

I had the same problem. After changing the node package from bcrypt to bcryptjs the comparision worked like a charm. Since the package seems to be a fork, the functions do not need to be adjusted.

I had this same problem, but I am sure I am not encoding my password twice. Here is the thing. bcrypt-nodejs npm package is on v0.0.3 and I am using this version. I am writing the algorithm to store a user password on register and read a user password on login. The frontend is a simple with input text for email field and input password for password field. When I submit the request I POST a call to https://localhost ... on my local node server. I can log the data received and I can see the password logged is the same as the password inserted on frontend.

The code used to store the password is:

//var user.bcrypt = bcrypt.genSaltSync(10);;
var clearPwd = user.password;
user.password = bcrypt.hashSync(clearPwd);//, user.bcrypt);
log4.debug("hashSyncked: "+ user.password);
db.userSave(user, cb);

The code used to read and compare password is:

log4.debug('compare '+pwd+' with saved on db for user %j', userDoc.password);
var okPwd = bcrypt.compareSync(pwd, userDoc.password);

So, I see the hashed password, it is logged as a string like $ert3435tF.02ri etc...

But everytime I login with the same password I registered with, okPwd is always false. Why?

Even if I un-comment the commented code!

UPDATE The solution I found was about methods. Password should not be stored and read like that, it is too ...rude !! The correct method is mentioned here Watch out! There is an error in that guideline. bcrypt.hash(...) functions needs 2 object parameter and 2 callbacks! The last one is the one called at the end of the hash process, the first is called to track the hash proces. I put that a null and it all works well. I admit I made another mistake: I used bcrypt-nodejs package instead of brcrypt.

只需修改数据库中分配给密码字段的字符长度,可能生成的哈希值大于该字段可以支持的值

my hash was starting with $2y and it had to start with $2b

This library supports $2a$ and $2b$ prefix bcrypt hashes. $2x$ and $2y$ hashes are specific to bcrypt implementation developed for John the Ripper. In theory, they should be compatible with $2b$ prefix.

在比较功能中很容易混淆顺序;)

bcrypt.compare(user_entered_password, database_encrypted_password)

This works for me.

var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync();

bcrypt.hash('mypassword', salt, function(err, hash){
    if(err) throw err;

    bcrypt.compare('mypassword', hash, function(err, result) {
      if (err) { throw (err); }
      console.log(result);
    });

});

I had the same issue and for me the solution was to fix a typo in my frontend. I was sending 'pasword' from my form and expecting 'password'. Somehow bcyppt then hashed the returned undefined value and that was the reason compare() always returned false.

Hope this helps someone!

Another possible solution which worked for me is if in your User model you put under password field.

lowercase: true,

I happened to had this one copied from another field. When I removed it the issue disappeared.

I deleted my user and recreated it and did this

const isMatch = await bcrypt.compare(password, user.password);
console.log(user.password, isMatch);
if (!isMatch) {
  return res.status(400).json({
    msg:
      "Sorry, your password was incorrect. Please double-check your password.",
  });

and at the time of creating a user, I did this

const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);

In the compare function, you do not need to generate a new hash, do this:

async function Login(email, password) {
  const user = await this.service.getByEmail(email);

  const passwordBd = user.user_password;

  const matching = await bcrypt.compare(password, passwordBd);

  console.log(matching); //true
};

In my case, I was passing in the hash as a command line argument to a node program - just for testing:

node admin/bcrypt.js password $2b$10$/v9nAxpPQoDH5LMa/q.0AON/gEk.AxF57hHtIGkKR5IAWfMLyBcmm

The hash started with $2b$10$/ ; the $2 and $1 were interpreted as positional arguments and evaluated to empty values, hence the value being compared was different than what I passed in. Escaping the $ symbols with a \ solved the issue:

node admin/bcrypt.js password \$2b\$10\$/v9nAxpPQoDH5LMa/q.0AON/gEk.AxF57hHtIGkKR5IAWfMLyBcmm

I had the same problem with postgresql, but should always be the same.

I simply had to trim my db result:

bcrypt.compare(
    req.body.password,
    String(user.PASSWORD).trim()
)

i dont know if you have the same as I did, I had the same problem because my table had the length of 35 chars and bcrypt compares if the hash lenght is diferent from 60 it returns false. Just increase the length of characters in your table

那是由于密码长度为 45,增加它并解决问题。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM