Bcrypt has a method called checkpw()
, which allows you to check whether the entered password matches the hashed password, which is saved in the database.
bcrypt.checkpw(password, hashed):
I used checkpw()
method as well like below;
if bcrypt.checkpw(login_password.encode("utf-8"), registered_password):
return JsonResponse({"message" : "login success"}, safe=False)
In my last post, I mentioned that you have to save a decoded password to the database because it would cause errors in login otherwise. I encoded the login_password
, which is the password that a user entered to login, but did not encode registered_password
, which is the hashed password because I had encoded it before hasing when I saved it to the database.
But it gave me this error
Unicode-objects must be encoded before checking
Facing the error message, I changed my code to this
if bcrypt.checkpw(login_password.encode("utf-8"), registered_password.encode("utf-8")):
return JsonResponse({"message" : "login success"}, safe=False)
But the code above doesn’t really make sense because I am “double-encoding” my hashed password, so I go another error message like this below
File "/Users/byeongjinkang/miniconda3/envs/lunch_buddy/lib/python3.7/site-packages/bcrypt/__init__.py", line 86, in hashpw
raise ValueError("Invalid salt")
ValueError: Invalid salt
I thought this implied that my salt, which was randomly generated by bcrypt.gensalt()
, was invalid, which doesn’t make sense. Why is bcrypt telling me that a salt, which was randomly generated by bcrypt, was invalid? In order to get deeper into the problem, I decided to look into that __init__.py
, and this is where the error occurred.
hashed = _bcrypt.ffi.new("char[]", 128)
retval = _bcrypt.lib.bcrypt_hashpass(password, salt, hashed, len(hashed))
if retval != 0:
raise ValueError("Invalid salt")
The bcrypt library describes this section that the hashed password must have the $2b$
prefix, which is achived by decoding the password. If you save the password without decoding it, its prefix becomes b'$2b$
, which raises an error.
Then you could argue “why don’t you save it as an encoded password?” I tried it, but unfortunately(?) bytes
object, whish is a type of the hashed password, doesn’t have an attribute encode
. So this is pretty much the only way.
In my next post, I am going to talk about how to use jwt
token.