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.
Related
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.
So basically i bought a book that teaches the basics of python and how to create a random number generator so I decided to go one step further and make a random password generator I found a tutorial online that gave me a good example of why and what is used to make a password generator but i want the output to be saved to a .txt file I do not know what i need to implement to get the result i want this is what i have i'm using python3.
import random
chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!, #,#$%^&*.'
number = input('Number of passwords - ')
number = int(number)
length = input('password length? - ')
length = int(length)
answer = input
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
password = open("passlist.txt", "a")
password.write(password)
password.close()
file = open('passlist', 'w')
file.write(password)
file.close()
this is what i get in shell
Traceback (most recent call last):
File "C:\User\Desktop\passgen.py", line 21, in <module>
password.write(password)
TypeError: write() argument must be str, not _io.TextIOWrapper
When you open a new file and set it equal to a variable, you are actually creating an _io.TextIOWrapper object. So in this line of code, you are creating this object and storing it in password, getting rid of the password generated in the previous lines of code.
password = open("passlist.txt", "a")
You are then trying to write to the passlist.txt file with this line:
password.write(password)
You are telling password, now an _io.TextIOWrapper object, to write to the passfile.txt the _io.TextIOWrapper object, not the password generated beforehand. This function is expecting a string, and you are now passing an _io.TextIOWrapper object. Since password is no longer a string, that is why you are running into the error.
To fix this, I would suggest creating a new variable:
txtFileWriter = open("passlist.txt", "a")
txtFileWriter.write(password)
txtFileWriter.close()
You may find that after fixing this, only one value is being stored inside your text file. I would recommend properly nesting your for loops:
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
The meaning of these for loops can be translated as:
For each password, set the password = ' ' and for each character, add one random character to password.
The problem with this is that you will only have one password after the for loops are complete. You are setting the password value to ' ' each time you run through the outer loop. The only password that will be saved, will be the last value. In order to fix this, I recommend using a list.
I recommend reading through this documentation
I don't want to spoon feed the answers since I realize you are learning python, so I will leave it here. You will want to create a list and then append a value to that list each time you generate a password. After some reading, hopefully this will make sense.
filename = 'passlist.txt'
with open (filename, 'a') as file_object:
file_object.write(password)
Using with will close the file once access is no longer needed.
You also need a list to append your passwords ;)
The error originates from password being re-assigned in password = open("passlist.txt", "a"). This causes and error in the next line as you are attempting to pass password as parameter to itself in password.write(password).
Some farther assistance
You have the right idea but you forgot to indent. All the lines below for P in range(number): should be indented because the program must generate and write a new password until it has satisfied the required amount of passwords.
The password = open("passlist.txt", "a")
password.write(password)
password.close() lines are unnecessary as you are overriding the generated password and assigning that password variable to something that is not a string; that is why you are getting that error.
Here is the code with the adjustments.
import random
chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!, #,#$%^&*.'
number = input('Number of passwords - ')
number = int(number)
length = input('password length? - ')
length = int(length)
answer = input
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
password += "\n" # writes the password in a new line
file = open('passlist.tx', "a")
file.write(password)
file.close()
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?
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
This question already has answers here:
I need to securely store a username and password in Python, what are my options? [closed]
(8 answers)
Closed 5 years ago.
I am trying to create a program that asks the user for, in this example, lets say a username and password, then store this (I assume in a text file). The area I am struggling with is how to allow the user to update this their password stored in the text file? I am writing this in Python.
import getpass
import os
import bcrypt
new=None
def two_hash():
master_key = getpass.getpass('enter pass word ')
salt = bcrypt.gensalt()
combo = salt + master_key
hashed = bcrypt.hashpw(combo , salt)
allow = raw_input('do you want to update pass ')
if allow == 'y':
new = getpass.getpass('enter old pass word ')
combo = salt + new
bcrypt.hashpw(combo , salt)
if ( bcrypt.hashpw(combo , salt) == hashed ):
new = getpass.getpass('enter new pass ')
print new
else :
pass
if __name__ == '__main__':
two_hash()
Note 1 : i wanted to split my code to some function but i can't so help for split it to some function
Because you've asked to focus on how to handle the updates in a text file, I've focused on that part of your question. So, in effect I've focused on answering how would you go about having something that changes in a text file when those changes impact the length and structure of the text file. That question is independent of the thing in the text file being a password.
There are significant concerns related to whether you should store a password, or whether you should store some quantity that can be used to verify a password. All that depends on what you're trying to do, what your security model is, and on what else your program needs to interact with. You've ruled all that out of scope for your question by asking us to focus on the text file update part of the problem.
You might adopt the following pattern to accomplish this task:
At the beginning see if the text file is present. Read it and if so assume you are doing an update rather than a new user
Ask for the username and password. If it is an update prompt with the old values and allow them to be changed
Write out the text file.
Most strategies for updating things stored in text files involve rewriting the text file entirely on every update.
Is this a single user application that you have? If you can provide more information one where you're struggling
You can read the password file (which has usernames and passwords)
- When user authenticate, match the username and password to the combination in text file
- When user wants to change password, then user provides old and new password. The username and old password combination is compared to the one in text file and if matches, stores the new
Try using JSON.
An example of a json file would be this:
{
"Usernames": {
"Username": [
{
"Password": "Password123"
}
]
}
}
Then to edit the json:
jsonloads = json.loads(open('json.json').read()) #Load the json
username = input("Enter your username: ") #Get username as a string
for i in jsonloads["Usernames"]: #Iterate through usernames
if i == username: #If the username is what they entered
passw = input("New password: ") #Ask for new password
jsonloads["Usernames"][i][0]["Password"] = passw #Set the password
jsonFile = open("json.json", "w+") #Open the json
jsonFile.write(json.dumps(jsonloads, indent=4)) #Write
jsonFile.close() #Close it
break #Break out of the for loop
else: #If it remains unbroken
print("You aren't in the database. ")
user = input("Username: ") #Ask for username
passw = input("Password: ") #Ask for password for username
item = {"Password":pass} #Make a dict
jsonloads["Usernames"].update({user: item}) #Add that dict to "Usernames"
with open('json.json','w') as f: #Open the json
f.write(json.dumps(jsonloads, indent=4)) #Write
Something like that should work, haven't tested it though.
Also, remember to always encrypt passwords!