Day 071 - Project 71 : Hashing passwords

If you have any questions, comments or issues with this project please post them here!

import random
from replit import db
print("welcome to system\n")
user=input("1:Newuser~ \n2:Login~ \n")
keys = db.keys()
if user== "1":
  print("Welcome cadet!Chose your username and password to proceed further.")
  username=input("Username: \n")
  password=input("Password: \n")
  salt=random.randint(10000,99999)
  newPassword=f"{password}{salt}"
  newPassword=hash(newPassword)
  db[username] = {"password": newPassword,"salt": salt}
  print("User id created,Welcome Soldier",username,".")
elif username in keys:
  print("Error user already exist, Log in? ")
elif user== "2":
  print("Login")
  username=input("username: \n")
  newPassword=input("password: \n")
  if username not in keys:   
    print("Error no user found, Create an account? ")
  else:
    username=input("Username: \n")
    password=input("Password: \n")
    salt=db[username]["salt"]
    newPassword=f"{password}{salt}"
    newPassword=hash(newPassword)
    if db[username]["password"] ==newPassword:
      print("User id created,Welcome Soldier",username,".")
    else:
      print("wrong username or password \n Try again.")

can someone fix the login error I’m getting db will always be confusing to me :pray:thank you

  1. format your code, like this:

```py

print("Hello World!")

```
2. explain the error

2 Likes

If you format your code like bigminiboss said it will be easier for us to understand it, you can also just link the repl as well.

Right off the bat I can see that you are doing some stuff wrong with Salting your password. The salt shouldn’t be random and storing it along side the password is literally removing the added security that salt provides

The idea of salting your password is that even if a hacker get’s all your encrypted passwords, they won’t be able to decrypt them even with a really fast tool like hashcat because they don’t have the salt for the password. If you are storing your salt along side your password, they now know exactly what your salt is and will be able to crack your passwords.
This is a major security flaw.

Instead of generating a random salt and storing it along side your password, you should put your salt in a .env or replit secrets, that way the password and salt and seperate, and unless the hacker has both of them they won’t be able to crack your password.

4 Likes

Try something like this:

import random, os
from replit import db
import hashlib


mysalt = os.environ["SALT"]

user = ""


def hash_password(password):
	return hashlib.sha256(password.encode()).hexdigest()

while True:
	print("[1] New User")
	print("[2] Login")
	
	choice = input("-> ")
	
	if choice == "1":
		username = input("Username: ")
	
		# check if username is taken
		if username in db.keys():
			print("Username taken!")
			continue
			
		password = input("Password: ")

		hash = hash_password(f"{password}{mysalt}")

		db[username] = hash

		user = username

		break

	
	elif choice == "2":
		username = input("Username: ")

		if username not in db.keys():
			print("That username does not exist!")
			continue

		password = input("Password: ")

		hash = hash_password(f"{password}{mysalt}")

		if db[username] == hash:
			print("Logged in")
			user = username
			break
		else:
			print("Incorrect password!")

	else:
		print("That is not an option")

print(f"Welcome {user}")
4 Likes
import random
from replit import db
print("welcome to system\n")
user=input("1:Newuser~ \n2:Login~ \n")
keys = db.keys()
if user== "1":
  print("Welcome cadet!Chose your username and password to proceed further.")
  username=input("Username: \n")
  password=input("Password: \n")
  salt=random.randint(10000,99999)
  newPassword=f"{password}{salt}"
  newPassword=hash(newPassword)
  if (username not in db.keys()):
    db[username] = {"password": newPassword,"salt": salt}
    print("User id created,Welcome Soldier",username,".")
  else:
    print("Error user already exist, Log in? ")
elif user== "2":
  print("Login")
  username=input("Username: \n")
  password=input("Password: \n")
  if username not in db.keys():   
    print("Error no user found, Create an account? ")
  else:
    salt=db[username]["salt"]
    newPassword=f"{password}{salt}"
    newPassword=hash(newPassword)
    if db[username]["password"] ==newPassword:
      print("User id created,Welcome Soldier",username,".")
    else:
      print("wrong username or password \n Try again.")
