I'm working on a basic Python 3 authentication system with passwords and optional usernames. Here's the segment I have:
import hashlib
import os.path
from secure import BadCharacterError
def setLayers(filePath, passwords, usernames=None):
# sanity check
if os.path.exists(filePath): raise FileExistsError
if usernames is not None and len(usernames) != len(passwords): raise IndexError
for name in usernames:
if "|" in name: raise BadCharacterError("Username contained bad character '|'!")
# Hash the passwords
counter = 0
for password in passwords:
salt = ""
if usernames is not None: salt = hashlib.sha512(usernames[counter].encode()).hexdigest() # generate a salt
hashedPassword = hashlib.sha512(salt.encode() + password.encode()).hexdigest() # hash them together
passwords[counter] = hashedPassword # replace the list entry
counter += 1
# write them to a file
with open(filePath, "a+") as file:
counter = 0
for password in passwords:
if usernames is None:
file.write(password)
else:
file.write(password + "|" + usernames[counter] + "\n")
counter += 1
def checkLayer(filePath, password, username=None):
# sanity check
if not os.path.exists(filePath): raise FileNotFoundError
# find the password hash
salt = ""
if username is not None: salt = hashlib.sha512(username.encode()).hexdigest() # find the salt
hashedPassword = hashlib.sha512(salt.encode() + password.encode()).hexdigest() # hash them together
with open(filePath, "r") as file:
db = file.read().split("\n")
counter = 0
if username is not None:
for entry in db:
entry = entry.split("|")
dbPassword = entry[0]
dbUsername = entry[1]
if dbPassword == hashedPassword and dbUsername == username:
return counter
counter += 1
elif username is None:
for entry in db:
if hashedPassword == entry:
return counter
counter += 1
return False # we will only reach this point if all of the others were not matched
I have a test program that will run first setLayers() and then checkLayer with appropriate parameters that should cause a match in checkLayer(). However, it always returns False (instead of a number, which would happen if there was a match).
Debugging to find the comparisons being made shows this:
ae7d239aca090e393d5a70620130746ea3f8decc131318739df7097741f2b9ad9fe3679cc1f48a9bd1649f2c3e7c9c279adae116511e7397d0ec16ef59803ec9 User1
76a92b70d005bf3d7ae31e7506df098ca0bf00c0f701a54de84f23a11095ca9832b00cd9ae4ce02867600c8e5e2a144ecfce059c22e9ea2070bf80883c6616db User2
0838b3c1856b32c2b84c6ab1b1770935588d348123c8439d9546f0829a7cd52a8696f927fbf0ae5b1dbc4be0e15e1da3b3e240974db7b6954f30b87acadccc42 User2
76a92b70d005bf3d7ae31e7506df098ca0bf00c0f701a54de84f23a11095ca9832b00cd9ae4ce02867600c8e5e2a144ecfce059c22e9ea2070bf80883c6616db User2
703bce701812f2cd00476c455d9d56df21b1e8f7c3dab5cef2e50e407f6b06733f1d771a60162d4380320cc498e3dc6143dd94bec31377086c526d8fbd3ec9ac User3
76a92b70d005bf3d7ae31e7506df098ca0bf00c0f701a54de84f23a11095ca9832b00cd9ae4ce02867600c8e5e2a144ecfce059c22e9ea2070bf80883c6616db User2
Each group of two lines is separated by a line. The first line in the group is the stored password/username set, while the second is the one entered into checkLine(). The second group from the top should have matching hashes.
Why is this not the case, and how can I solve it?
Thanks.
Related
I'm trying to make a password generator in Python but I have some problems with it.
My code is down below:
import random
import time
f = open("password_list.txt", "a+")
start = time.time()
password = ""
chars= "123456789"
number = int(input("Number of passwords to generate? = "))
length = int(input("Password length? = "))
for p in range(number):
password = ""
for c in range(length):
password += random.choice(chars)
print(password)
f.write(password + "\n")
print('time: ' + str((time.time() - start)) + ' sec')
f.close()
Everything works fine but the only problem is sometimes it generates the same passwords in the text file. How can I avoid that?
One way to avoid the duplication issue is to put the passwords into a set in your loop, and keep looping until the length of the set is the number of passwords you want to generate. Then you can write the contents of the set to the file. This shows how to generate the set of passwords:
import random
chars= "123456789"
number = 5
length = 8
passwords = set()
while len(passwords) < number:
password = ""
for c in range(length):
password += random.choice(chars)
passwords.add(password)
print(passwords)
Sample output:
{'67824479', '67159221', '78423732', '77922952', '83499619'}
Program to login in, using a file called 'UserAccounts.txt'
def login():
print("logging in, ok")
counter = 0
while counter <= 5:
Username = input("Username:")
Password = input("Password:")
users = open("UserAccounts.txt","r")
entry = False
########### v checks file v #############
for record in users:
if record == Username:
Pass = record
if Pass == Password:
print("logged in")
entry = True
if entry == False:
print("Incorret, try again")
counter = counter + 1
print("LOCKED: Tried over 5 times")
Code always outputting no matter input:
logging in, ok
Username:El
Password:Password
Incorret, try again
Username:
Do you know why? (when user and password are in file)
Thank you for helping, have a good day!
(probably simple problem but brain isn't working)
When reading line by line, the line is seperated by comma, so you need to split by commas before declaring them as Username or Pass.
def login():
print("logging in, ok")
counter = 0
while counter <= 5:
Username = input("Username:")
Password = input("Password:")
users = open("UserAccounts.txt","r")
entry = False
########### v checks file v #############
for record in users:
if record.split(',')[0] == Username:
Pass = record.split(',')[1] #assuming 34 is pwd. [2] if 'Secure' is the pwd
if Pass == Password:
print("logged in")
entry = True #maybe replace this line with "return" to stop while loop
if entry == False:
print("Incorret, try again")
counter = counter + 1
I need to make a function for client registration where the client's username must be unique. I made a dict and a list where I put everything from my txt file, and now I've been trying to set for and while loops, but it isn't going well:
client_list = []
def c_l():
with open("svi.txt","r") as f:
pieces = ["username","password","name","lastname","role"]
for r in f.readlines():
dicct = {}
bla = r.strip().split("|")
count = 0
for i in bla:
dicct[pieces[count]] = i
count += 1
client_list.append(dicct)
c_l()
def reg():
for r in client_list:
while True:
username = input("Username: ")
if (username == r["username"] ):
print("Username is already taken, please try again: ")
else:
break
password = input("Your password:")
name = input("Your name: ")
lastname = input("Your lastname: ")
client = username + "|" + password + "|" + name + "|" + lastname + "|" + "buyer"
with open("svi.txt","a") as f:
f.write(client)
reg()
When I was typing this function for the first time, I made all in one function, where I opened the file, typed code for unique username and then printed client into that txt file. In that function my while loop worked, because all I had to do is to split the parts of the file and index the right one, then make this while loop, which worked fine. But now I've been told that I have to do it by using dict and list and I tried doing this, I don't know what the problem is with my approach.
You may want to load usernames into a set which ensures uniqueness. Then, in your reg function check whether the new username is in the set, like:
if username in myset:
raise InvalidUsernameError
else:
myset.add(username)
I am trying to make a program where the user can add usernames and passwords to a text file and then also delete usernames and passwords in the text file. At the moment I do not know how to delete a line of code and keep the same text file and the only way to delete it is to get the user to input the username they want to delete and then the password and username are deleted. My code so far:(In this code I have already made the username and password checking functions work.) Thanks for any help :)
import re
def UsernameChecking():
print("\nYour Username must have no blank spaces and must be less than 20 characters long")
ab = False
while not (ab):
global Username
Username = input("Please enter what you would like your username to be:\n")
if len(Username) > 20:
print("You username must be under 20 characters long")
elif re.search('[ ]',Username):
print("There is not allowed to be any blank spaces in your username")
else:
print("Your username has been accepted!")
ab = True
def PasswordChecking():
print("\nYour password must be at least 6 characters. \nIt also must be 12 or less characters")
ac = False
while not (ac):
global Password
Password = input("Please enter what you would like your password to be:\n")
if len(Password) < 6:
print("Your password must be 6 or more characters long")
elif len(Password) > 12:
print("Your password must be 12 or less characters long")
else:
print("Your password has been accepted!")
ac = True
def CreateFile():
f = open("UsernameDatabase.txt","w")
f.close()
def AddingData():
f = open("UsernameDatabase.txt", "a")
f.write("\n\nUsername:" + (Username))
f.write("\nPassword:" + (Password))
f.close()#closes the file
def DeletingData():
DeleteRequest = input("What Username and password would you like to delete. PLease enter the username:\n")
f = open("UsernameDatabase.txt", "r+")
def RunningProgram():
zz = False
while not (zz):
Q = input("Do you want to add a username and password to the file?\n")
if Q == "Y":
UsernameChecking()
PasswordChecking()
AddingData()
else:
zz = True
RunningProgram()
DeletingData()
To delete usernames and passwords from the file:
data = [i.strip("\n").split(":") for i in open("UsernameDatabase.txt")]
user_name_to_delete = "something"
password_to_delete = "something"
f = open('UsernameDatabase.txt', 'w')
for entry in data:
if entry[-1] != user_name_to_delete or entry[-1] != password_to_delete:
f.write(':'.join(entry)+'\n')
f.close()
I'm trying to build a working login function that will take me to my menu.
Here is the code I have:
def login(userlist):
verified = False
name = input('username: ')
password = input('password: ')
while not verified:
name = input('username: ')
password = input('password: ')
if [name, password] in userlist:
verified = True
print('You logged in the system!')
else:
print('invalid username\password.')
return verified
Even though I type in the correct username and password into the program, it keeps saying Invalid...
What am I missing? Also, userlist is a textfile with the usernames and passwords are separated by lines. I'm able to read the file because of my load function:
def load():
user_file = open('userdata.txt', 'r')
userlist = []
line = user_file.readline()
while line != '':
line = line.split()
userlist.append(line)
line = user_file.readline()
user_file.close()
return userlist
My text file ends up looking like this:
username #password #list
Sam #password #[1,2,...]
(the list of numbers doesn't actually spill over to the next line)
Here is my registration function, which I think is relevant.
def register(userlist):
# ASK FOR USERNAME
name = input('Choose your username: ')
while search(userlist, name):
print('The username is not available. Choose somethng else. ')
name = input('Choose your username: ')
# ASKING FOR PASSWORD
password = input('Choose your password: ')
p = input('Retype your password: ')
while p != password:
password = input('Choose your password: ')
p = input('Retype your password: ')
# SURVEY INDEX
a = list(range(26))
user = [name, p, a]
userlist.append(user)
print('Your registration is successful, your user namw ia: ', name)
user_file = open('userdata.txt', 'a')
user_file.write(str(name) + ' ' + str(p) + ' ' + str(a)+ '\n')
user_file.close()
return userlist
if userlist is file IO object:
for i in userlist.readlines():
if [name, password] in i.split() # assumes no whitespace in password is allowed
verified = True
print('You logged in the system!')
if userlist is a dict:
if (name,password) in userlist.items()
You have issues with your load function. When you checked if [name, password] were in the userlist you hadn't stored the username and password together, they were in separate lists in the userlist.
So I changed the load function to do what you wanted.
I changed the load function though assuming your text file looks like this (missing line breaks is fine as well).
EDIT: Okay so I made changes to my answer now I know what your text file looks like.
def login(userlist):
verified = False
print(userlist)
while not verified:
name = input('username: ')
password = input('password: ')
if [name, password] in userlist:
verified = True
print('You logged in the system!')
else:
print('invalid username\password.')
return verified
def load():
userlist = []
with open('test.txt', 'r') as user_file:
for line in user_file:
line = line.strip()
if not line:
continue
userlist.append(line.split()[:2]) # Gets only name and password
return userlist
if __name__ == '__main__':
user_list = load()
login(user_list)
If you would like to change to a dictionary, instead then you can do this
if [name, password] in userlist: becomes if userlist.get(name) == password:
userlist = [] becomes userlist = {}
userlist.append(line.split()[:2]) becomes
name, password = line.split()[:2]
userlist[name] = password
Side Note:
I would suggest changing your write line to something cleaner.
user_file.write("{0} {1} {2}\n".format(name, p, a))