How to store passwords in database python

Store the password+salt as a hash and the salt. Take a look at how Django does it: basic docs and source. In the db they store $$ in a single char field. You can also store the three parts in separate fields.

The function to set the password:

def set_password[self, raw_password]:
    import random
    algo = 'sha1'
    salt = get_hexdigest[algo, str[random.random[]], str[random.random[]]][:5]
    hsh = get_hexdigest[algo, salt, raw_password]
    self.password = '%s$%s$%s' % [algo, salt, hsh]

The get_hexdigest is just a thin wrapper around some hashing algorithms. You can use hashlib for that. Something like hashlib.sha1['%s%s' % [salt, hash]].hexdigest[]

And the function to check the password:

def check_password[raw_password, enc_password]:
    """
    Returns a boolean of whether the raw_password was correct. Handles
    encryption formats behind the scenes.
    """
    algo, salt, hsh = enc_password.split['$']
    return hsh == get_hexdigest[algo, salt, raw_password]

How to hash passwords using the bcrypt library

Photo by Franck on Unsplash

When storing passwords, one of the greatest risks is that someone may steal the database and be able to decrypt them. To avoid this, you should always hash the passwords before storing them.

In this article, I will show you how to do this in Python using the bcrypt library.

Installing bcrypt

First of all, we need to install bcrpyt using pip.

pip install bcrypt

It is good practice [although not required] to create a new virtual environment for this project. If you want to learn more about this, check the following article.

What is Password Hashing?

First of all, it’s important to know the theory behind hashing.

A hashing function is a function that takes a string of bytes, and “transform” it to another string of bytes, from which it is impossible to determine the initial string. Furthermore, there aren’t two different inputs that give the same output.

This means that if we store the hashed password, even if someone stole the database they would not be able to determine what are the plain text passwords.

Now suppose that a user has registered with the password "HelloWorld" . Then to execute the login, we need to check if the password written by the user is the same as the stored one.

To do so, we can just hash the password used for the login, and then check if this hash corresponds to the stored one. Since by the definition of hash function there aren’t two different inputs that give the same output, the two hashes will be equal only if the password written by the user is the same as the one used during registration.

The only weakness is that if the password is short, an attacker may try to hash all possible passwords until he finds the correct one. However, this is unlikely if the password is long enough since there are too many combinations. But how to make sure that the password is long?

Usually, before hashing a password we will add a salt, i.e. a random sequence of characters. In this way, we know that even if the user uses a short password, it will be still secure.

Create a Password Database

Now that we have seen the idea behind hashing, let’s see how this works in Python. We will create a class PasswordDatabase , which will implement a method register[user, password] to add a new user and login[user, password] which returns true if the user user is registered with a password password .

First of all, we should create the __init__ method.

class PasswordDatabase:
def __init__[self]:
self.data = dict[]

Here data is the dictionary which stores usernames and passwords: the usernames are used as keys of the dictionary.

Registering a New User

Now let’s create the function to register a new user. It will:

  1. Check if the user is already registered and if this is the case return False . Otherwise, it should:
  2. Hash the password;
  3. add the user and hashed password to the dictionary;
  4. return True .

The first step is easy to implement: we just need to check if the username is already present in the dictionary.

def register[self, user, password]:
if user in self.data:
return False

Now we need to hash the password. Here is where bcrypt comes to our help.

First of all, we need to import it:

import bcrypt

Now we can create a method hash_password .

def hash_password[self, password]:
pwd_bytes = password.encode["utf-8"]
salt = bcrypt.gensalt[]
return bcrypt.hashpw[pwd_bytes, salt]

The first line is to convert the password [which is a string] into a sequence of bytes. In fact, bcrypt functions will operate on sequences of bytes, not on strings.

Then we create a salt for the password using bcrypt.gensalt[] . Finally, we can create the hash from the password bytes and the salt and return it.

Let’s go back to the register function. Here we need to call the hash_password method we just created, and then save the username and the hash into the dictionary. The function returns True because a new user has successfully been saved.

def register[self, user, password]:
if user in self.data:
return False
pwd_hash = self.hash_password[password]
self.data[user] = pwd_hash
return True

Log In a User

Another method needed by the Passworddatabase class is the one for executing login. This will take as input a username and a password, and then check if a user with the given username and password is registered.

def login[self, user, password]:
if user not in self.data:
return False
pwd_bytes = password.encode["utf-8"]
return bcrypt.checkpw[pwd_bytes, self.data[user]]

First of all, we need to return false if the username is not present in the database.

Then we can check if the password given as input corresponds to the hash saved in the database. As before, we need to convert the password string into bytes using the encode["utf-8"] function. Then we can call the function bcrypt.checkpw . This takes as argument the password [in bytes] and the hash. Then it returns true if and only if the password is correct.

Testing The Code

Here is the complete code of our PasswordDatabase :

import bcryptclass PasswordDatabase:  def __init__[self]:
self.data = dict[]
def register[self, user, password]:
if user in self.data:
return False
pwd_hash = self.hash_password[password]
self.data[user] = pwd_hash
return True
def login[self, user, password]:
if user not in self.data:
return False
pwd_bytes = password.encode["utf-8"]
return bcrypt.checkpw[pwd_bytes, self.data[user]]
def hash_password[self, password]:
pwd_bytes = password.encode["utf-8"]
salt = bcrypt.gensalt[]
return bcrypt.hashpw[pwd_bytes, salt]

We can test it with the following lines of code:

db = PasswordDatabase[]print["Registering users"]
print[db.register["john", "password"]]
print[db.register["Seth", "HelloWorld"]]
print[db.register["john", "myname"]]
print["Login"]
print[db.login["abc", "password"]]
print[db.login["john", "pwd"]]
print[db.login["john", "password"]]

If everything works correctly, the last register function should return false, because a user named “john” already exists.

Then when logging in the users, only the last call should return true: it is the only one where both username and password are correct.

Conclusion

Thank you for reading through to the end! If you want to learn more about the bcrypt library, here are some useful links:

More content at plainenglish.io. Sign up for our free weekly newsletter. Get exclusive access to writing opportunities and advice in our community Discord.

How do I store login credentials in Python?

3 Ways to Store and Read Credentials Locally in Python.
Storing them as system variables..
Storing them as variables in your virtual environment..
Storing them in a .env file..
The Most Convenient Way..

How do I create a password generator in Python?

How to Code a Password Generator in Python [in 4 Steps].
Step 1: Import necessary modules. As a first step, let's import the secrets module. ... .
Step 2: Define the alphabet. The next step is to define the alphabet. ... .
Step 3: Fix the length of the password; Generate a password. ... .
Step 4: Customize Your Passwords Based on Constraints..

How does Python store password in database in encrypted form?

Steps:.
Import Fernet..
Then generate an encryption key, that can be used for encryption and decryption..
Convert the string to a byte string, so that it can be encrypted..
Instance the Fernet class with the encryption key..
Then encrypt the string with the Fernet instance..

Where does Python store database credentials?

Store the credentials in a config file and access the file from the script. This is not a very secure option as the config file can get accidentally pushed to the repo thus exposing your credentials. Store the credentials in a config file and use AWS KMS decryption to encrypt the password.

Chủ Đề