1

I would like to know how one could validate a password with regex.

I tried using lookahaed assertions but I somehow failed. I don't know how I can match a certain length of a string.

My conditions are :

  • At least 8 characters
  • At least one digit
  • At least one lower English letter
  • At least one upper English letter
  • At least one symbol of !@#$%-
  • Only above characters are allowed

Thanks in advance!

4 Answers 4

4

you are in the right step with lookahead assertions.

Your requirements can be broken down to this :

  • (?=.{8,})
  • (?=.*\d)
  • (?=.*[a-z])
  • (?=.*[A-Z])
  • (?=.*[!@#$%-])
  • [\da-zA-Z!@#$%-]*

Putting it all together you end up with this :

foundMatch = Regex.IsMatch(subjectString, @"^(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%-])[\da-zA-Z!@#$%-]*$");

Which can in turn be explained by this :

"
^                   # Assert position at the beginning of the string
(?=                 # Assert that the regex below can be matched, starting at this position (positive lookahead)
   .                   # Match any single character that is not a line break character
      {8,}                # Between 8 and unlimited times, as many times as possible, giving back as needed (greedy)
)
(?=                 # Assert that the regex below can be matched, starting at this position (positive lookahead)
   .                   # Match any single character that is not a line break character
      *                   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   \d                  # Match a single digit 0..9
)
(?=                 # Assert that the regex below can be matched, starting at this position (positive lookahead)
   .                   # Match any single character that is not a line break character
      *                   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   [a-z]               # Match a single character in the range between “a” and “z”
)
(?=                 # Assert that the regex below can be matched, starting at this position (positive lookahead)
   .                   # Match any single character that is not a line break character
      *                   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   [A-Z]               # Match a single character in the range between “A” and “Z”
)
(?=                 # Assert that the regex below can be matched, starting at this position (positive lookahead)
   .                   # Match any single character that is not a line break character
      *                   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   [!@#$%-]            # Match a single character present in the list below
                          # One of the characters “!@#$”
                          # The character “%”
                          # The character “-”
)
[\da-zA-Z!@#$%-]    # Match a single character present in the list below
                       # A single digit 0..9
                       # A character in the range between “a” and “z”
                       # A character in the range between “A” and “Z”
                       # One of the characters “!@#$”
                       # The character “%”
                       # The character “-”
   *                   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
$                   # Assert position at the end of the string (or before the line break at the end of the string, if any)
"
Sign up to request clarification or add additional context in comments.

Comments

1

This should work for you

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%-]).{8,}$

Explanation

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    [0-9]                    any character of: '0' to '9'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    [a-z]                    any character of: 'a' to 'z'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    [A-Z]                    any character of: 'A' to 'Z'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    [!@#$%-]                 any character of: '!', '@', '#', '$',
                             '%', '-'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  .{8,}                    any character except \n (at least 8 times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Really, you shouldn't enforce this kind of password though. See this noteworthy xkcd comic for a fair explanation why

Through 20 years of effort, we've successfully trained everyone to use passwords that are hard for humans to remember, but easy for computers to guess.

XKCD password strength

2 Comments

While this is correct, I think you forgot the final requirement.
Thank you!Nice comic by the way!
0

Is there any reason you need to use a single regex for all of these rules? It's more common, and more readable, to test each one separately. For example:

if(pass.length < 8 || ! pass.matches(/[0-9]/) || ! pass.matches(/[a-z]/)
   || ! pass.matches(/[A-Z]/) || ! pass.matches(/[!@#$%-]/)
   || pass.matches(/[^0-9A-Za-z!@#$%-]/))
{
    . . . // reject password
}

1 Comment

My requirement specifications are regex... Thank you anyway!
0

Probably something like this:
(Oops, better make this at least correct)
expanded

^
(?=[0-9a-zA-Z!@#$%-]{8,}$)
(?=.*[0-9])
(?=.*[a-z])
(?=.*[A-Z])
(?=.*[!@#$%-])

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.