This question already has answers here:
Validation of a Password - Python
(14 answers)
Closed 1 year ago.
I would like to test if the input value meets the criterias:
at least one lower case letter
at least one upper case letter
at least one digit
at least one character that is non \w
It seems the regex I programmed only follows this specific order like:
abCD99$%
But if I shuffled the sequence, the regex doesn't work anymore:
CD99ab$%
Anyone knows what the problem is please? Cheers in advance.
import re
# Asks user for an input
print('Please enter a password for checking its strength:')
pwd = input('> ')
#Test the input to see if it is more than 8 characters
if not len(pwd) < 8:
pwdRegex = re.compile(r'([a-z]+)([A-Z]+)([0-9]+)(\W+)') #order problem
if not pwdRegex.search(pwd) == None:
print('Password OK.')
else:
print('Please make sure password fulfills requirements!')
else:
print('Characters must not be less than 8 characters!')
You need to make use of lookaheads to verify your requirements:
(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\W)^.+$
(?=.*[a-z]) - make sure we have a lowercase char somewhere
(?=.*[A-Z]) - make sure we have an uppercase char somewhere
(?=.*[0-9]) - make sure we have a digit somewhere
(?=.*\W) - make sure we have a non-\w somewhere
^.+$ - all the aforementioned requirements were met so lets capture the entire line
This piece can be omitted if you're just doing a pass/fail test and don't need to capture anything
https://regex101.com/r/HdfVXp/1/
In your case, I think it could be a good solution to make your validation without regex:
def isGoodPassword(password):
# contains upper and lower, digit and special char
return (not password.islower()
and not password.isupper()
and any(c.isdigit() for c in password)
and any(not c.isalnum() for c in password))
isGoodPassword('hello') # False
isGoodPassword('Hello!') # False
isGoodPassword('Hello!1') # True
The https://pypi.org/project/password-strength/ package contains code to do this. If you are interested in how this is done rather than actually doing it you could read the source code.
Related
What im making
Hi!
Im making a password generator script in Python ( Script below ). and i was wondering what the best way would be to make sure the passwords dont have two of the same character/symbol right after eachother.
as an example:
kjhd8!3JJp-#huwwg
i would like a way within my script to make sure the duplicates arent "touching". if that makes sense (my english isnt very good).
the same password can have the same character, thats fine. but i would like it not to have them "touching"
like:
kjwhd8!3Jp-#huwJg
if that makes sense.
The script
import random
import string
import sys
#amount of passwords to make
amount = 10
# Characters and symbols to use for the password
# ive split it up to make sure it takes from all of the lists
chars ="abcdefghjkmnpqrstuvwxyzABCDEFGHJK"
specials="#####!-----"
digits="2346789"
characters = list(chars + digits + specials)
def generate_random_password():
# length of the passwords
length = 18
# mixes and shuffles the characters
random.shuffle(characters)
# Puts the sections together at random
password = []
for i in range(length):
password.append(random.choice(characters) )
# another shuffle to make sure (probably noy needed but meh)
random.shuffle(password)
# converts to a string
print("".join(password))
# Prints out as many passswords as stated in the "amount" variable
for index in range(amount):
generate_random_password()
You can just check if the generated char is the same that the previous one, if it is: pick another char, else continue.
prev_char=None
for i in range(length):
random_char = random.choice(characters)
while prev_char == random_char:
random_char = random.choice(characters)
password.append(random_char)
prev_char = random_char
You can use a regex for this!
The expression:
(.)\1
What it does:
(.) - group that matches one character
\1 - reference to group 1 (the group above)
What this essentially does is that it looks for a character repeating right after itself.
How to use it?
import re
any(re.findall(r"(.)\1", "kjwhd8!3Jp-#huwJg"))
findall will find any ocurrences of this; any will give you True or False if there are any cases.
Note: You could also extend this so that the same character doesn't repeat within the next let's say 4 characters: (.).{0,4}\1
I am brand new to Python.
I'm trying to ensure a username contains ONLY alpha characters (only a-z). I have the below code. If I type digits only (e.g. 7777) it correctly throws the error. If I type numbers and letters mix, but I START with a number, it also rejects. But if I start with a letter (a-z) and then have numbers in the string as well, it accepts it as correct. Why?
def register():
uf = open("user.txt","r")
un = re.compile(r'[a-z]')
up = re.compile(r'[a-zA-Z0-9()$%_/.]*$')
print("Register new user:\n")
new_user = input("Please enter a username:\n-->")
if len(new_user) > 10:
print("That username is too long. Max 10 characters please.\n")
register()
#elif not un.match(new_user):
elif not re.match('[a-z]',new_user):
print("That username is invalid. Only letters allowed, no numbers or special characters.\n")
register()
else:
print(f"Thanks {new_user}")
Why don't you use isalpha()?
string = '333'
print(string.isalpha()) # False
string = 'a33'
print(string.isalpha()) # False
string = 'aWWff'
print(string.isalpha()) # True
in your code, uf, un and up are unused variables.
the only point where you validate something is the line elif not re.match('[a-z]',new_user):, and you just check if there is at least one lowercase char.
To ensure that a variable contains only letters, use: elif not re.match('^[a-zA-Z]{1,10}$',new_user):
in the regex ^[a-zA-Z]{1,10}$ you find:
^ : looks for the start of the line
[a-zA-Z] : looks for chars between a and z and between A and Z
{1,10} : ensure that the char specified before (letter) is repeated between 1 and 10 times. As LhasaDad is suggesting in the comments, you may want to increase the minimum number of characters, e.g. to 4: {4,10}. We don't know what this username is for, but 1 char seems in any case too low.
$ : search for the end of the line
Since you were looking for a RegEx, I've produced and explained one, but Guy's answer is more pythonic.
IMPORTANT:
You're not asking for this, but you may encounter an error you're not expecting: since you're calling a function inside itself, you have a recursive function. If the user provides too many times (more than 1000) the wrong username, you'll receive a RecursionError
As the re.match docs say:
If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object.
That's exactly what's happening in your case: a letter in the beginning of the string will satisfy the match. Try the expression [a-z]+$ which will make sure that the match expands till the end of the string.
You can check the length on the same go: [a-z]{1,10}$.
I'm a beginner in Python and my assignment is to guess the password by running through the length of the unknown, random password and then replacing that position with the correct letter/number. I know it involves running the code until a match is found but I'm stuck.
You are to write a program that will try to guess each position of the password. The program must use a function that contains the code to hack the password.
Use of lists and methods/functions such as list( ) and .join will be helpful.
You should begin by displaying a string made up of asterisks (e.g. *******) equal to the length of the generated password.
As you match each letter/number in the secret password, replace the asterisk in that same position with that letter/number.
The output should look like this:
Password is yfdszk
Hacking...
Found match at position 2
*d****
Found match at position 1
*fd***
Found match at position 5
*fd**k
Found match at position 3
*fds*k
Found match at position 0
yfds*k
Found match at position 4
yfdszk
I did it! yfdszk
Here is my code:
import random
characters="abcdefghijklmnopqrstuvwxyz0123456789"
charList=list(characters)
def generatePassword(pwLen):
pw=""
for i in range(pwLen):
rand=int(random.randint(0,len(charList)-1))
pw=pw + (charList[rand])
pwList = list(pw)
return pw
def hackPassword(pw):
r`enter code here`and=int(random.randint(0,len(charList)-1))
pw=pw + (charList[rand])
pwList = list(pw)
asterisk = "*" * len(pw)
asteriskList = list(asterisk)
print asterisk
for numbers in range(len(charList)):
if charList == pwList[]:
password = pw[:index] + "*" + pw[index+1:]
password=generatePassword(8)
# display secret
print "Password is " + password
hackPassword(password)
I need to be able to guess the password, using a for loop to go through the length of the password, then finding a match, and then replacing that asterisk with the found letter/number.
But I'm getting this error message:
IndexError: list index out of range on line 20
Although your sample run is flawed, I believe I understand the gist of what you're trying to do. You generate a random password and then represent it with asterisks, so that the length is shown. Then, for each character in characters="abcdefghijklmnopqrstuvwxyz0123456789" you check if it matches any of the chars in the password. By the time you've run through it, you're done. So, you're going to need a double nested loop. I won't write it for you, but i'll give you a hint, in pseudocode:
generate a random password
make a corresponding 'fake' password of the same length of asterisks
for char in charList:
for position in actual password:
if char matches that position:
change the asterisk to that char in the fake password
if my fake password is cracked (no more asterisks):
print('Whoohoo!')
go home, you're done
Hope this helps! Getting the logic right is always the hardest part of programming!
As a side note, I got the above understanding because I noticed in your example that you are cracking the password in alphabetical order... d-f-k-s-y-z...
I am trying to write a program that would check if the letters and numbers in a string are in the right order, and the example I am using to write it is a car registration plate. Is it possible to check if the letters and numbers in a string correspond to a format of where they are in relation to each other?
For example:
The user inputs a car's registration, and the program checks if it is a standard number plate or not, and if it isn't, the program tells the user. The format's allowed would be from a standard UK registration plate (LLNN.LLL), and the strings could be up to 10 characters long.
You should have a look at regular expressions
For example number plates in my country are 3 letters and 3 numbers (ABC-123) so the regex string would be ([a-zA-Z]{3})-([0-9]{3})
You can use http://pythex.org/ to test regex patterns.
I try to give an answer but it is likely that this is not what you want:
import re
string1 = "(LLNN.LLL)"
string2 = "(abcdefgh)"
reg = re.compile(r'\([LN]{4}\.[LN]{3}')
print bool(re.match(reg, string1))
print bool(re.match(reg, string2))
This matches all the strings that consist of (, 4 times L or N, a dot and 3 times L or N.
this code takes the registration something like xjk649 and tests it, and prints when its false:
iReg = input('Registration: ')
test = ''
for i in range(0,len(iReg)-3):
if 'abcdefghijklmnopqrstuvwxyz'.find(iReg[i]) != -1:
print('succes first three charracters')
else:
test = 'WRONG'
for j in range(3,len(iReg)):
if '0123456789'.find(iReg[j]) != -1:
print('succes last three charracters')
else:
test = 'WRONG'
if test == 'WRONG':
print('false resgistration')
hope this helped
Thanks
I want this function to work in my is_password_good function.
def is_ascii(some_string) :
for each_letter in some_string:
if ord(each_letter) < 128:
return False
return True
The is_good_password function makes certain the user's password is at least 10 characters long and that at least one uppercase and lowercase exists.
How can I pass my ASCII function to check if the user creates a passwords using at least one symbol by ASCII standards?
def is_good_password(password):
count_upper, count_lower = 0, 0
for characters in password:
if characters.isupper():
count_upper += 1
if characters.islower():
count_lower += 1
is_password_good = True
if len(password) <= 10:
print "Password is too weak, must be more than 10 characters long!"
is_password_good = False
if count_upper < 1 or count_lower < 1:
print "Password must contain at least one uppercase and one lowercase character!"
is_password_good = False
create_user(database)
print "Welcome! Username & Password successfully created!"
return is_password_good
You can check string.punctuation exist in string or not.
>>>string.punctuation
'!"#$%&\'()*+,-./:;<=>?#[\\]^_`{|}~'
import re
def getmix(password):
Upper=len(set(re.findall(r'[A-Z]',password)))
Lower=len(set(re.findall(r'[a-z]',password)))
Nums=len(set(re.findall(r'[0-9]',password)))
Symb=len(set(re.findall(r'[~!##$%^&\*()_+=-`]')))
return (Upper, Lower, Nums, Symb)
Should give you a good starting point.
The function somestring.isalnum() will return False if not all characters in the string are alphabetics or numbers.
The precise definition of these categories are locale-dependent; make sure you know which locale you are using.
By the by, ASCII is only defined up to character code 127. If you go above 127, you need to know which character set and encoding you are dealing with. However, characters like # and ! are indeed defined in ASCII, and have character codes in the 30-something range. You are better off using library functions which abstract away the precise character codes, anyway.
has_symbol = False
for c in '~!##$%^&*()_+=-`':
if c in password:
has_symbol = True
break
if not has_symbol:
print "Password must contain at least one uppercase and one lowercase character!"
is_password_good = False
Always use the builtins, don't roll your own, so in that spirit, use the string module for a canonical list of symbols:
import string
symbols = string.punctuation
and printing symbols shows us these characters:
!"#$%&'()*+,-./:;<=>?#[\]^_`{|}~
You can pass to any the "one iterable in another" construction:
if any(char in symbols for char in some_string):
print 'password good'
However, I actually prefer the set methods instead of the above construction:
if set(symbols).intersection(some_string):
print 'password good'
but Triplee's advice on isalnum is just as potent, doesn't require importing the string module, and quite shorter.
if not some_string.isalnum():
print 'password good'