0

Hi there developer folks,

I'm trying to write a little proof-of-concept program on repl.it which stores credentials securely using BCrypt. To save myself faffing with SQL, I'm prototyping using the built in repl.it database to store credentials.

The method in question is as follows:

def SignUp(self):
        '''Takes the username and password used to initialise the object, and stores them securely'''

        username = self.__username_input
        # Convert password input into bytes object
        password_bytes = bytes(self.__password_input, "UTF-8")
        # Hash password using the BCrypt algorithm
        hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt(rounds=14))
        
        username_available = True # True for testing - change to False for production

        # Checks if the username is available
        try:
            db[username]
        except KeyError:
            username_available = True

        if username_available:
            # Store password in database
            db[username] = hashed_password
            self.Username = username
            self.IsAuthenticated = True
            print(db[username])
            return True
        else:
            return False

Currently, when I run this, I get the following error:

TypeError: Object of type bytes is not JSON serializable

Now I've tried changnig db[username] = hashed_password to db[username] = str(hashed_password), which works fine, but then when I grab the hashed password back out of the database like so bcrypt.checkpw(password_bytes, bytes(db[username], "UTF-8")), BCrypt throws this error:

ValueError: Invalid salt

Any suggestions would be awesome.

Thanks!

gwood
  • 23
  • 4
  • It helps if you tell us specifically which lines are generating the error messages you are describing. – larsks Jan 31 '21 at 14:35
  • Currently the error is coming from Line 20. – gwood Jan 31 '21 at 14:37
  • Just a reminder: Python adds values called `salt` to hash for security reasons. Salt value is different per python instances. – jupiterbjy Jan 31 '21 at 14:50
  • Oh yeah, I know, thanks though! I'm pretty sure in this case the salt is integrated into the final hash string produced by BCrypt. – gwood Jan 31 '21 at 14:52

1 Answers1

0

The problem seems to be that db supports only serializable objects. Since I don't know what db is, in my outdated answer I assumed you were using a dictionary, but that's not true.

# Store the password by encoding the bytes
db[username] = hashed_password.decode()

# Check it decoding the string
bcrypt.checkpw(password_bytes, db[username].encode())

Differences between using str() and bytes(), and using .encode() and .decode()

password = '123123'
password_bytes = bytes(password, "UTF-8")

str_convert = str(password_bytes)
bytes_convert = bytes(str_convert, "UTF-8")
# str_convert = "b'123123'"
# bytes_convert = b"b'123123'"

decode = password_bytes.decode()
encode = decode.encode()
# decode = '123123'
# encode = b'123123'

Even though the first time you use password_bytes = bytes(password, "UTF-8") and it works, I don't recommend converting strings to bytes this way. It is better if you use .encode()

Lucas Vazquez
  • 1,456
  • 16
  • 20
  • The issue is if I leave it alone, it throws the error TypeError: Object of type bytes is not JSON serializable. I'm pretty sure it needs converting to something, I just can't figure out what. – gwood Jan 31 '21 at 14:39
  • Apologies for not clarifying. DB is the repl.it built in database. – gwood Jan 31 '21 at 14:47