node.bcrypt.js icon indicating copy to clipboard operation
node.bcrypt.js copied to clipboard

bcrypt.compare always returns false

Open francis-Paul-code opened this issue 3 years ago • 22 comments

Of course many have had the challenge but I've looked at most solutions and I still can't find the reason why my case has refused.

Screenshot from 2021-12-13 20-12-22

I've checked everything thoroughly, the characters saved in the DB are the exact Hash character length, the passwords are the same, I just cannot understand why It refuses to work

francis-Paul-code avatar Dec 13 '21 17:12 francis-Paul-code

Ensure you aren't hashing more than once. Are you hashing in an ORM model update?

jonbito avatar Dec 21 '21 20:12 jonbito

This might be happened because of character length in your DB. Check this

irkhamissimo avatar Jan 08 '22 14:01 irkhamissimo

In my case, happened using windows, but the same project using a mac, works

Any solution?

edersonfaccin avatar Nov 23 '22 14:11 edersonfaccin

I'm also experiencing the same issue. The problem is neither due to rehashing nor using different character sets.

Gatharikih avatar Jan 19 '23 04:01 Gatharikih

Here I'm facing the same problem with compareSync (is always returning false). But, in my case, when I change compareSync with compare, return true in every case.

image

borjamunozvw avatar Jan 20 '23 12:01 borjamunozvw

I am having the same issue, anyone got the around it?

mosesrb avatar Feb 09 '23 19:02 mosesrb

Personally I'd to create a REST API in Java to hash and compare passwords.

Gatharikih avatar Feb 09 '23 20:02 Gatharikih

For me the solution was to hashing the password and then compare it. It seems that the bycrypt.compare only works with the original password and the hashed pasword:

 if (!user) {
    console.log("user not found");
    return res.send("user not found!");
  } else {
    bcrypt.hash(req.body.password, 10, function (err, hash) {
      if (err) {
        throw err;
      } else {
        bcrypt.compare(user.password, hash, function (err, result) {
          if (err) {
            throw err;
          }
          console.log(result);
          if (!result) {
            return res.status(201).json({ message: "Wrong password!" });
          } else {
            return res.status(201).json({ message: "Connected!", user: user });
          }
        });
      }
    });
  }

borjamunozvw avatar Feb 13 '23 08:02 borjamunozvw

For me the solution was to hashing the password and then compare it. It seems that the bycrypt.compare only works with the original password and the hashed pasword:

 if (!user) {
    console.log("user not found");
    return res.send("user not found!");
  } else {
    bcrypt.hash(req.body.password, 10, function (err, hash) {
      if (err) {
        throw err;
      } else {
        bcrypt.compare(user.password, hash, function (err, result) {
          if (err) {
            throw err;
          }
          console.log(result);
          if (!result) {
            return res.status(201).json({ message: "Wrong password!" });
          } else {
            return res.status(201).json({ message: "Connected!", user: user });
          }
        });
      }
    });
  }

The code above takes the plaintext password and hashes it and then uses bcrypt compare method over it. So every password is a valid password because you are not testing it against the stored password in database but rather with user own password.

mosesrb avatar Feb 13 '23 08:02 mosesrb

Something is up with my MongoDB idk, tried argon2 npm as well and even that package is unable to verify password from MongoDB, below is my password field schema, am i doing something wrong here before storing data in MongoDB

const userSchema = new mongoose.Schema({ name:{ type: String, minlength: 3, maxlength: 255, required: true }, email:{ type: String, minlength: 3, maxlength: 255, unique: true, required: true }, password:{ type: String, minlength: 3, maxlength: 1024, required:true }, isAdmin: Boolean });

mosesrb avatar Feb 13 '23 08:02 mosesrb

For me the solution was to hashing the password and then compare it. It seems that the bycrypt.compare only works with the original password and the hashed pasword:

 if (!user) {
    console.log("user not found");
    return res.send("user not found!");
  } else {
    bcrypt.hash(req.body.password, 10, function (err, hash) {
      if (err) {
        throw err;
      } else {
        bcrypt.compare(user.password, hash, function (err, result) {
          if (err) {
            throw err;
          }
          console.log(result);
          if (!result) {
            return res.status(201).json({ message: "Wrong password!" });
          } else {
            return res.status(201).json({ message: "Connected!", user: user });
          }
        });
      }
    });
  }

