This is my code which and it asks a user to enter a password string and checks for any repeated elements.The thing is I didn't understand the code and why they set a unique_element to an empty string.And what does unique+=password[i] do,why is i in [] in this brackets?
def check_pass():
password= raw_input('Enter a password:')
unique_element = ''
for i in range (len(password)):
if len(unique_element) == 0:
unique_element += password [i]
else:
not_unique = True
for j in range (len(unique_element)):
if unique_element[j] == password[i]:
not_unique = False
if not_unique:
unique_element += password[i]
return unique_element == password
print check_pass()
Explaining the Code above may be a little tedious. Suffice it to say that if your intention is to check if a given String [password] contains any duplicate character, you might do that without the need for any loops - which (in this case) is likely unnecessary. Here's how:
def pass_has_unique_characters():
# CAPTURE THE ENTERED CHARACTERS
password = input('Enter a password:')
# SETS CANNOT HAVE DUPLICATES SO WE CAST THE STRING (password) TO A SET
st_password = set(password)
# NOW WE CHECK THE LENGTHS OF BOTH: password AND st_password
# IF BOTH HAVE THE SAME LENGTH, THEN THE PASS HAS UNIQUE CHARACTERS,
# RETURN [True] ... OTHERWISE RETURN [False]
return (True if len(st_password) == len(password) else False)
print(pass_has_unique_characters())
Related
So I'm creating a password manager, and my code is somewhat close to this,
I was wondering if there's a way to check for a character inside a string while it's still being written (i.e. before the user clicks Enter), so that I can change the color of the line that says "An uppercase character" to green when the user inputs an uppercase character, and goes back to original character if the user deletes the character.
from termcolor import colored
from getpass import getpass
import string
def check_for_owasp_standards(password):
uppercase_letters = string.ascii_uppercase
lowercase_letters = string.ascii_lowercase
digits = string.digits
special_characters = "!##$%^&*()-_"
length_is_over_8 = False
contains_uppercase_letter = False
contains_lowercase_letter = False
contains_digit = False
contains_special_character = False
Checklist = []
if len(password) >= 8 :
length_is_over_8 = True
Checklist.append(length_is_over_8)
for character in password:
if character in uppercase_letters:
contains_uppercase_letter = True
break
Checklist.append(contains_uppercase_letter)
for character in password:
if character in lowercase_letters:
contains_lowercase_letter = True
break
Checklist.append(contains_lowercase_letter)
for character in password:
if character in digits:
contains_digit = True
break
Checklist.append(contains_digit)
for character in password:
if character in special_characters:
contains_special_character = True
break
Checklist.append(contains_special_character)
if False in Checklist:
return False
else:
return True
print(colored("According to OWASP password standards 2021 your master password must contain the following :", "magenta"))
print(colored("*An uppercase character", "magenta"))
print(colored("*A lowercase character", "magenta"))
print(colored("*A digit", "magenta"))
print(colored("*Length has to be 8 or more characters\n", "magenta"))
master_password = getpass(colored("Enter your master password : ", "blue"))
if not check_for_owasp_standards(master_password):
print(colored("Password does not meet the standards, let's try again.\n", "yellow"))
else:
print(colored("Master password saved successfully!", "green"))
I created a solution to your problem.
This is a video showing how it works on my console >> YouTube.
You can get the whole code, organised here >> Github.
And here is explanation:
You will need to turn off console output, then capture each keypress, and at the end turn console output back on.
For this you will need from pynput.keyboard import Key, Listener, which works basically like this:
def on_release(key):
print(key)
if key in [Key.enter, Key.esc]:
return False
with Listener(on_release=on_release) as listener:
listener.join()
which will basically print every pressed key, and stop working when pressing Enter or Esc.
Tp stop it from being visible you will disable it by os.system("stty -echo") and enable back with os.system("stty echo")
Here is how I changed your code:
This method is similar to your check_for_owasp_standards(password) but will return a list of booleans for each standard that need to be checked:
def checkStandards(password):
uppercase_letters = string.ascii_uppercase
lowercase_letters = string.ascii_lowercase
digits = string.digits
special_characters = "!##$%^&*()-_"
length_is_over_8 = False
contains_uppercase_letter = False
contains_lowercase_letter = False
contains_digit = False
contains_special_character = False
checklist = []
if len(password) >= 8 :
length_is_over_8 = True
checklist.append(length_is_over_8)
for character in password:
if character in uppercase_letters:
contains_uppercase_letter = True
break
checklist.append(contains_uppercase_letter)
for character in password:
if character in lowercase_letters:
contains_lowercase_letter = True
break
checklist.append(contains_lowercase_letter)
for character in password:
if character in digits:
contains_digit = True
break
checklist.append(contains_digit)
for character in password:
if character in special_characters:
contains_special_character = True
break
checklist.append(contains_special_character)
return checklist
Next function will show this information as coloured. Green for accepted, red for not. The easiest way to show changes, overring previous lines written to console is to clear all console.
def updateStandards(password):
# clear console
os.system('clear')
# check
standards = checkStandards(password)
print(accept("Length >= 8", standards[0]))
print(accept("Contains uppercase letter", standards[1]))
print(accept("Contains lowercase letter", standards[2]))
print(accept("Contains digit", standards[3]))
print(accept("Contains special character", standards[4]))
using
def accept(text, accepted=False):
if accepted:
return f'\033[32;1m{text}\033[0m' # green
else:
return f'\033[31;1m{text}\033[0m' # red
The main function will look like this. It will first reset global variable storing user input to empty string. Then show all rules for password. Then ask user for password and turn off showing in console. At the end, it will turn it back.
def getPassword():
try:
# reset stored input to empty string
global user_input
user_input = ''
# show rules for password
updateStandards('')
# ask for password
print('Write your password:')
# turn off showing input
os.system("stty -echo")
# collect keys until ENTER/ESC
with Listener(on_release=on_release) as listener:
listener.join()
input()
except:
print(traceback.print_exc())
finally:
# turn on showing input
os.system("stty echo")
The last part is to write listener for key press:
def on_release(key):
global user_input
# store key
k = str(key).replace('\'', '')
if len(k) == 1:
user_input += k
# delete last char
if key == Key.backspace:
user_input = user_input[:-1]
updateStandards(user_input)
print('Write your password:', ''.join('*' for _ in range(len(user_input))))
# Stop listener
if key in [Key.enter, Key.esc]:
finished(user_input)
return False
When user end writing password, you can do anything you want with it:
def finished(password):
# do what you need to do, e.g. store password somewhere
standards = checkStandards(password)
if all(standards):
print('Your password is:', password)
else:
print('Your password should meet all the rules')
I'm trying to make a program that tests the strength of a password. Right now, everything else works, however the numbers doesn't. I can't test whether a string is a number without it not returning the last print statement. I probably haven't explained it well, but how can I make it so that it tests if a characer in a string is a number?
error_list = ['']
errors = ''
password = str(input('Enter in your password to test: '))
for char in password:
if type(char) == int:
safe_unsafe.append('y')
else:
safe_unsafe.append('n')
if 'y' in safe_unsafe:
pass
else:
errors = errors + 'No instance of a number was found.\n'
error_list.append('number')
safe_unsafe.clear()
print(errors)
You are looking for isdigit() API
https://docs.python.org/3.8/library/stdtypes.html#str.isdigit
Example
str = "1"
str.isdigit() #this return True
"a".isdigit() #return False
Updates in your code
error_list = ['']
errors = ''
password = str(input('Enter in your password to test: '))
for char in password:
if char.isdigit(): #changed line
safe_unsafe.append('y')
else:
safe_unsafe.append('n')
if 'y' in safe_unsafe:
pass
else:
errors = errors + 'No instance of a number was found.\n'
error_list.append('number')
safe_unsafe.clear()
print(errors)
this is my password checker code (whether it is valid or not)
I need to run the password checker for 5 times, until it's valid.
If it's valid, I have to break out of the loop.
The password should be more than 7 characters.
The password needs to include both numbers (at least two) and characters.
(If not, return False)
There should be no space.
If there is anything else than numbers and characters, I need to return False
I need to run my password_checker function in the for loop,
but I'm not so sure what to say after 'if'.
I have tried -
if a=False:
print(password_checker(i))
print(Invalid password)
but it didn't work.
Also, I don't understand how should I call my password_checker() in the for loop.
Finally, I need to put a break in my for loop
if the password in the input is valid.
But I'm not sure where is the appropriate part to place it
def password_checker(password):
a=True
num_Count = 0
if password.isalpha() == True:
print ("error! needs numbers")
a = False
if password.isnum() == True:
print ("error! needs characters")
a = False
if password.isspace() == True:
print ("error! no space allowed")
a = False
if len(password)<=8:
print ("error! needs more than 8 characters")
a = False
for i in range(0, 10):
num_Count += password.count(i)
if num_Count(password.count()) < 2:
print("error! needs at least 2 numbers")
a = False
password = str(input("Enter password: "))
for i in range(0,5):
if ____________________:
print(password_checker(i))
print("Invalid password")
else:
print(password_checker(i))
print("Valid password")
break
How should I correct my code in order to make my function work?
for i in range(0,5):
password = str(input("Enter password: "))
password_checker_result = password_checker(password)
if not password_checker_result:
print("Invalid password")
else:
print("Valid password")
break
This code will work for you, now let me explain:
The flow is as following:
This is done 5 times (is inside the for loop):
1) Request password from user.
2) Check if password is valid.
3) Print according to valid/not valid result.
The fact that you are using a for loop does not require you to actually use the iteration index (meaning 'i' in our case)
As part of an assignment, I'm creating a program to ask a user to input a username and password.
I've completed the username part (easy), but in the assignment instructions, the password must:
contain an uppercase character
contain a lowercase character
be longer than 6 characters
contain a number
have no white space
There are 5 specific error messages that need to display if any of these conditions are not true.
What I've got currently has some weird behavior, the errors only show up in a specific order (for example, password "f" will have the error "must have an uppercase character" instead of "must be longer than 6 characters"). I know this is because of the nesting order of the if statements, but if there's a better way... It also for some reason doesn't catch white space in the password. I know it probably isn't the most efficient way but here's what I've got so far:
def validatePassword():
accept = "n"
while accept == "n":
password = input("Please enter a valid password: ")
upper = "n"
lower = "n"
digit = "n"
length = "n"
white = "n"
if len(password) >= 6:
length = "y"
for char in password:
if char in string.ascii_uppercase:
upper = "y"
if char in string.ascii_lowercase:
lower = "y"
if char in string.digits:
digit = "y"
if char not in string.whitespace:
white = "y"
if upper == "y":
if lower == "y":
if digit == "y":
if length == "y":
if white == "y":
accept = "y"
else:
print("::: ERROR :::",password,"must not have any white space character.")
else:
print("::: ERROR :::",password,"must be longer than 6 characters.")
else:
print("::: ERROR :::",password,"must contain a number.")
else:
print("::: ERROR :::",password,"must contain a lowercase character.")
else:
print("::: ERROR :::",password,"must contain an uppercase character.")
return password
You could try something like this:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def validatePassword(password):
if not any(x.isupper() for x in password):
return False, "No upper case character"
if not any(x.islower() for x in password):
return False, "No lower case character"
if len(password) < 6:
return False, "Not longer than 6 characters"
if not any(x.isdigit() for x in password):
return False, "No number"
if any(x.isspace() for x in password):
return False, "Contains hitespace"
return True, ""
def test():
# test some passwords
test_passwords = ["lkjasdf", "KAJSDF", "lfSF", "asdfADSF", "asdf ADSF 123", "asdfADSF123"]
for p in test_passwords:
print validatePassword(p)
# "real" usage
while True:
password = input("Please enter a valid password: ")
result, message = validatePassword(password)
if result is True:
break
else:
print(message)
if __name__ == '__main__':
test()
Obviously the correct way to do this is with any() and a generator expression, but seeing as how you said I'm like 8 weeks into a 10 week introductory course those probably don't help you.
Here's how you can do it without using any() by just looping through the characters checking for the presence of certain types of characters.
def validate_password(password):
hasUpper = hasLower = hasNumber = hasWhiteSpace = False
for char in passwordStr:
if char.isupper():
hasUpper = True
if char.islower():
hasLower = True
if char.isdigit():
hasNumber = True
if char.isspace():
hasWhiteSpace = True
if len(password) <= 6:
return False, "Password must be longer than 6 characters"
if not hasUpper:
return False, "Password must contain atleast one uppercase character"
if not hasLower:
return False, "Password must contain atleast one lowercase letter"
if not hasNumber:
return False, "Password must contain alteast one number"
if hasWhiteSpace:
return False, "Password cannot contain any white space"
return True
First, there's the data type bool which can represent the values True and False. You should use them to represent simple true/false states instead of assigning the strings "y" and "n".
Second, checking every character separately and storing whether the different conditions are met at least once is a possible way. However, Python has powerful string examination methods that can make your life much easier. Let me demonstrate them by writing a short function which takes aa password as argument and simply returns True or False depending on whether the passwords meets your restrictions:
def is_password_valid(password):
# check password length:
if len(password) < 6:
print("Your password is too short, at least 6 characters are required!")
return False
# check if password contains any non-alphanumeric letters (including whitespace):
# (isalnum() only returns true if the string only contains letters and digits, nothing else)
if not password.isalnum():
print("Your password may only contain letters and digits!")
return False
# check if password contains letters:
# (isdigit() only returns true if all of the characters are numbers)
if password.isdigit():
print("Your password does not contain any letters!")
return False
# check if password contains uppercase letters:
# (islower() only returns true if all of the letters are lowercase, non-letters are ignored)
if password.islower():
print("Your password does not contain any uppercase letters!")
return False
# check if password contains lowercase letters:
# (isupper() only returns true if all of the letters are uppercase, non-letters are ignored)
if password.isupper():
print("Your password does not contain any lowercase letters!")
return False
# check if password contains lowercase numbers:
# (isalpha() only returns true if all of the characters are letters)
if password.isalpha():
print("Your password does not contain any numbers!")
# if all conditions above are okay, the password is valid:
print("The password is okay.")
return True
You may of course reorder the blocks in my code above as you wish.
You can then simply use this helper function inside your loop which looks a lot simpler and cleaner now:
def validate_password():
accept = False
while not accept:
password = input("Please enter a valid password: ")
accept = is_password_valid(password)
You can try Regular Expressions. If you don't know about regex, as you've mentioned in your comment, this is a great website.
For validation, check if the password matches with any of the rules which will render it invalid and if not, it is a valid password.
import re
def validate(passwd):
pattern = r'^(.{0,5}|[^0-9]*|[^A-Z]*|[^a-z]*|.*\s+.*)$'
result = re.search(pattern, passwd)
if result:
print 'Invalid Password'
else:
print 'Valid Password'
What this does is check if, passwd is less than 6 chars OR contains no numbers OR contains no uppercase chars OR contains no lowercase chars OR contains spaces. If none of the criteria matches, the password is valid.
I need some help figuring out how to make a function that checks a string for a bunch of conditions.
Passwords must be at least 5 characters long
Passwords must contain at least one upper case letter
Passwords must contain at least two numbers
Passwords may not contain the characters "E" or "e"
Passwords must include at least one special symbol: !, #, #, $, %, ^, &
right now this is all that I have
def passwordChecker(password):
'''
'''
caps = sum(1 for c in password if c.isupper())
nums = sum(1 for c in password if c.isdigit())
symb = any(c in password for c in '!##$%^&')
note = any(c in password for c in 'Ee')
if len(password) <5:
return False
elif caps < 1:
return False
elif nums < 1:
return False
elif symb == False:
return False
else:
return True
Edit**
Just realized that I have to check also if there are commonly used passwords like 'password' or '111111' and I dont really know about how I would approach this.
Just an alternative using regular expressions:
import re
def passwordChecker(password):
return all(re.search(pattern, password) for pattern in
('.{5}', '[A-Z]', '\d.*\d', '^[^Ee]*$', '[!##$%^&]'))
Demo using five barely invalid and five barely valid tests (one invalid and one valid for each of the five rules):
for password in ('1A!', '12!34', 'A1bc!', 'A12E!', 'A12bc',
'1A!2.', 'A2!34', 'A12c!', 'A12b!', 'A12b#'):
print(passwordChecker(password))
Prints False for the first five and True for the last five.
you are just missing a branch
elif note:
return False
before the else:
This is a good time to talk about decorators! I love using decorators to validate data, probably too much. You could make validators for all that, and wrap it around your get_password method.
def v_length(password):
return len(password) >= 5
def v_upper(password):
return password.lower() != password
def v_2_nums(password):
return sum(c.isdigit() for c in password) >= 2
def v_no_e(password):
return "e" not in password.lower()
def v_specialchar(password):
any(s in password for s in "!##$%^&")
def validator(*tests):
def wrap(func):
def wrapped(*args, **kwargs):
result = func(*args, **kwargs)
if not all(test(result) for test in tests):
# fail the input somehow -- how??
return result
return wrapped
return wrap
#validator(v_length, v_upper, v_2_nums, v_no_e, v_specialchar)
def get_password():
pwd = input("Enter your password: ")
I like to wrap my validators in their own factories when I do this in real code, so that it's easier to change per application
def v_length(min_length):
def wrapped(password):
return len(password) >= min_length
return wrapped
#validator(v_length(8))
def get_weak_password():
input("Enter your wussy password: ")
#validator(v_length(64))
def get_strong_password():
input("Enter your Herculean password: ")
This second approach works well for checking for common passwords.
def v_common(common_pwd_set):
def wrapped(password):
return password not in common_pwd_set
return wrapped
COMMON_PASSWORDS = {"hunter2", "111111", "password"}
#validator(v_common(COMMON_PASSWORDS))
def get_password():
pwd = input("Use a tricksy one! ")
The following checks for each failure condition, with short-circuiting (it'll stop checking once it finds something). The "common" passwords aren't really common, but I wanted values that would pass the rest of the checks.
def passwordChecker(password):
'''
A password checker. Returns True if the password is acceptable; False otherwise.
'''
if (len(password) < 5 or
not any(c.isupper() for c in password) or
sum(c.isdigit() for c in password) < 2 or
'e' in password.lower() or
not (set(password) & set('!##$%^&')) or
password in {'Password12!', 'Passwd12!'}):
return False
return True
>>> passwordChecker('Password12!')
False
>>> passwordChecker('hi')
False
>>> passwordChecker('H12!')
False
>>> passwordChecker('Hi12!')
True
Yet another way to do this...
def passwordChecker(password):
return (len(password) > 4 and
len(filter(str.isupper, password)) > 0 and
len(filter(str.isdigit, password)) > 1 and
'e' not in password.lower() and
any(special in password for special in '!##$%^&') and
password not in ('password', '111111'))
I think the most interesting part of my solution is the use of filter; some people like it, others hate it. Anyway, all of the other solutions work just as well. Just thought I'd throw this one into the mix for completeness.