HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Regex password strength test

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
regexteststrengthpassword

Problem

I've been following a Python programming book and reached the Regex chapter where I encountered this challenge:

Write a password strength checker that checks if a password is:

  • At least 8 character long



  • Contains at least one uppercase and lowercase letter.



  • And contains at least one digit.



I managed to do so, but frankly my solution seems both long and ugly. I was hoping someone could shed some light as to how I could maybe condense my program and improve readability if possible.

import re
def is_password_strong():
    password = input('Enter a password to test: ')
    
    length_regex = re.compile(r'.{8,}')
    length = True if length_regex.search(password) != None else False

    uppercase_regex = re.compile(r'[A-Z]')
    lowercase_regex = re.compile(r'[a-z]')
    uppercase = True if uppercase_regex.search(password) != None else False
    lowercase = True if lowercase_regex.search(password) != None else False
    case = True if uppercase and lowercase == True else False

    digit_regex = re.compile(r'[0-9]')
    digit = True if digit_regex.search(password) != None else False

    return(length and case and digit == True)
print(is_password_strong())


And here is my non-regex solution if you can't read the above and want to see what I am trying to do with regex:

def is_password_strong():
    password = input('Enter a password to test: ')
    length = len(password) >= 8
    case = password != password.upper() and password != password.lower()
    digit = any(c.isdigit() for c in password)
    
    return(length and case and digit == True)


I know this isn't a good test of password strength, but it was the book's challenge. I'm not implementing it for any real use.

Solution

Here are the major comments:

-
Ideally functions should do one thing at once. Your function is doing two: (1) asking the user for a password and (2) evaluating the strength of that password.

You should break this code into two functions: (1) ask_user_for_password() and (2) is_password_strong(password).

-
Regexes are not always the right tool for the job. (I appreciate this is a chapter on regexes, but the point has to be made.)

Python has fairly powerful string manipulation tools. You should reach for those before opening your regex toolbox – I think the Python constructs are usually much easier to read and debug. Brownie points for writing a version that doesn’t use regexes – I would almost always prefer this version in a “real” codebase.

-
Be lazy about evaluation. This function is fairly fast, because it doesn’t have many checks. Even so, you can save yourself a little work – as soon as a check fails, you can return False.

(It’s fine to bail out early for a password strength evaluation. Try to avoid doing this when doing real authentication – if your function takes noticeably different time depending on what’s wrong with the function, you’re vulnerable to a timing attack.)

-
Your function should have a docstring. Docstrings are the preferred way to document functions in Python. For this function, it should be fairly simple -- it evaluates a password, and returns True/False depending on whether it meets certain criteria -- but you should still write it.

And a few nitpicks:

-
Compare to None with “is”, not “==” and “!=”.

It’s always preferred to check using “is”, which checks identity, not equality – this makes sure the object you’re dealing with really is None, and not a class with a strange equality operator. It’s also faster.

-
You can tidy up your booleans.

Quite a few of your lines boil down to:

result = True if (check != None) else False


This line reduces to:

result = (check is not None)


That’s more readable and direct.

Then your final boolean can be reduced to:

return (length and case and digit)


which is equivalent.

-
Put your main code in an if __name__ == '__main__' block. This means that it only runs when the file is called directly – not, for example, when it’s imported as a module.

This makes your code easier to reuse.

Code Snippets

result = True if (check != None) else False
result = (check is not None)
return (length and case and digit)

Context

StackExchange Code Review Q#112404, answer score: 8

Revisions (0)

No revisions yet.