'bcrypt compareSync "Unhandled rejection Error: data and hash must be strings"

I'm using knex to select a specific users password from my database. this hashed password is returned to me in an object like this:

[ anonymous {
 password_hash: 
 '$2a$10$zRSFdNJsg8S3Xv1I73gjYuRu.Mw/9Dtujh0dTqrtc9DA12vUHuqbK' } ]

When I try using bcrypt.compareSync to compare the entered password and the password that exists in the database, it give me an error saying data and hash must be strings. I tried using the .toString() method and JSON.stringify(password_hash). But both don't help. How do I get this to work?

Here is my code:

knex('users').where({
    email: req.body.loginEmail
  }).select('password_hash')
  .then(function(password_hash) {
      //console.log("resp", password_hash)
      console.log("JSON stringifies",JSON.stringify(password_hash))
      console.log("req", req.body.loginPass)
      console.log('hash', password_hash)
      bcrypt.compareSync(req.body.loginPass, JSON.stringify(password_hash), function(err, doesMatch){
      if (doesMatch){
        console.log("Passwords Match")
        req.session.email = rows[0].email;
        var templateVars = {
          emale: req.session.email
        }
        res.render('/dashboard', templateVars)
      } else {
        console.log("THIS IS THE ERROR", err);
        res.send("I DONT KNOW YOU. SIGN UP FIRSt.")
      }
    })
  })

My entire error:

Unhandled rejection Error: data and hash must be strings
at Object.compareSync (/vagrant/CaloBoxInc/node_modules/bcrypt/bcrypt.js:144:15)
at /vagrant/CaloBoxInc/server.js:159:14
at tryCatcher (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/vagrant/CaloBoxInc/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:570:20)
at tryOnImmediate (timers.js:550:5)
at processImmediate [as _immediateCallback] (timers.js:529:5)


Solution 1:[1]

Could it be that your req.body.loginPass is not string? JSON.stringify always returns undefined / string and bcrypt returns different error if parameter is undefined so that paramater can't be the problem.

Try force casting req.body.loginPass to string like this:

bcrypt.compareSync(´´+ req.body.loginPass, ...

(just for debugging purposes... though you should already see from earlier console logs it it is not a string).

Solution 2:[2]

This error arises if one or more arguments passed to bcrypt.compareSync function are either undefined or null.

Solution 3:[3]

The solution to this problem is by changing the datatype of the password field in your Database to char(150) to avoid truncation. I hope that helps.

Solution 4:[4]

Go to your mongoose file, where you can set your types of email and password. Change type of password from Number to String.

Solution 5:[5]

In the database, the older password value was not a hashed password. It was in a String. Delete the old value in the database. Create a new one with the hashed password and then validate it. It works.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mikael Lepistö
Solution 2 Sai Trinath Saka
Solution 3 ShadRack Osewe
Solution 4 Tomer Shetah
Solution 5 ouflak