简体   繁体   中英

Is there a way to check the validity of a password only if 3/4 conditions are met?

I have to make a program to check the validity of a password. Conditions are: at least 8 characters, 1 upper letter, 1 lower letter, 1 number in range 0-9, 1 symbol. If 3 / 4 of the conditions are met (excluding password length because it should always be longer than 8 characters) the program should check the password strength. If the length of the password is 8 characters long the strength is equal to 1. for every 4 more characters the strength increases by 1. In case all conditions are met, the strength should be doubled.

In the code bellow, I wrote a huge line of code but I think I have a mistake and that there is a much faster way to do it. So I am asking you whether there is a way to do it faster or not. If yes, what would that be?

def is_valid_password():
    pwd=input("Enter a password: ")
    f=1
    l=0
    u=0
    d=0
    s=0
    p=0
    if(len(pwd)>=8):
        for i in pwd:
            if i.islower():
                l+=1
            if i.isupper():
                u+=1
            if i.isdigit():
                d+=1
            if(i=='!' or i=='@' or i=='#' or i=='$' or i=='&' or i=='_'):
                s+=1
    if((l+u+d+s)==len(pwd) and l==0 and u>=1 and d>=1 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u==0 and d>=1 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d==0 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s==0) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s>=1):
        if((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s>=1):
            if(len(pwd)>12):
                f=(f+(len(pwd)-8)//4)*2
            elif(len(pwd)>=9 and len(pwd)<=12):
                f==4
            elif(len(pwd)==8):
                f==2
            print(f"Valid password with strength {f}")        
        else:
            if(len(pwd)>12):
                f=f+(len(pwd)-8)//4
            elif(len(pwd)>=9 and len(pwd)<=12):
                f==2
            elif(len(pwd)==8):
                f==1
            print(f"Valid password with strength {f}")
            
    else:
        print("Invalid password!")
 
while True:
    is_valid_password()

I'd probably make a list of functions like testLength() , testUpper() , testDigit() , and so on. The functions just return a 1 (fulfilled) or 0 (failed). Note that it is really easy to extend the number and kind of tests.

Now you write something like

numPassed = testLength(pwd) + \
            testUpper(pwd) + \
            testDigit(pwd) + ...
if (numPassed < (3 * numTests)/4)
    issueError("password too weak")

This is kind of pseudo code, but I think the idea is understandable. Note that this code certainly isn't faster, but it is easy to understand and easy to maintain or extend. (It's not slow either, as long as you don't want to test a billion passwords at once).

Personnaly, I do this:

import re

def is_valid_password(PassWord):
    Conditions = 0
    
    if len(PassWord) < 8:
        print(f"The password ({PassWord}) is too short !")
        return 0
    
    # Or re.findall("[a-z]", PassWord):
    if PassWord != PassWord.lower():
        Conditions += 1
    
    # Or re.findall("[A-Z]", PassWord):
    if PassWord != PassWord.upper():
        Conditions += 1
    
    if re.findall("[0-9]", PassWord):
        Conditions += 1
    
    # Or re.findall("[!@#$&_]", PassWord):
    if re.findall("[^a-zA-Z0-9]", PassWord):
        Conditions += 1
    
    if Conditions < 3:
        print(f"The password ({PassWord}) not respect the conditions !")
        return 0
    
    Power = 1 + int((len(PassWord) - 8) / 4)
    
    if Conditions == 4:
        Power *= 2
    
    print(f"Valid password ({PassWord}) with strength {Power}") 
    return 1


is_valid_password("Hello") # Error
is_valid_password("hello2020") # Error
is_valid_password("HELLO2020") # Error
is_valid_password("Hello2022") # 1
is_valid_password("Hello 2022") # 2
is_valid_password("HelloHello2022") # 2
is_valid_password("Hello _ 2022") # 4
is_valid_password("Hello Hello 2022") # 6

I guess it's simpler and more readeable.

You could try this way using regex. include what you need to find in brackets and in or in the pattern:

passwd='P%&ippo8lo'
pattern=r'(\d)|([[:upper:]])|([[:lower:]])|([\$%&])'

1-digit, 2-uppercase letter, 3-lowercase letter, 4-simbol

the 'findall' method will return a list of sets in which you just have to make sure that all the fields have been used:

rt=regex.findall(pattern, passwd)
[
 ('', 'P', '', '')
 ('', '', '', '%')
 ('', '', '', '&')
 ('', '', 'i', '')
 ('', '', 'p', '')
 ('', '', 'p', '')
 ('', '', 'o', '')
 ('8', '', '', '')
 ('', '', 'l', '')
 ('', '', 'o', '')
]

now the hardness of the password depends on how many fields of the set have been used:

good = [False] * 4

for s in rt:
    for i in range(0, len(s)):
        if s[i] != '':
            good[i] = True

print(good)

[True, True, True, True]

if one of the requests has not been used, the corresponding field will be False

About the password length:

ovr_len = len(password) - 8
hardness_point = int(ovr_len / 4)
total_point += hardness_point

one point every 4 characters beyond 8

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM