Introduction
Following on from some of my previous content about data security, I’ve written a short proof of concept program showing how BCrypt can be used to securely store passwords.
I hope you like it, and feedback is always welcome.
Code
main.py
try:
from user import User
import os
import time
except ImportError:
print("\nError! Necessary libraries unavailable...\n")
def clear():
time.sleep(2.5)
os.system('cls' if os.name == 'nt' else 'clear')
username = input("Username: ")
password = input("Password: ")
# Example Username: testUser
# Example Password: testPass
user = User(username, password)
go = True
while go:
try:
menu = int(input("\nEnter 1 to login\nEnter 2 to sign up\nEnter 3 to delete your credentials from the database\nEnter 4 to exit\n: "))
if menu == 1:
result = user.Authenticate()
if result == True:
print(f"\nSuccess!\nYou are logged in as: {user.Username}")
clear()
else:
print("\nError! please try again...")
clear()
elif menu == 2:
result = user.SignUp()
if result == True:
print(f"\nSuccess!\n\nYou are logged in as: {user.Username}")
clear()
else:
print("\nError! that username is taken...")
clear()
elif menu == 3:
result = user.RemoveUser()
if result == True:
print(f"\nThe credentials associated with the username {username} have been deleted.")
clear()
# Terminate program as User object must be recreated.
go = False
else:
print("\nPlease make sure you are logged in before deleting your credentials.\n")
clear()
elif menu == 4:
clear()
go = False
else:
print("\nError! Please try again...")
clear()
except:
print("\nAn unexpected error has occurred! Please try again...")
clear()
user.py
try:
import bcrypt
from replit import db
except ImportError:
print("\nError! Necessary libraries unavailable...\n")
class User:
IsAuthenticated = False
Username = ""
__Attempts = 0
def __init__(self, username_input, password_input):
# Initialise private variables
self.__username_input = username_input
self.__password_input = password_input
def SignUp(self):
'''Takes the username and password used to initialise the object, and stores them securely'''
username = self.__username_input
# Encode password to UTF-8 for use by BCrypt
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 = False # True for testing - change to False for
# 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.decode()
self.Username = username
self.IsAuthenticated = True
return True
else:
return False
def Authenticate(self):
# Default to False
authenticated = False
username = self.__username_input
# Encode password to UTF-8 for use by BCrypt
password_bytes = self.__password_input.encode("UTF-8")
# Checks if the username is recognised
try:
stored_password = db[username]
except KeyError:
return False
# Will return True if the inputted password matches the stored hash
authenticated = bcrypt.checkpw(password_bytes, stored_password.encode("UTF-8"))
if authenticated:
self.IsAuthenticated = True
self.Username = username
return True
else:
self.__Attempts += 1
return False
def RemoveUser(self):
username = self.__username_input
try:
# Credentials can only be removed if the user has logged in
if self.IsAuthenticated == True:
del db[username]
self.IsAuthenticated = False
return True
else:
return False
except:
return False
Note: The code is also available on repl.it, and is designed to run on there.
Test Credentials
Username: testUser
Password: testPass
-George