I am trying to create a login system for my project and I need to use hashing for the users password, I am unsure how to hash a variable name and convert it into bytes to give a hex result for the password.
tried using:
hash_object = hashlib.md5(b(password))
and:
hash_object = hashlib.md5((password))
Code:
import hashlib
user = {}
username = input("What is your username? ")
password = input("What is your password? ")
hash_object = hashlib.md5((password))
print(hash_object.hexdigest())
Error:
Traceback (most recent call last):
File "E:\loginsystem.py", line 8, in <module>
hash_object = hashlib.md5((password))
TypeError: Unicode-objects must be encoded before hashing
Encode the password string with the .encode method.
import hashlib
user = {}
username = input("What is your username? ")
password = input("What is your password? ")
hash_object = hashlib.md5(passsword.encode('utf8'))
print(hash_object.hexdigest())
I recommend this great thread that might clear some things up:
What is the difference between a string and a byte string?
Related
I am trying to write a code that will work like this:
First function of the code is registration:
here the user will input their username and password, then the code will create a text file named after the username and it will include 2 lines:
1.username
2.password
import time
def registracia():
print ("To register you'll need to type your username and your password.")
time.sleep (1.5)
userName = input("username: ")
time.sleep (1.5)
passWord = input("password: ")
filename = userName + ".txt"
file = open(filename, "+w")
file.write (userName+"\n")
file.write (passWord)
file.close
if __name__ == "__main__":
registracia()
Then there's the 2nd function of the code and that will be login.
My thought for the login is that it will ask for input of the username, then it will open the file named after the username and read the 2nd line, after reading the line it will ask for input of password and then use if to check if the input is equal to the 2nd line.
My problem is that the readline only reads 1 letter from the username, at least that's what I think it's doing.
import time
print ("To login you'll need to type your username first")
def login():
#time.sleep (1.5)
userName = input ("username: ")
filename = userName +".txt"
file = open(filename, "r")
#time.sleep (1.5)
realPassWord = file.readline(2)
print (realPassWord)
passWord = input ("password: ")
if passWord == realPassWord:
print ("successfuly logged in ")
elif passWord != realPassWord:
print ("incorrect password")
login()
login()
I'm also adding an example of input and outputs to see what's happening:
Registration:
Input:
username: abc321
password: cba123
Output:
abc321.txt (a text file):
abc321
cba123
Login:
Input:
abc321
Output (the output shouldn't be really visible, output is what the code will expect for the password input, but I added the print of realPassWord so I can see what the code expects):
ab
Desired output:
cba123
The logic of the code looks alright. There are just some typos or syntax errors I would like to fix.
I did not fix the style guide problems. For that I would recommend following the PEP8 Coding Guidelines, especially when naming variables. Please use snake_case for that in Python, instead of camelCase.
Also do not forget to call file.close() with the () - brackets.
import time
def registracia():
print("To register you'll need to type your username and your password.")
time.sleep(1.5)
userName = input("username: ")
time.sleep(1.5)
passWord = input("password: ")
filename = userName + ".txt"
file = open(filename, "w+")
file.write(userName + "\n" + passWord)
file.close()
if __name__ == "__main__":
registracia()
For the login part, the problem is, that file.readline(2) only reads the first two bytes.
Therefore you need to use something that splits your file content into lines.
In your case, you could use file.read().splitlines()[1].
import time
print ("To login you'll need to type your username first")
def login():
#time.sleep (1.5)
userName = input("username: ")
filename = userName +".txt"
file = open(filename, "r")
#time.sleep (1.5)
realPassWord = file.read().splitlines()[1]
print(realPassWord)
passWord = input("password: ")
if passWord == realPassWord:
print("successfuly logged in ")
elif passWord != realPassWord:
print("incorrect password")
login()
login()
Just a note:
I would never recommend storing passwords as a plain text into text-files. If you consider using that seriously, then be sure to hash your passwords and maybe even store them into databases.
The core issue with you code is how you are reading from the file.
There are a few other things I would also point out.
You are storing the username in the file but you never use it. Having the password and username in the file in plain text does not seem to be good security.
The password is also currently echoed to the terminal when it is typed in.
Python has some functionality you might want to look at:
Python has password input functionality to prompt the user for a password without echoing:
https://docs.python.org/3/library/getpass.html
Hashing the value of the password stored in the file:
https://docs.python.org/3/library/hashlib.html#hashlib.scrypt
Using UUID for the file name rather than the username:
https://docs.python.org/3/library/uuid.html
Pathlib to simplify reading and writing files:
https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_bytes
https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_bytes
Password compare with “constant-time compare” to reduce the risk of timing attacks
https://docs.python.org/3/library/secrets.html#secrets.compare_digest
The following is not exhaustive and may not be right for your situation. It is just an example of these being used:
from getpass import getpass
from hashlib import md5, scrypt
from pathlib import Path
from secrets import token_bytes, compare_digest
import time
import uuid
SALT_SIZE = 64
def filename_uuid(filename):
_hash = md5()
_hash.update(filename.encode('utf-8'))
uuid_name = uuid.UUID(_hash.hexdigest())
return Path(f"{uuid_name}.txt")
def password_hash(password, salt):
hash_value = scrypt(password, salt=salt, n=16384, r=8, p=1)
return salt + hash_value
def check_password(password, stored_value):
salt = stored_value[:SALT_SIZE]
_password = password_hash(password, salt)
return compare_digest(_password, stored_value)
def registracia():
print("To register type your username and your password.")
username = input("username: ")
password = getpass().encode('utf8')
salt = token_bytes(SALT_SIZE)
token = password_hash(password, salt)
filename = filename_uuid(username)
filename.write_bytes(token)
def login(attempts=0):
print("To login you'll need to type your username first")
username = input("username: ")
filename = filename_uuid(username)
try:
token = filename.read_bytes().strip()
except FileNotFoundError:
token = b""
password = getpass().encode('utf8')
if check_password(password, token):
print("successfully logged in ")
else:
print("incorrect username/password combination")
if attempts < 1:
login(attempts + 1)
if __name__ == "__main__":
registracia()
login()
I'm trying to compare a saved hash and a user input in python using bcrypt. My code:
while passnotcorrect == True:
password = input("Enter password: ")
password = password.encode('utf-8')
file = open('password.txt', 'r')
checkhash = file.read()
file.close()
checkhash = checkhash.encode('utf-8')
if bcrypt.checkpw(password, checkhash):
passnotcorrect = False
os.system('cls||clear')
else:
print("Password is incorrect \n")
The error:
ValueError: Invalid salt
I'd really like some help with this. I'm not sure why this function would require the salt in the first place. Thanks
A little late but I think your issue is that you're trying to compare 'password' which is utf8 encoded string input with 'checkhash', another string read from a file.
Bcrypt.checkpw() takes in a UTF8 encoded string for the password to check as the first argument followed by the UTF8 encoded hash to compare the password being provided against to see if the provided pass matches the hash pass.
TLDR; you're passing two strings to the checkpw method, when the second argument needs to be the hash you're comparing against (gold standard).
db_pass = "pw-string123" # from database
password = "pw-string123" # from input
db_hashed_pass = bcrypt.hashpw(db_pass.encode('utf8'), bcrypt.gensalt())
print(f'Hashed pass to save in db: {db_hashed_pass}')
is_pass_matching = bcrypt.checkpw(password.encode('utf8'), db_hashed_pass)
print(f'Do passwords match? {is_pass_matching}')
Make sure your hashed password isn't being truncated (length matches) upon entry or retrieval.
I am making a login system for my project, and I have the usernames and passwords stored in a text file, with usernames in the first column and passwords in the second column, and then separating each login/password with a new line and using : as a barrier between the username/password.
Upon entering the correct username and password, I always get incorrect login, however if I only compare the username to the file it functions properly. Even if I print the password and username straight from the file and then print it next to the username/password I entered, it is still the exact same yet still say incorrect login!
def login():
file=open("user.txt","r")
user=input("enter usename")
password=input("enter password")
Check=False
for line in file:
correct=line.split(":")
if user==correct[0] and password==correct[1]:
Check=True
break
if Check==True:
print("succesffuly logged in")
file.close()
mainMenu()
else:
print("incorrect log in")
file.close()
login()
I suspect you have a \n at the end of each user / password string. I suspect line looks like user:pass\n after being read in. Use line.strip().split(':') to remove the newline, which is causing password==correct[1] to fail.
Replace:
for line in file:
correct=line.split(":")
With:
for line in file:
correct=line.strip().split(":")
For why, see https://docs.python.org/2/library/string.html#string.strip
string.strip(s[, chars])
Return a copy of the string with leading and trailing characters removed. If chars is omitted or None, whitespace characters are removed. If given and not None, chars must be a string; the characters in the string will be stripped from the both ends of the string this method is called on.
We can just check using in
def login():
file = open("user.txt", "r")
user = input("enter usename ")
password = input("enter password ")
if ('{0}:{1}'.format(user, password)) in file:
print('yay')
else:
print('Boo !! User not found')
login()
if you wanted to use the for loop I would suggest:
def login():
file = open("user.txt", "r")
user = input("enter usename ")
password = input("enter password ")
for line in file:
temp_user, temp_password = line.strip().split(':')
if temp_user == user and temp_password == password.strip():
print('yay')
else:
print('boo username and password not found!')
login()
Really important, WARNING!
Please take necessary security measurements as this code does not provide any, there are a lot of vulnerabilities that could be exploited. No hashing function and Python itself does not provide a lot of security, I would suggest using getpass.getpass explanation HERE
Hello i am looking for some help. so for some back ground this code is going to be used as a log in system for personal use. i am trying to get it to check just one line so i can get it to validate that the username is correct and or the password. how would i do this?
user = input("please Enter your full name: ")
if os.path.isfile(user + ".txt"):
with open(user + ".txt", "r")
print("------------------------")
Username = input("|Username: ")
password = getpass.getpass("|Password: ")
print("------------------------")
Ok, if you insist on doing it in an insecure way then I guess you have just a file with a plaintext user name and password in it. I understand that perhaps you are knew to Python so an insecure method is somewhat acceptable :P. Example below,
bosh
password
(in the file there would be no gap between lines as shown above, they would be on consecutive lines)
If not then I recommend you do this as this is how the code section below will expect it to be.
submittedUsername = input("Please enter username: ")
submittedPassword = input("Please enter password: ")
credentialsFile = open("credentials.txt", "r")
credentials = credentialsFile.readlines()
username = credentials[0].rstrip("\n\r")
password = credentials[1].rstrip("\n\r")
if submittedUsername == username:
if submittedPassword == password:
print("Login verified!")
#both username and password verified here, do what you want
else:
#password incorrect
print("Login invalid")
else:
#username incorrect but whether you want to specify what is wrong is up to you
print("Login invalid")
If there are any parts you would like explaining, do ask. Hope that helps.
This question already has answers here:
How to correct TypeError: Unicode-objects must be encoded before hashing?
(10 answers)
Closed 8 years ago.
im trying to hash a password from a file and then match it with the password given by the user. it's not ment to be super safe just safe enought so that the password isn't plain text in the file.
I get the error
TypeError: Unicode-objects must be encoded before hashing
it works if i type hashpass = hashlib.md5(b'p').hexdigest()
but then it only encrypts "p"
How do i get it to encrypt my string inputs?
PROGRAM
import hashlib
status = ""
def passhash():
code = open("password.txt", "r")
password = code.readline()
global encrypt
encrypt = hashlib.md5(password).hexdigest()
def checkPassword():
for key in range(3):
p = input("Enter the password >>")
hashpass = hashlib.md5(p).hexdigest()
if hashpass == encrypt:
print("password correct!")
status = "q"
return status
else:
print ('wrong password, try again')
print ('you have failed')
def Main():
status = input("p for program, q to quit: ")
if status == "p":
passhash()
checkPassword()
elif status == "q":
print("Byebye")
status = "q"
return status
while status != "q":
status = Main()}
Encode your Unicode string before hashing and/or open the file in binary mode. Pick an encoding and stick to it; UTF-8 supports all of Unicode:
p = input("Enter the password >>")
hashpass = hashlib.md5(p.encode('utf8')).hexdigest()
You either have to do the same in passhash() or open the file in binary mode and assume that the file uses the same encoding.
The expression b'p' encodes the string literal 'p' as bytes, not the value of the p variable. Try p.encode('utf-8').
By the way, what you're doing is pointless. Since you're storing plaintext and collecting plaintext input from the user, hashing the two before comparing them doesn't add any security.
The right way to approach this is to store the password hash (never storing the plaintext) and hashing the input for comparison. Better yet to hash the password with a random salt; store the salt and hashed password; and hash the input with the salt for comparison.