Word guesser doesn't print enough characters - python

The idea is that you enter any passwords/characters and then it tries to find that word that you have entered by trying out different combinations of letters and numbers (it really is pointless huh)
The problem right now is that "pw_guess" only prints out one letter or number at a time. There also appears to be duplicates. For example i found that letter "e" was printed 6 times, though should only print it once.
import random
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
pw = input("Enter a password: \n")
pw_lenght = len(pw)
while True:
for i in range(pw_lenght):
random_character = random.randrange(len(characters))
pw_guess = characters[random_character]
if pw_guess == pw:
print('Password found!\nPassword: ', pw)
exit()
print(pw_guess)
It is suppose to print and try out as many letter/numbers at a time as how many have been entered in to the user input.
For example:
You type "password123" to the input. Then it will count how many
characters there are in that user input (11 in this example), and
starts trying out and printing different combinations of characters.
One print should now include 11 random characters. Then at some point
it will get right combination and stop.
As said above, now it only prints one character at a time and there are also duplicate characters which i don't want.
I've tried putting just one letter to the user input, and it guessed it right, so otherwise it works fine.

import random
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
pw = input("Enter a password: \n")
pw_lenght = len(pw)
while True:
for i in range(pw_lenght):
random_character = random.randrange(len(characters))
pw_guess = ''.join([characters[random.randrange(len(characters))] for x in range(len(pw))])
if pw_guess == pw:
print('Password found!\nPassword: ', pw)
exit()
print(pw_guess)

Your inner loop should assemble all the random characters into a single password guess, instead of guessing each letter separately.
import random
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
pw = input("Enter a password: \n")
while True:
pw_guess = ''
for i in range(len(pw)):
pw_guess += random.choice(characters)
if pw_guess == pw:
print('Password found!\nPassword: ', pw)
break
print('Password not found. Incorrect guess: ', pw_guess)

Since Python 3.6 you can use random.choises to get more characters at once.
I would recommend the string-module for better readability.
It's very annoying to fill the terminal with thousands of incorrect guesses, so I've changed the code a little.
import string
import random
characters = string.digits + string.ascii_letters
password = input('Enter a password:\n')
guesses = 1
while True:
pw_guess = ''.join(random.choices(characters, k=len(password)))
if password == pw_guess:
break
guesses += 1
print('Password found!')
print(f'Password: {pw_guess}')
print(f'{guesses} guesses needed')

Related

Rejecting Strings with a space between two words

So I've almost finished a program in which the user inputs a name/word and it spits out the Soundex counterpart.
The code runs well and the Soundex methodology is sound, "Get it Sound". What I had issues with were the strings being returned. Things like space before or after the word typed in or having an uppercase and lowercase name being repeated when they shouldn't have been. Those got fixed rather easily.
What I'm having issues with now is when the user inputs something like, "Carl Sagan" it returns the ("Word should only contain characters") elif of my program.
What I'd like to do is respond to the user and say, ("Two words entered at once, Please enter one at a time."). When those instances happen.
Here's a snippet of my code:
#input name
name = input("To start, Please give your name :")
print("\nGreetings,", name.strip().capitalize(), "Your Soundex-name is:", convert_to_soundex(name), "\n" )
#creating dictionary
dicti={}
#convert name to code and store in dictionary
dicti[name]=convert_to_soundex(name)
# keeping asking user for a word or name until user enters 0
while(True):
word=input("Please give a word to convert (0 to exit) :").strip().capitalize()
if word=='0':
break
elif word=="":
print("Please give word with atleast one character.")
elif not word.isalpha():
print("Word should only contain characters.")
else:
if word in dicti:
print("Word already exists")
else:
dicti[word]=convert_to_soundex(word)
#printing formatted data
printData(dicti)
You can add another while..if instead of name input like this:
while True:
name = input("To start, Please give your name :")
if ' ' in name:
print("Two words entered at once, Please enter one at a time.")
else:
break
#input name
name = input("To start, Please give your name :")
print("\nGreetings,", name.strip().capitalize(), "Your Soundex-name is:", convert_to_soundex(name), "\n" )
#creating dictionary
dicti={}
#convert name to code and store in dictionary
dicti[name]=convert_to_soundex(name)
# keeping asking user for a word or name until user enters 0
while(True):
word=input("Please give a word to convert (0 to exit) :").strip().capitalize()
if word=='0':
break
elif ' ' in word:
print("Two words entered at once, Please enter one at a time.")
elif word=="":
print("Please give word with atleast one character.")
elif not word.isalpha():
print("Word should only contain characters.")
else:
if word in dicti:
print("Word already exists")
else:
dicti[word]=convert_to_soundex(word)
#printing formatted data
printData(dicti)
name = input("give name please...")
for nam in name:
if nam == " ":
print('invalid input')
# removes space from input
print(''.join([i for i in name if i != " "]))

Password Verfification for numbers and special characters

I am trying to create a user login system program. I am trying to make sure the password must have at least 10 characters which I have done, but I'm having trouble making sure it has at least two numbers and only underscore as a special character. I have seen some solutions about numbers and I don't get them and they rarely have at least 2 digits.
Here is my code:
print("Welcome ")
print('')
print('New users should enter Sign to create an account')
print('')
print('')
username = input('Enter your Username: ')
if username == 'Sign':
while True:
usernames = ['Dave','Alice','Chloe']#A list that stores usernames
create_user = input('Enter your new username: ')
if create_user in usernames:
print('This user name has been taken .Try again')
continue
else:
break
usernames.append([create_user])
while True:
create_pass = input('Enter your your user password: ')
passwords = []#A list thst stores password
pass_len = len(create_pass)
if pass_len < 10:
print('Your password must be at least 10. Try again')
continue
else:
print('')
print('You are now a verified user.')
print('Run the application again to re-login.')
print('Thank You')
break
else:
password = input('Enter your password')
print('Visit www.bitly/p8?. to continue')
If you're not wanting to use regex, you could add some simple logic like this:
num_count = 0
for character in create_pass:
if character.isdigit():
num_count += 1
if num_count < 2:
print('You must have at least 2 numbers in your password')
This is how I'd do it. You can check for the underscore with in and use regex to search for the numbers.
import re
test = 'hisod2f_1'
underscore = '_' in test
twonums = len(re.findall(r'\d', test)) >= 2
if underscore and twonums:
# your logic

How to replace a double while loop?

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

Identifying special characters in password verification in python

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):

How to check the "password" for numbers in python

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.

Categories