I have set up a program to change a "password". I have it checking to see if it is at least 8 characters, contains a capital letter and has a number, and if it does not meet this criteria, it asks for the password again. I have everything working except the checking for a number and I was wondering if someone could help.
npwv = 1
while npwv == 1:
npw = input("Please enter new password.")
npwc = input ("Please confirm new password")
if npwc == npw:
if npwc.isupper()== False:
if npwc.islower()== False:
if len(npwc) >= 8:
if str.isdigit(npwc) == True:
npw=npwc
print("Your password has been changed")
else:
print("Your password must contain a number")
npwv = 1
else:
print("Your password must contain at least 8 characters.")
npwv = 1
else:
print("Your password must contain at least 1 upper case character.")
npwv = 1
else:
print ("Passwords don't match")
npwv = 1
You are checking if the password itself is fully uppercase or composed of numbers. What you need to check if if the characters in the password match this criteria.
has_upper = any([c.isupper() for c in npwc])
has_digit = any([c.isdigit() for c in npwc])
You can also use regular expressions.
By the way, you should prefer getpass to get the password from the user.
Have you considered using .isalnum()?
>>> foo = "123asd"
>>> foo
'123asd'
>>> foo.isalnum()
True
>>>
Edit: Judging by the other answers, I am not sure what are you looking for, could explain it with examples?
I would suggest using sets, and the string package from stdlib for your list of acceptable characters.
I would also suggest refactoring a bit to remove a lot of the nesting with if / else branches.
import string
upper = set(list(string.uppercase))
lower = set(list(string.lowercase))
numbers = set(list(string.digits))
while True:
npw = input("Please enter new password: ")
npwc = input("Please confirm new password: ")
if npwc != npw:
print("Passwords don't match")
continue
if len(npcw) < 8:
print("Your password must contain at least 8 characters.")
continue
chars = set(list(npwc))
if not upper.intersection(chars):
print("Your password must contain at least 1 upper case character.")
continue
if not lower.intersection(chars):
print("Your password must contain at least 1 lower case character.")
continue
if not numbers.intersection(chars):
print("Your password must contain a number")
continue
npw = npwc
print("Your password has been changed")
break
This can be made more compact but yeah..
while True:
npw = input("Please enter new password.")
npwc = input ("Please confirm new password")
if npwc == npw:
if any(x.isupper() for x in npwc):
if any(x.islower() for x in npwc):
if len(npwc) >= 8:
if any (x.isdigit() for x in npwc):
npw=npwc
print("Your password has been changed")
#break # you probably want to exit the loop at this point
else:
print("Your password must contain a number")
else:
print("Your password must contain at least 8 characters.")
else:
print("Your password must contain at least 1 upper case character.")
else:
print("Your password must contain at least 1 lower case character.")
else:
print("Passwords don't match")
This looks like a job for regular expressions. Solution below:
import re
def password_validator(password):
if len(password) < 8:
return False, "Your password must contain at least 8 characters"
if not re.match('.*[0-9]', password):
return False, "Your password must contain a number"
if not re.match('.*[A-Z]', password):
return False, "Your password must contain at least 1 upper case character."
if not re.match('.*[a-z]', password):
return False, "Your password must contain at least 1 lower case character."
return True, "Your password has been changed"
while True:
npw = input("Please enter new password.")
npwc = input("Please confirm new password")
if npw != npwc:
print("Passwords don't match")
continue
is_valid, message = password_validator(npw)
print(message)
if is_valid:
break
You could also validate the whole thing in one go as:
pattern = """
(?=.*[a-z]) # use positive lookahead to see if at least one lower case letter exists
(?=.*[A-Z]) # use positive lookahead to see if at least one upper case letter exists
(?=.*\d) # use positive lookahead to see if at least one digit exists
[A-Za-z0-9##$%^&+=]{8,} # match any character in [] at least 8 times
"""
pwd_validator = re.compile(pattern, re.VERBOSE)
if pwd_validator.match(password):
# legit password
else:
# no match ask again
Hope this helps. The re.VERBOSE just makes this regular expression self-documenting so a lot easier to understand in future.
Related
I'm trying to create this python program that will prompt the user to enter a password. However, the password has to be between 6 and 12 characters. Also it must have a "#" in it but not in the first character or last. This is what I have so far, I'm not sure what I'm doing wrong I just keep getting the "Not a valid password" response. Any help would be greatly appreciated. Thank You
# This program will determine whether a password meets all security requirements
import re
print ("Hello, please enter a password between 6 and 12 characters.")
print ("The password may consist of a combination of numbers and letters, but the one of characters (after the first and before the last) must be a # sign.")
password = input("Please enter your password: ")
x = True
while x:
if (len(password)<6 or len(password)>12):
break
elif not re.search("[a-z]", password):
break
elif not re.search("[0-9]", password):
break
elif not re.search("[A-Z]", password):
break
elif not re.search("[#]", password):
break
else:
print("Valid Password")
x = false
break
if x:
print("Not a valid password")
# This program will determine whether a password meets all security requirements
import re
print ("Hello, please enter a password between 6 and 12 characters.")
print ("The password may consist of a combination of numbers and letters, but the one of characters (after the first and before the last) must be a # sign.")
is_valid = False
while not is_valid:
password = input("Please enter your password: ")
if (len(password)<6 or len(password)>12):
print('Password is the wrong length')
continue
if not re.search("[a-z]", password):
print('Password missing lowercase letter.')
continue
if not re.search("[0-9]", password):
print('Password missing a number.')
continue
if not re.search("[A-Z]", password):
print('Password missing uppercase letter.')
continue
if re.search("^#", password) or re.search("#$", password):
print('Password cannot begin or end with #.')
continue
print("Valid Password")
is_valid = True
I think this is roughly what you're trying to do, you can improve it to fit your use case. The way you have your loop currently it will only ever run once, the break statement exits the loop if it hits one of your conditions. The while statement never gets a chance to check the x variable you set to false.
I modified the loop so it will repeatedly prompt until the password fits the format you specified. You could also add a prompt to quit or try another password for a better user experience. I modified your # check so the regex checks if it is either at the beginning or the end of the password.
Also I changed all your conditions to if statements. The order the conditions are checked is important, and could potentially hid a false condition. Like the classic FizzBuzz problem.
I've been trying to figure this out my own, but I couldn't come up with solutions for this. I did come across to SpecialSym["$", "#", "#"] but I wasn't able to work that one into this code.
print("Password is incorrect, please try again...")
passW()
You can do this by adding the condition which would check whether any of the characters is in the list ["$", "#", "#"] or not.
The updated code would be:
import re #regular expression
print("Please enter a password to log in...")
def passW():
while True:
password=input("Enter a password:\n")
if password=="Y0urC0llege":
print("Logging in...")
print("Your login was successful.")
print("Welcome, Professor.")
break
elif len(password) < 10:
print("Please make sure your password is as least 10 characters long.")
elif re.search("[0-9]", password) is None:
print("Please contain as least 1 number in your password.")
elif re.search("[A-Z]", password) is None:
print("Please contain 1 capital letter in your password")
elif re.search("[$##]", password) is None:
print("Please contain as least 1 character symbol in your password.")
else:
print("Password is incorrect, please try again...")
passW()
Hope it helps.
You have to take special characters in a variable after that you can check the condition like below:
SpecialSym = ['!','#','#'] # You can add as many symbols you want.
elif not any(char in SpecialSym for char in password):
print("Please contain as least 1 character symbol in your password.")
The program, which assesses password strength, initially checks whether the length of the password is correct (6-12) and whether the password contains extented ASCII characters, i.e. 127-255.
The problem I have is that if the user first inputs a password which is too short or too long, the program then doesn't check for extended characters in the next password, inputted by the user and vice-versa, with checking for extended characters first.
I implemented a double while loop, if that's the correct way of calling it, however it still didn't bring the desired effect.
import re
import time
#score variable, responsible for later defining if passwords is weak, medium or strong
Score = 0
#list for improvements to password printed out with score at the end
Improvements = []
Password = ""
#defines function for checking for presence of extended characters (i.e. ascii 128-255)
def hasExtended(s):
return any(ord(i) > 127 for i in s)
#inputs password
Password = input("Please enter a password:")
Password_length = len(Password)
Extended_presence = hasExtended(Password)
#checks password length (6-12), asks user to re-input until password is within boundaries
#checks if password contains extended characters
#double while loops to allow for two conditions simultaneously
while Password_length < 6 or Password_length > 12:
if Password_length < 6:
Outputted_length = "too short"
Outputted_criteria = "no shorter than 6 characters"
else:
Outputted_length = "too long"
Outputted_criteria = "no longer than 12 characters"
print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
Password = input("Please enter a password:")
Password_length = len(Password)
while Extended_presence:
print("Your password contains characters from the extended ASCII list. Please don't use these.")
Password = input("Please enter a password:")
Extended_presence = hasExtended(Password)
while Extended_presence:
print("Your password contains characters from the extended ASCII list. Please don't use these.")
Password = input("Please enter a password:")
Extended_presence = hasExtended(Password)
while Password_length < 6 or Password_length > 12:
if Password_length < 6:
Outputted_length = "too short"
Outputted_criteria = "no shorter than 6 characters"
else:
Outputted_length = "too long"
Outputted_criteria = "no longer than 12 characters"
print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
Password = input("Please enter a password:")
Password_length = len(Password)
else:
#defines function for checking for presence of numbers
def hasNumbers(s):
return any(i.isdigit() for i in s)
#defines function for checking for presence of letters
def hasLetters(s):
return any(i.isalpha() for i in s)
#defines function for checking for presence of special characters
def hasSpecial(s):
return any(ord(i) < 48 for i in s)
#checks if password contains letters
Letter_presence = hasLetters(Password)
if not Letter_presence:
Score = Score - 1
Improvements.append("letters")
else:
Score = Score + 1
#checks if password is all upper case
Is_upper = Password.isupper()
if not Is_upper:
Score = Score + 1
else:
Score = Score - 1
Improvements.append("upper and lower case letters")
#checks if passwords is all lower case
Is_lower = Password.islower()
if not Is_lower:
Score = Score + 1
else:
Score = Score - 1
Improvements.append("upper and lower case letters")
#checks if password contains a number
Number_presence = hasNumbers(Password)
if not Number_presence:
Score = Score + 0
Improvements.append("numbers")
else:
Score = Score + 1
#checks if password is just numbers
Only_numbers = Password.isdigit()
if not Only_numbers:
Score = Score + 0
else:
Score = Score - 1
Improvements.append("other characters")
#checks if password contains special characters
Special_presence = hasSpecial(Password)
if not Special_presence:
Score = Score + 0
Improvements.append("special characters, such as '$'")
else:
Score = Score + 1
#outputs weak, medium or strong password to user and suggest improvements
if Score <= 2:
print("The program is processing your password...")
time.sleep(2)
print("Your password isn't acceptable! Please try again.")
print("Next time, remember to include", Improvements)
if Score == 3:
print("The program is processing your password...")
time.sleep(2)
print("Your password is weak, you should try again.")
print("Next time, remember to include", Improvements)
elif Score == 4:
print("The program is processing your password...")
time.sleep(2)
print("Your password is medium, it should be OK.")
print("Next time, remember to include", Improvements)
elif Score == 5:
print("The program is processing your password...")
time.sleep(2)
print("Your password is strong, it is absolutely fine.")
I would suggest you to write validator, a function that looks like this:
def validate_password(password):
... # check score, symbols and other, print whatever you want
return score
And then call it in a way like that one:
pass = input('Enter your password')
score = validate_password(pass)
while score <= 3:
pass = input('Enter another password')
score = validate_password(pass)
You can implement such scenario like below:
check_pass function will check for length of function
def hasExtended(s):
return any(ord(i) > 127 for i in s)
check_pass = lambda x: x>=6 and x<=12 # check for range of input value
password=input("Password: ")
if check_pass(len(password)) and not hasExtended(password):
print("Valid password")
else:
print("Do not use extended ascii characters, use password with minimum length of 6 and maximum length of 12")
to be more precise about error you can use nesting in below way:
if check_pass(len(password)) and not hasExtended(password):
print("Valid password")
elif check_pass(len(password)) and hasExtended(password):
print("do not use extended ascii character")
elif not check_pass(len(password)) and hasExtended(password):
print("password length should be between 6 to 12")
similarly if you want to check for invalid length of minimum lenght and maximum length separately.
If you wish to check all condition separately and then show success or failure you can do like below:
def verify_password(password):
if len(password) < 6:
print("require minimum 6 characters")
if len(password) > 12:
print("can not use more then 12 characters")
if hasExtended(password):
print("use only valid ascii characters")
else:
print("valid password")
return True
while not verify_password(password): # loop will never stops unless valid password or used break statement within
password = input("Password: ")
The function will check for three different condition if condition satisfied message will be printed else it will continue executing, at the end if it is valid password instead of printing anything it will print valid password and return True instead of None.
Try this code , and instead of while just use if in first checking codition of Extended_presence , You don't need while there because its already in the scope of previous while loop :
import re
print([chr(i) for i in range(127,200)])
import re
import time
#score variable, responsible for later defining if passwords is weak, medium or strong
Score = 0
#list for improvements to password printed out with score at the end
Improvements = []
Password = ""
#defines function for checking for presence of extended characters (i.e. ascii 128-255)
def hasExtended(s):
return any(ord(i) > 127 for i in s)
#inputs password
Password = input("Please enter a password:")
Password_length = len(Password)
Extended_presence = hasExtended(Password)
#checks password length (6-12), asks user to re-input until password is within boundaries
#checks if password contains extended characters
#double while loops to allow for two conditions simultaneously
while Password_length < 6 or Password_length > 12:
if Password_length < 6:
Outputted_length = "too short"
Outputted_criteria = "no shorter than 6 characters"
else:
Outputted_length = "too long"
Outputted_criteria = "no longer than 12 characters"
print("Your password is", Outputted_length, ". It has to be", Outputted_criteria, ".")
Password = input("Please enter a password:")
Password_length = len(Password)
if Extended_presence:
print("Your password contains characters from the extended ASCII list. Please don't use these.")
Password = input("Please enter a password:")
Extended_presence = hasExtended(Password)
while Extended_presence:
print("Your password contains characters from the extended ASCII list. Please don't use these.")
Password = input("Please enter a password:")
Extended_presence = hasExtended(Password)
output:
Please enter a password:hel¢
Your password is too short . It has to be no shorter than 6 characters .
Please enter a password:hello¢
Your password contains characters from the extended ASCII list. Please don't use these.
Please enter a password:hello¢
Your password contains characters from the extended ASCII list. Please don't use these.
Please enter a password:hellllo#
Why don't you delegate your password check to a function and separate the user input from checking the password? That way you can ask the user as many times as you want without complex jumps. Something like:
def validate_password(password):
if len(password) < 6:
return 0, "Your password is too short, it has to be no shorter than 6 characters."
elif len(password) > 12: # why, tho?
return 0, "Your password is too long, it has to be no longer than 12 characters."
# these can be optimized but I'll leave that as an exercise for you
if any(ord(i) > 127 for i in password): # again, why?!
return 0, ("Your password contains characters from the extended ASCII list. "
"Please don't use these.")
score = 0
improvements = []
if any(i.isalpha() for i in password):
score += 1
if password.isupper() or password.islower():
score -= 1
improvements.append("upper and lower case letters")
else:
score += 1
else:
score -= 1
improvements.append("letters")
if any(i.isdigit() for i in password):
score += 1
if password.isdigit():
score -= 1
improvements.append("other characters")
else:
# score -= 1 # are you sure you don't want to reduce the score?
improvements.append("numbers")
if any(ord(i) < 48 for i in password):
score += 1
else:
# score -= 1 # are you sure you don't want to reduce the score?
improvements.append("special characters such as '$'")
return score, "Next time remember to include: {}".format(", ".join(improvements))
And now you can call it from wherever you want, as many times as you need:
while True:
candidate = input("Please enter a password: ")
print("The program is processing your password...") # why? this happens in an instant
score, message = validate_password(candidate)
time.sleep(2) # why are we making people wait for no reason?
if score <= 1:
print(message)
print("Please try again.")
elif score == 2:
print("Your password is weak, you should try again.")
print(message)
elif score == 3:
print("Your password is medium, it should be OK.")
print(message)
break
elif score == 4:
print("Your password is strong, it is absolutely fine.")
break
print("Accepted password: " + candidate)
And you can get an output as:
Please enter a password: dfld
The program is processing your password...
Your password is too short, it has to be no shorter than 6 characters.
Please try again.
Please enter a password: dfldsadlslads
The program is processing your password...
Your password is too long, it has to be no longer than 12 characters.
Please try again.
Please enter a password: dflds°
The program is processing your password...
Your password contains characters from the extended ASCII list. Please don't use these.
Please try again.
Please enter a password: ddlllsd
The program is processing your password...
Next time remember to include: upper and lower case letters, numbers, special characters
such as '$'
Please try again.
Please enter a password: ddlllsd12
The program is processing your password...
Next time remember to include: upper and lower case letters, special characters such as '$'
Please try again.
Please enter a password: Ddlllsd12
The program is processing your password...
Your password is medium, it should be OK.
Next time remember to include: special characters such as '$'
Accepted password: Ddlllsd12
I am working on an assignment for password validation where the program keeps asking the user for a valid password until one is given. I am having trouble checking the input string for special characters. Currently the program accepts the password even if their is no special characters. Also I would like to implement a feature that terminates the loop after 3 unsuccessful attempts but am not sure which loop to implement the count in.
Here is my code:
import re
specialCharacters = ['$', '#', '#', '!', '*']
def passwordValidation():
while True:
password = input("Please enter a password: ")
if len(password) < 6:
print("Your password must be at least 6 characters.")
elif re.search('[0-9]',password) is None:
print("Your password must have at least 1 number")
elif re.search('[A-Z]',password) is None:
print("Your password must have at least 1 uppercase letter.")
elif re.search('specialCharacters',password) is None:
print("Your password must have at least 1 special character ($, #, #, !, *)")
else:
print("Congratulations! Your password is valid.")
break
passwordValidation()
There is no need to use regular expression for something so simple. How about:
elif not any(c in specialCharacters for c in password):
or
specialCharacters = set('$##!*')
...
elif not specialCharacters.intersection(password):
These are my two def functions:
def valid_username(username):
# implement the function here
while True:
try:
username = input("Username: ")
if len(username) < 8:
print ("Sorry, the username must be at least 8 characters long.")
if username.isalnum() == False:
print ("Sorry, your name can only contain alpha numeric characters")
numupper = 0
for c in username:
if c.isupper() == True:
numupper += 1
if numupper > 0:
print ("You have at least 1 uppercase in this username.")
else:
print ("You have no uppercase in this username.")
numlower = 0
for d in username:
if d.islower() == True:
numlower +=1
if numlower > 0:
print ("You have at least 1 lowercase in this username.")
else:
print ("You have no lowercase in this username.")
numdigit = 0
for e in username:
if e.isdigit() == True:
numdigit += 1
if numdigit > 0:
print ("You have at least one digit in this username.")
else:
print("You have no digits in this username.")
continue
except:
print ("Sorry, not valid. Try again.")
else:
print ("Thank you for your input")
break
def valid_password(password, username):
# implement the function here
while True:
try:
password = input("Password: ")
if username in password:
print ("That's not secure at all.")
if len(password) < 8:
print ("Sorry, the password must be at least 8 characters long.")
if password.isalnum() == False:
print ("Sorry, your password can only contain alpha numeric characters")
numupper = 0
for c in password:
if c.isupper() == True:
numupper += 1
if numupper > 0:
print ("You have at least 1 uppercase in this password.")
else:
print ("You have no uppercase in this password.")
numlower = 0
for d in password:
if d.islower() == True:
numlower +=1
if numlower > 0:
print ("You have at least 1 lowercase in this password.")
else:
print ("You have no lowercase in this password.")
numdigit = 0
for e in password:
if e.isdigit() == True:
numdigit += 1
if numdigit > 0:
print ("You have at least one digit in this password.")
else:
print("You have no digits in this password.")
continue
except:
print ("Sorry, not valid. Try again.")
else:
print ("Thank you for your input")
break
my main program is this:
username = input("Username: ")
result, reason = uservalidation.valid_username(username)
if not(result):
print (reason)
else:
password = input("Password: ")
pwresult, pwreason = uservalidation.valid_password(password, username)
if not(pwresult):
print (pwreason)
else:
print ("Username and Password combination is valid!")
when I run it I get the following:
Username: d
Username: user
Sorry, the username must be at least 8 characters long.
You have no uppercase in this username.
You have at least 1 lowercase in this username.
You have no digits in this username.
Username: craig2345
You have no uppercase in this username.
You have at least 1 lowercase in this username.
You have at least one digit in this username.
Thank you for your input
Traceback (most recent call last):
File "C:/Users/Si Hong/Desktop/pythontest/HuangSiHong_Assign8_part3.py", line 7, in <module>
result, reason = uservalidation.valid_username(username)
TypeError: 'NoneType' object is not iterable
>>>
I'm having trouble figuring out why when I type enter in the first value for username, it doesn't trigger the function, but does it after the 2nd time I enter it in, and also I am not sure how to solve the nonetype error issue, if someone can explain this to me, that would be great thank you so much!
If a function doesn't have a value explicitly returned then it implicitly returns None, which cannot be applied to tuple unpacking this way.
The reason that you're seeing the Username: prompt twice is that you ask for input once in the main program and then again, immediately, inside the function. The function should not ask the user for any input, it gets the value of username from the argument passed to it.
The reason you're seeing the error about NoneType (not nonetype as you wrote, Python is case-sensitive and you should really get in the habit of typing exactly what it says) is that your function valid_password() does finish with a return statement returning two values as expected by your program. In fact, it doesn't have a return statement at all, which means it effectively returns the special Python value None (which is an object of type NoneType).
Because you tell your program to extract two values from whatever the function returns, it's trying to do so by iterating over the values returned. NoneType is not one of the types that can be iterated over (since it contains no information), thus the error message.