Python Password Hashing
We will learn about password hashing and how to encrypt a salt and hash password with a third-party library called bcrypt
. We also look at different hashing algorithms from the hashlib
library in Python.
Salt and Hash Password With bcrypt
Library in Python
Hashing is the process of taking a string and turning it into a seemingly random string of a fixed length, and that process is irreversible. It is a one-way function, so you cannot return the hash to its original string like encryption, where you can encrypt a message and then decrypt it.
Hashing is used in user management; for example, if we have some database breach or lose data or someone hacks our system when we use a plaintext password. Hashing gives us some layer of protection; however, the hashed password cannot easily be cracked if we maintain it properly.
In this section, we will see how to work with hashed passwords using the bcrypt
module; let’s go ahead and jump into the code. We are going to use a third-party library called bcrypt
, which is a hashing algorithm.
bcrypt
is a reliable, robust, and recommended algorithm for hashing passwords; it gives us some nice and simple-to-use functions that let us get things done quickly.
First, we will install this library by using the following command.
pip install bcrypt
Now we need to import bcrypt
, create a password, and store it in a variable, and the password must be a byte string. To hash this password, we will create a new variable called hashed_pswd
and call the hashpw()
method from bcrypt
.
It takes two arguments; the first is a password, and the second is something called gensalt()
, randomly generating a number or a salt and hash password.
import bcrypt
My_pswd = b"Mypassword111"
hashed_pswd = bcrypt.hashpw(My_pswd, bcrypt.gensalt())
print(hashed_pswd)
Output:
b'$2b$12$KEW01pYNDc3ee9U0wZpmgOBpUvvjkig/qxs593hGh/aZ2AvvGTyWu'
Hash a Password Using hashlib
Library
This section will use the hashlib
library to create a salt and hashed password. If you pass secure data like passwords and stuff from one location to another, it is a good idea to ensure that someone cannot read it.
There are two types of things that you can do when you want to hide something or make it unreadable for the user. The first is hashing, and the second is encryption; encryption is mostly not used in passwords.
If we want to transfer files from our computer to another or send a file, then we use encryption. But, if we want to check whether the password is correct or not or to store passwords in our server, then mostly hashing is used.
The best thing about the hashlib
library is that we do not need to install anything; it comes with Python 3 or a newer version. After importing hashlib
, we will create an object called MD5_Algo
and call md5()
from hashlib
.
md5
is just a kind of hashing algorithm, md
stands for message-digest
, and 5
is the version. Now we need the string we want to convert plaintext into hashing, and for this, we call the update()
method and write the string we want to hash.
Then inside the print()
function, we call the hexdigest()
method; after converting the strain to actual md5
, it converts into a hex form.
import hashlib
MD5_Algo = hashlib.md5()
MD5_Algo.update("hello")
print(MD5_Algo.hexdigest())
This piece of code throws an error (Unicode objects must be encoded before hashing), and in the above section, we already discussed that we need to convert a string into bytes.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_4064/2416014515.py in <module>
2
3 MD5_Algo=hashlib.md5()
----> 4 MD5_Algo.update('hello')
5 print(MD5_Algo.hexdigest())
TypeError: Unicode-objects must be encoded before hashing
After converting the string into bytes, we see it gives us an md5
encrypted hashed password.
import hashlib
MD5_Algo = hashlib.md5()
MD5_Algo.update(b"hello")
print(MD5_Algo.hexdigest())
Output:
5d41402abc4b2a76b9719d911017c592
hashlib.sha512()
There are also other kinds of encrypted hash; let’s find out what kind of hashing stuff is actually inside Python. We can print out available algorithms using the algorithms_available
attribute.
print(hashlib.algorithms_available)
Output:
{'md4', 'md5', 'shake_256', 'shake_128', 'sha512_224', 'md5-sha1', 'sha224', 'sha3_512', 'sha1', 'sha3_384', 'sha512', 'sha3_224', 'sha512_256', 'sha384', 'sha256', 'blake2b', 'sha3_256', 'blake2s', 'ripemd160', 'whirlpool', 'sm3', 'mdc2'}
As we can see, there are a lot of cool algorithms, and obviously, all of these objects have the same sort of structure, they will have the same functions and variables, but it is just a different algorithm.
sha512
is the one we will use and pass in a string; after that, we use hexdigest()
to that string, which will be hashed.
import hashlib
MD5_Algo = hashlib.sha512(b"hello")
print(MD5_Algo.hexdigest())
When we run this code, we get a long mass of characters.
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
sha512
is stronger and kind of better than sha1
; it all depends on the scenario you determine as better or best in your circumstances.
Salting and Hashing
The problem with these kinds of old algorithms is that they can be brute-forced or reverse-engineered, and it is not that safe because everyone can decrypt this encrypted hash easily. Our encrypted hash is hello
; what if we do a dictionary attack and decrypt it from the sha512
dictionary?
The downfall of sha512
is that many people use their passwords on Facebook or other applications; usually, they use their birthdays which have already been reversed and looked at in sha512
, so that is why it is not a safe way.
One of the safest ways is salting; salting adds some character in front of your original string. Let’s say if we add "a"
in front of "hello"
, we have added the character "a"
as salt in front of our original string.
hashlib.sha512(b"helloa")
Now we have encrypted this hash with this extra salt which is why it will be very difficult for hackers and other people who try to figure out how to decrypt the hash, so that is where the salt comes in.
hashlib.pbkdf2_hmac()
In Python, the hashlib
library has a function that is a little bit slow but a pretty good function called pbkdf2_hmac()
. We will be using this function and the second library is actually for converting the binary to ASCII characters.
The pbkdf2_hmac()
requires a couple of parameters; the first parameter is the name of the algorithm we will use, so we are using sha512
in this case. The next one is the password or the text we want to hash; in this case, it will be "hello"
.
The next one is called salt, the salt will be added to this password, and then they will be encrypted using sha512
. And the last one is the number of iterations; if we do this iteration a hundred thousand times, then it is going to be very difficult to find it to decrypt.
In the last line of code, we convert the encrypted hash to an ASCII character using the hexlify()
method from the binascii
library.
import hashlib
import binascii
Enc_Salt = hashlib.pbkdf2_hmac("sha512", b"hello", b"a", 100000)
print(binascii.hexlify(Enc_Salt))
Output:
b'40b5957a2d2f5aebcdd878a04e644215d4f3aba3f11c00a1f24e75f8ea2efa11611b2a923a9050832cb768a3a3ad282011cab524b741d392c664b8efbb5f389f'
Now we can see the sha512
dictionary cannot decrypt.
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn