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.
Related
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 have a school assignment which consists of me having to crack a unix password file, the passwords were created using SHA-512,
I'm using python3, to write my password cracking script, which goes through a password file, adds the salt and compares each password until the hash is found.
Here is my code:
#!/usr/bin/env python3
import crypt
passFile = open('passwords.txt', 'r')
salt_MD5 = []
hash_MD5 = []
salt_SHA512 = []
hash_SHA512 = []
for line in passFile:
if "$6$" in line:
temp1 = line.split(":")
temp1 = temp1[1]
salt_SHA512.append(temp1[:11])
hash_SHA512.append(temp1)
if "$1$" in line:
temp1 = line.split(":")
temp1 = temp1[1]
salt_MD5.append(temp1[:11])
hash_MD5.append(temp1)
print(salt_MD5, hash_MD5)
print(salt_SHA512, hash_SHA512)
crackStation = open('1000000passwords.txt', 'r')
print("Searching for the password...")
counter = 0
for index in crackStation:
counter += 1
hashed_value_1 = crypt.crypt(index, salt_MD5[0])
hashed_value_2 = crypt.crypt(index, salt_MD5[1])
hashed_value512_1 = crypt.crypt(index, salt_SHA512[0])
hashed_value512_2 = crypt.crypt(index, salt_SHA512[1])
if counter % 50000 == 0:
print("Counter is at: " + str(counter) + " Left to iterate = " + str(1000000-counter))
# if hashed_value_1 == hash_MD5[0]:
# password_1 = index
# print("User one has been cracked password is: " + password_1)
# if hashed_value_2 == hash_MD5[1]:
# password_2 = index
# print("User two has been cracked password is: " + password_2)
if hashed_value512_1 == hash_SHA512[0]:
password_3 = index
print("User one has been cracked using password: " + password_3)
if hashed_value512_2 == hash_SHA512[1]:
password_4 = index
print("User one has been cracked using password: " + password_4)
print("Search Complete.")
try:
print(password_1, password_2, password_3, password_4)
except Exception as e:
print("Oh shit something went wrong :s" + e)
Please disregard the MD5, salt and hash, as that I will deal with later (professor claimed that some of the passwords in the file would be crackable and a fellow student confirmed that he was able to crack both the SHA-512 passwords therefore I commented the MD5 out for the sake of speed)
I'm curious to see WHAT type of encoding I should be using to read from the password file, So far I've tried 'mac_roman', to iterate through the dictionary file, and now I just didn't set an encoding, I'm assuming the default should be UTF-8, but I honestly don't know how to check to confirm.
If anyone has any suggestions on what I can do to get this working I'd really appreciate it!
(I'm attempting the default encoding right now, by not initializing one
crackStation = open('1000000passwords.txt', 'r')
)
If in the case that, that does in fact work I will let you know!
Additonal question:
Could someone tell me what the encoding would be for this password file,
adamkaplan:$6$S4Y0gQuy$QRkLo5t/6KONMAiQY9DIAPojv0Q8CBvDtNqe02sfR7rnEdw.QgSm0LU/JRcIc/Arn/PpK3lxroc19bVQDwUGQ/:17786:0:99999:7:::
cardib:$6$t84.Fvbo$8lKHpxBDnjoHhnFS3.A4ezNZmKfy5MLbe7UGZoOnWgz55j0g5TBx5LOQAujDiqkUuE50EACOZsydlBZgy5jkw/:17786:0:99999:7:::
the password hash isn't BASE64, and the reason I'm asking is because when I use different encodings within a dictionary file each encoding gives a different hash, so that's what is throwing me off, the fact that if I use UTF-8, I will receive a different hash verses latin-1
So what encoding would linux password file be using by default.
If I create a new linux account through the terminal and set a password and go back inside my password file I will have a newly made hash for that new usernames password, and the encoding that was used within that hashing algorithm is what I Would need, or atleast that's what I image would need in order to crack the password.
Hope that isn't too confusing :s
I'm curious to see WHAT type of encoding I should be using to read from the password file
You should be using the encoding that the file is encoded in.
Unfortunately, it is impossible in general to tell the encoding of a file from just the file, you need some additional out-of-band information such as a header in the file telling you the encoding, the transmission format telling you the encoding … or just asking the author of the file.
However, since the passwords in the encrypted database are most likely treated as octet streams, it might make sense to treat the password dictionary the same way.
I honestly don't know how to check to confirm.
Use iconv. It'll fail when trying to convert a file containing malformed characters.
Here are some test files:
printf 'ascii only\n' > ascii_only.txt
printf 'utf-8 \342\230\272\n' > utf8.txt
printf 'latin1. pi\361ata.\n' > latin1.txt
Here are some examples:
$ iconv -f utf-8 -t utf-8 < utf8.txt > /dev/null && echo "ok"
ok
$ iconv -f ascii -t utf-8 < utf8.txt > /dev/null && echo "ok"
iconv: illegal input sequence at position 6
$ iconv -f utf-8 -t utf-8 < latin1.txt > /dev/null && echo "ok"
iconv: illegal input sequence at position 10
You can try ASCII, UTF-8 and Latin1 (in that order), and use whichever encoding iconv accepts first.
Even if this wasn't a school assignment, you could realistically expect most passwords to be ASCII.
The solution that worked out for me, the reason I wasn't able to crack the passwords were because I failed to strip the new lines from the dictionary words,
simply doing a
line = line.rstrip()
solved my problem, I didn't need to do any type of encoding or anything to have the file work.
I am making a program that checks to see if any of the user's input is in the file. If the user input is not currently in the file, then we will append that input into the used_passwords file and ask the user to type something else again. else if they retype the input we just recently added(or any of the presets) then we want to tell them that they can't reuse a password.
The problem I am having with this code is that whenever I type a letter that is from the word in the used_passwords file or if I type a part of the word in the file then the program tells me that I can't reuse a password.
For example: If I type in "abc", the program will tell me that I have already reused that password and I am assuming it is probably because the program reads the files character by character and reads the abc in abcdeF!23.
Although, I don't want the program to tell me I can't reuse a or multiple characters from the file. I want the program to tell me that I can't reuse a word from the program
I am also wondering if we could put the inputs or presets into an array IN THE FILE.
fileUsed_Pass = open("used_passwords.txt", 'a')
fileUsed_Pass.write("\nabcdeF!23")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.write("zxcbhK#44")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.write("poiuyT&11")
fileUsed_Pass.write("\n\n")
fileUsed_Pass.close()
def password():
string = input("Enter Here:")
if string in open('used_passwords.txt').read():
print("You can not reuse that password!\n")
password()
else:
# file-append.py
f = open('used_passwords.txt','a')
f.write('\n'+string)
f.close()
password()
password()
UPDATE: I have gotten the code to work using the with statement.
rather than using an If and else statement, I had used a with statement.
Here what I am doing is checking for every single line to see if it has any text that matches my input string. If there are none, then we'll make some_variable equal True. If it doesn't, then we'll make it equal false.
with open("used_passwords.txt", 'r') as tFile:
for line in tFile:
if string != line and string+"\n" != line:
some_variable = True
else: #If it equals anything else from the file, then false
some_variable = False
break
#print(some_variable)
#this was added for me/the user to make sure that the with statement was working
Afterwards, if it does equal True: we'll add it to the file. If it doesn't we'll make the user input another password that does not match any of the ones insie of the file.
tFile = open("used_passwords.txt", 'a')
if some_variable == True:
tFile.write("\n" + string)
print("\nGOOD! Password does not match old ones!")
elif some_variable == False:
print("\nYou can not re-use a password!")
password()
Working directly with text files is probably not the greatest solution;
you should consider using some form of database instead (such as the sqlite3 library which, IIRC, comes preinstalled with Python3).
Also, keep in mind that storing passwords as clear text is a security "no-no".
At the very least, use one of the many available cryptographic hash functions, then store and compare the hashes, not the passwords.
Here's a basic example that uses both sqlite3 and SHA-256, a common hashing function:
#!/usr/bin/python3
import sqlite3
import hashlib
db = sqlite3.connect( "used_passwords.db" )
cur = db.cursor()
cur.execute( "CREATE TABLE IF NOT EXISTS passwords( pwd TEXT, UNIQUE( pwd ))" )
def password():
pwd = input( "password: " )
sha = hashlib.sha256( pwd.encode( 'utf-8' )).hexdigest()
cur.execute( "INSERT INTO passwords VALUES( ? )", ( sha, ))
while True:
try:
password()
break
except KeyboardInterrupt:
print( "aborted" )
break
except sqlite3.IntegrityError:
print( "cannot reuse that password" )
db.commit()
db.close()
Note the UNIQUE constraint on pwd, which ensures that an sqlite3.IntegrityError exception is raised whenever a password is already present in passwords (this makes the verification implicit, and minimizes the SQL cumbersomeness).
Usage example:
% ./pwd.py
password: foo
% ./pwd.py
password: foo
cannot reuse that password
password: bar
%
You can verify that no clear-text password appears in the database:
% sqlite3 ./used_passwords.db
SQLite version 3.16.2 2017-01-06 16:32:41
Enter ".help" for usage hints.
sqlite> select * from passwords;
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae ; <- this is "foo"
fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 ; <- this is "bar"
sqlite>
Of course you can expand on that and add more features, such as support for multiple users, password expiration, etc...
Considering that you are adding a \n after each password you enter in the file, you can try to append \n to the string variable and then search after that.
You're using .read(), which reads the entire file as one string.
word = 'abc'
for line in open('file.txt').readlines():
if word in line:
return True
Use .readlines() instead and loop through every line to check if the string is in any of the file lines.
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!
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.