Test the Strength of a Password in Python

Viewed 1582

A string is a WEAK password if: either, it is less than 8 characters long, or, it is an English word,which is function is_english_word( ) is True.

A string is a STRONG password if: it contains at least 11 characters AND it contains at least 1 lower case letter AND it contains at least 1 capital letter AND it contains at least 1 numerical digit.

A string is a MEDIUM password if it is NOT a WEAK password AND is NOT a STRONG password.

def is_english_word( string ):
    with open("english_words.txt") as f:
        word_list = []
        for line in f.readlines():
            word_list.append(line.strip())
        if string in word_list: 
            return True
        elif string == string.upper() and string.lower() in word_list:
            return True
        elif string == string.title() and string.lower() in word_list:
            return True
        else:
            return False

def password_strength( string ):
    lower = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
    upper = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
    for item in string:
        if item in lower:
            string = string.replace(item, "x")
        elif item in upper:
            string = string.replace(item, "y")
        elif item.isnumeric():
            string = string.replace(item, "n")      
    for item in string:        
        if len( string ) < 8 or is_english_word( string ) :
            return 'WEAK'
        elif len( string ) >= 11 and string.count("x") >= 1 and string.count("y") >= 1 and string.count("n") >= 1: 
            return 'STRONG'
        else:
            return 'MEDIUM'

print( password_strength( 'Unimaginatively' ) )

This password should be "WEAK",but the output is "MEDIUM",I don't know what's the problem of my codes.Many thanks.

2 Answers

There are a number of problems with your code; Notably, you are replacing the lowercase chars with x, uppercase with y and digits with n, before calling is_english_word - that means is_english_word() will be called with 'Xyyyyyyyyyyyyyy' which is not an english word. That is making your password not 'WEAK'.

Since it is also not 'STRONG', it ends up being 'MEDIUM'.

For the record, here is an example of a correct code to do what you want:

import string
def password_strength(string):
    if len(string) < 8 or is_english_word(string):
        return 'WEAK'
    elif (len(string) > 11 and 
            any(ch in string.ascii_lowercase for ch in string) and
            any(ch in string.ascii_uppercase for ch in string) and
            any(ch.isdigit() for ch in string)):
        return 'STRONG'
    else:
        return 'MEDIUM'   

If you think of those 3 restrictions on the types of letters in terms of the same operation (checking it is true for at least one character) performed using string methods, you can simplify your code significantly:

def is_weak(word):
    return len(word < 8 or is_english_word(word)

def is_strong(word):
    return len(word) >= 11 and all(any(method(c) for c in word) 
                                   for method in (str.islower, str.isupper, str.isdigit))

def password_strength(password):
    if is_weak(password):
        return 'WEAK'
    elif is_strong(password):
        return 'STRONG'
    else:
        return 'MEDIUM'
Related