-1

I'm using regular expression to check/enforce a password requirement - minimum: 6 characters, max: 12 characters with a combination of numbers, alphabets and the specified special character.

import re

pswd = input('Please enter your password: ')

reg = re.compile(r'[A-Za-z0-9@#$]{6,12}')

mat = re.match(reg, pswd)

if mat:
    print(f"{pswd} is a valid password.")
else:
    print("Please check password requirements")

When I test 2We3345 it prints:

2We3345 is a valid password.

I am of the impression that .match requires the entire string to match the regex in its entirety. Am I missing something? I tried with the .search method, but no dice.

J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
wuki
  • 89
  • 9
  • this approach will limit passwords to this characters instead of enforcing using all of them. Also, why limit to 12 chars? – Marat Sep 14 '19 at 22:15
  • Your regex says you need between 6 and 12 characters drawn from the set you provided; the password you are testing has 7 characters. Thus, according to your regex, this *is* a valid password. What makes you think it isn't? – Scott Hunter Sep 14 '19 at 22:16
  • I thought .match means it has to match everything in the regex? The test password does not contain any special characters; I require the password to be of length 6 -12 and to contain numbers, alphabets and the special characters in the regex to pass this test. How do I enforce this? Is there a regex method that forces it to check for all the matches? – wuki Sep 14 '19 at 22:19
  • Try `reg.match(string)‘, with `reg` being the compiles RE –  Sep 14 '19 at 22:31

3 Answers3

0

The password you used matches the capture group since it begins with a sequence of 6-12 characters matching any of A-Z, a-z, 0-9, @, #, or $.

Also, re.match only checks the beginning of the string. From the docs:

re.match(pattern, string, flags=0)

If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object

Notice that a password exceeding 12 characters will also pass, as will passwords containing invalid characters after 6 valid ones.

To match the entire string, try the following regex:

'^[A-Za-z0-9@#$]{6,12}$'

Additionally, check for special characters like so:

reg = re.compile(r'[@#$]')
mat = re.search(reg, pswd)
if mat:
    # ...
J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
Irfan434
  • 1,463
  • 14
  • 19
  • Thanks for the detailed explanation. Sorry, I'm finding it difficult to articulate this into code; how do I "match the entire string" and "check for special characters" simultaneously? I tried using a boolean AND for both conditions but all to no avail – wuki Sep 14 '19 at 23:07
  • The boolean should be in the `if` statement. e.g. if mat1 and mat2: ... – Irfan434 Sep 15 '19 at 00:09
  • Correct. I'm using a boolean with an if statement but that doesn't work at all. Does it work for you? – wuki Sep 15 '19 at 00:23
  • See edit. (I accidentally left a backslash before the `[`). – Irfan434 Sep 15 '19 at 00:26
  • Edit: I was using .match attribute instead of the .search attribute for my boolean. I am new to regex so I may need to understand how these different attributes work. posting my working code here. – wuki Sep 15 '19 at 00:31
  • after reading the documentation of `search` and `match`, I believe `match` is a misnomer since it only checks the beginning of the string for the pattern. Personally, I'll stick with `search` when needed in my regex code moving forward as opposed to `match`. – wuki Sep 15 '19 at 01:22
0

This is my working code:

import re

pswd = input('Please enter your password: ')

reg = re.compile(r'^[A-Za-z0-9@#$]{6,12}$')
spec_reg = re.compile(r'[@#$]+')

pswd_mat = reg.search(pswd)
spec_mat = spec_reg.search(pswd)

if pswd_mat and spec_mat:
    print(f"{pswd} is a valid password")
else:
    print("Please check password requirements")
wuki
  • 89
  • 9
0

Password constraints are:

1.  Only uses letters a-z, A-Z, digits (0-9), and special characters @#$
2.  Length 6-12 characters
3.  Has at least one of each (lower case, uppper case, digit, and special character.

Solution:

import re
# (?=...) is a positive lookahead which means the pattern must be in the following characters
# (?=.*[A-Z]) means upper case character must be ahead
# (?=.*[a-z]) means a lower case character must be ahead
# (?=.*/d)    means a digit (0-9) must be ahead
# (?=.*[@#$]) a special character must be ahead

# pattern to satisfy constraints
pattern = r"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@#$])[A-Za-z0-9@#$]{6,12}$"

prog = re.compile(pattern)
prog.match(password)  # non-null if valid password

Test

pwds = ["password", "passWord0#", "password0#", "PassWord#0", "PassWord#0/", "PassWord#0andmore", ]

print("\n".join([f"{pwd} {True if prog.match(pwd) else False}" for pwd in pwds]))

Output

password False        # No upper case, numbers, or special
passWord0# True       # At least one of each
password0# False      # No upper case
PassWord#0 True       # At least one of each
PassWord#0/ False     # "/" is not an allowed character
PassWord#0andmore False  # More than 12 characters
DarrylG
  • 16,732
  • 2
  • 17
  • 23