2 Likes

@InvisibleOne damn bruh I just learned salting yesterday :skull:but thank you for the explanation also a very nice website that you built I hope one-day id be able to id be neat to have my own website xD
and I dk what hashlib is brb gotta google that :dove:

ah, bro, I can see you’ve put my salt with password inside hash_password but you didn’t create salt? ig .
also what this line means -
hashlib.sha256(password.encode()).hexdigest()

When I call the function to hash the password, I’m inputting the salt and the password together, so it is being salted

hash = hash_password(f"{password}{mysalt}")

And to answer your question about hashlib, hashlib is a python library for hashing stuff. Sha256 is a known hashing algorithm that is super secure (except against quantum computers). .hexidigest() get’s the hex version of the hash, it outputs a string that makes it easier for storing.

2 Likes

sha256 can be brute-forced because it’s made to resolve quickly, so it’s better for verification, signature, identification than passwords
Instead you could use something like

db[username] = hashlib.pbkdf2_hmac('sha256', password.encode(), os.environ["SALT"], 1024)
1 Like

I disagree, if it’s salted correctly cracking Sha256 is going to take literal years.

1 Like

1 Like

cracking the algorithm != brute-forcing a password, which would mean checking the sha256 hash of many passwords until you get to the correct hash

1 Like

If it’s salted that is physically impossible. If the average password is like 8-10 chars or whatever, and it isn’t salted then there is a limited enough pool of possible passwords that it could be brute forced. but if I salt it with another string of like 50 chars, now the length of my password is around 60 chars, meaning there are around 26^60 possible passwords, with is physically impossible to brute force.

1 Like

Important to recognise the difference between probability and feasibility. It isn’t impossible, it just isn’t feasible. It would take way too long for anyone to even consider trying it.

1 Like

Hi guys,
I am a bit stuck again… The Login doesn’t work as intended…

My code produces the correctly hashed password from the user password (including the stored salt)
but yet the matching doesn’t work :frowning: Can you spot why it is not matching??

(I made #comments to explain my thinking)

from replit import db
import random

def create():
  username = input("Create Username: ")
  password = input("Create Password: ")
  salt=salter()
  password_hashed = hash(f"{salt}{password}")
  db[username]={"salt":salt,"password":password_hashed}
  
def login():
  username = input("Enter Username: ")
  password = input("Enter Password: ")
  salt = db[username]["salt"]
  password_hashed = hash(f"{salt}{password}")
  print(password_hashed) #for validation
  if username == db[username] and password_hashed == db[username]["password"]:
    print(f"Welcome {username}!") #this is not working!
  else:
    print("Incorrect Login")

def salter():
  s=random.randint(0,11)
  a=random.randint(0,11)
  l=random.randint(0,11)
  t=random.randint(0,11)
  salt=f"{s}{a}{l}{t}"
  return int(salt)

for key, value in db.items():
    print(f"{key}: \t{value}") #just to check what's stored so far

while True: 
  print("LOGIN SYSTEM\n\n")
  menu=input("1: Add User\n2: Login\n> ")
  if menu == "1":
    create()
  elif menu == "2":
    login()
  else: 
    print("No valid option! Try again!")

Thanks so much for your help!! :pray:

That condition is where you have an error. I am sure you can immediately see why …

is it because username is a string and db[username] is a dictionary?

either way, I’ve changed it to

if username in db.keys()

and that works :slight_smile:

but please enlighten me!
did you have a different solution in mind?

The problem is that you are storing under the user name salt and hashed password in a dict and wanted to compare such dict to a string … which will always be false as they are never the same.

From the way you wrote the program you actually only need to check the hashed password because if the user is wrong the hashed values are different (except in the rate case the password happen to be the same for two different users)

2 Likes

if this makes it easier, replit db is just a giant dictionary named db which can hold up to around 1000 values/100MB

1 Like