The code above takes the plaintext password and hashes it and then uses bcrypt compare method over it. So every password is a valid password because you are not testing it against the stored password in database but rather with user own password.

Sorry that I didn't copy the full code so it the can be tricky. In my case "user.password" was the equivalent to my database user (as you can see, I've declared and array with users), and not the received through body (I also checked with postman). Here you can find the full code:


const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");

function login(req, res) {
  // console.log('username', req.body.username)
  // console.log('password', req.body.password)
  const users = [
    {
      id: "kasndaojsdnasd",
      username: "usuario1",
      password: "pwusuario1",
    },
    {
      id: "kasasdasdasd",
      username: "usuario2",
      password: "pwusuario2",
    },
    {
      id: "asdasdnasd",
      username: "usuario3",
      password: "pwusuario3",
    },
  ];
  //modify for the proper db service
  const user = users.find((user) => user.username == req.body.username);

  if (!user) {
    console.log("user not found");
    return res.send("user not found!");
  } else {
    bcrypt.hash(req.body.password, 10, function (err, hash) {
      if (err) {
        throw err;
      } else {
        bcrypt.compare(user.password, hash, function (err, result) {
          if (err) {
            throw err;
          }
          console.log(result);
          if (!result) {
            return res.status(201).json({ message: "Wrong password!" });
          } else {
            return res.status(201).json({ message: "Connected!", user: user });
          }
        });
      }
    });
  }
}

module.exports = login;

I've tested with both correct and incorrect password and username and works in every case

borjamunozvw avatar Feb 13 '23 08:02 borjamunozvw

@borjamunozvw your code here is incorrect; bcrypt expects compare(data, hash)

  • Data = user input
  • hash = hashed password from db

For others with this issue, unless someone provides me with a sample repository and some DB dump, I'll not be able to work on this case. I'm unable to reproduce this at my side.

recrsn avatar Feb 13 '23 09:02 recrsn

@borjamunozvw Yes you are right the 'user' is from database, however the

bcrypt.compare() require plaintext and hash password from database.

bcrypt.compare(plaintext, hashpassword)

and i also tried your code but it's still giving me false every time.

mosesrb avatar Feb 13 '23 09:02 mosesrb

@recrsn I am using [email protected] along with [email protected] with mongoDB compass. I have no idea why compare method is not working. I tried argon2 npm as well. The verify method in that package is also not working with my setup.

I think something is wrong with my database, I have increased the limit to 2048 char for password but still it's not working

mosesrb avatar Feb 13 '23 09:02 mosesrb

I had also same problem and finally I realised that we first have to save the one user and password will be encrypted and then compare will work properly. I did it and my problem was solved. If you have users in the db whose passwords aren't encrypted then compare will always return false.

SuhailHamid42 avatar May 27 '23 10:05 SuhailHamid42

I had also same problem and finally I realised that we first have to save the one user and password will be encrypted and then compare will work properly. I did it and my problem was solved. If you have users in the db whose passwords aren't encrypted then compare will always return false.

For avoidance of doubt, am comparing user's encrypted password stored in db against the user's provided password.

Gatharikih avatar May 27 '23 10:05 Gatharikih

Same issue. Seems to always returns false. Database column is enough large, tried to change $2b$ to $2a$ without chance, tried to use compare() instead of compareSync() but all same. Still returning false...

Any workaround?

Forium777 avatar Jun 15 '23 22:06 Forium777

I had also same problem and finally I realised that we first have to save the one user and password will be encrypted and then compare will work properly. I did it and my problem was solved. If you have users in the db whose passwords aren't encrypted then compare will always return false.

for me same issue how to solve

vamshizz avatar Jul 19 '23 11:07 vamshizz

This might be happened because of character length in your DB. Check this

Thank's a lot, you saved my day

PACMainArchitect avatar Sep 01 '23 09:09 PACMainArchitect

To resolve the issue, I observed that in the database, I was storing the password in a designated column with a character size smaller than the number of characters in the password hash. I simply made the change, and it worked.

JLimaRodrigues avatar Dec 16 '23 19:12 JLimaRodrigues

I was having the same error and apparently, as mentioned in this answer, it is an error in the database. In my case I had to define the maxlength to 60 in my MongoDB schema, I show you an example of what it looks like:

password: { type: String, required: true, unique: false, maxlength: 60 },

Hope it helps !!

noriaku avatar Dec 22 '23 17:12 noriaku