user7153744
user7153744

Reputation: 331

bcrypt.checkpw returns TypeError: Unicode-objects must be encoded before checking

I am calling bcrypt.checkpw to check unencrypted password matches with hashed password stored in the credential database, but receive

TypeError: Unicode-objects must be encoded before checking

How should I resolve this issue? Any suggestion?
I installed python 2.7.6, and bcrypt 3.1.1

I have the following code:

def check_password(password, hashed_password)
    if not bcrypt.checkpw(password, hashed_password):
        raise InvalidCredentials("403 Forbidden")
    else:
        return true

And receive the following error:

File "/home/qt/virtualenv/lib/python2.7/site-packages/bcrypt/init.py", line 100, in checkpw
raise TypeError("Unicoed-objects must be encoded before checking")
TypeError: Unicode-objects must be encoded before checking

I looked into bcrypt/__init__.py, but I'm not sure why

def checkpw(password, hashed_password):    
    if (isinstance(password, six.text_type) or            
        isinstance(hashed_password, six.text_type)):        
    raise TypeError("Unicode-objects must be encoded before checking")

Upvotes: 33

Views: 32342

Answers (5)

Kirui Aron
Kirui Aron

Reputation: 1

I had the same error and here is the solution You have to decode after encoding before checking hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

if user and bcrypt.checkpw(password.encode('utf8'), user.password.encode('utf-8')):

Upvotes: 0

Sunday Ikpe
Sunday Ikpe

Reputation: 974

Something you could do like this

bcrypt.checkpw(password.encode('utf-8'), hashed_password)

simple does it

Upvotes: 14

Jonathan Duclos
Jonathan Duclos

Reputation: 130

Using that like e.g. and see the comments below the code:

import bcrypt

def comparacaoSenha(passw, hash):
    if bcrypt.checkpw(passw, hash):
        print("It Matches!")
    else:
            print("It Does not Match")

password = "super secret password".encode('utf-8')
password2 = "another password".encode('utf-8')

hashed = bcrypt.hashpw(password, bcrypt.gensalt())
heashed2 = bcrypt.hashpw(password2, bcrypt.gensalt())

print("Teste 1: ")
print("-----------------------------")
print("PASSWORD: ", password)
print("HASHED PW: ", hashed)
comparacaoSenha(password, hashed)
print("-----------------------------")

print("Teste 2: ")
print("-----------------------------")
print("PASSWORD: ", password2)
print("HASHED PW: ", heashed2)
comparacaoSenha(password2, heashed2)
print("-----------------------------")

# Things to remember:
# always use the encode('utf-8') or put a prefix 'b'' just before the strings
# EX: newPass = b"OTHER PASSWORD" // or newPass="OTHER PASSWORD".encode('utf-8')
# 

Upvotes: 0

Gosha null
Gosha null

Reputation: 641

i use something like that

class User(Base):
    __tablename__ = "user"
    id = Column(BigInteger, primary_key=True, autoincrement=True)

    login = Column(String, nullable=False, unique=True)
    password = Column(String, nullable=False)

    @staticmethod
    def make_password_hash(password):
        hash = bcrypt.hashpw(password=password.encode('utf-8'), salt=bcrypt.gensalt())
        return hash.decode('utf-8')

    def is_password_valid(self, password):
        return bcrypt.checkpw(password.encode('utf-8'), self.password.encode('utf-8'))

Upvotes: 9

Laurent LAPORTE
Laurent LAPORTE

Reputation: 22992

I make the assumption that you use Python 3. With Python 3, strings are, by default, unicode strings.

If you call the bcrypt.checkpw() function with unicode values:

import bcrypt

password = "seCr3t"  # unicode string
hashed_password = "hashed_seCr3t"  # unicode string

bcrypt.checkpw(password, hashed_password)

You'll get this exception

Traceback (most recent call last):
  ...
TypeError: Unicode-objects must be encoded before checking

The reason is simple: cryptographic functions only work on bytes strings (or arrays in fact).

You password and hashed_password must be both bytes strings.

If you use the bcrypt.hashpw() function, your hashed_password must be a bytes string, and I think the problem is for the password value. This password must come from a HTML form of something similar. To use the bcrypt.checkpw() function, you must first encode the string value using the same encoding you use to encrypt the password with the bcrypt.hashpw() function. Usually, we choose 'utf8' encoding.

For instance (Python 2 & 3):

import bcrypt

# at creation first:
password = u"seCr3t"
hashed_password = bcrypt.hashpw(password.encode('utf8'), bcrypt.gensalt())

# first attempt:
password = u"seCrEt"
bcrypt.checkpw(password.encode('utf8'), hashed_password)
# -> False

# second attempt:
password = u"seCr3t"
bcrypt.checkpw(password.encode('utf8'), hashed_password)
# -> True

See simple usage on Gihub page

Upvotes: 36

Related Questions