tags:

views:

32

answers:

2

Hi
It's my first post, so hello everybody. I have problem with regex expression. I have password validation by regex.This is my expression:

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$  

It works - the password must contain at least 1 digit, at least 1 lower case letter, at least 1 upper case letter and at least special character: @#$%^&+=. So I have to input all this characters.

But I'd like password, which has at least 3 combination, not all 4.
So these passwords should be good:

2Df (not special character), dF# (not digit), a4% (not upper case). I'd like to ask, how this regex expression should look? I could write each expression to check each combination, for example:

  • Not include digit: ^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$
  • Not include upper case: ^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).*$

But maybe I can do it in one expression. Thanks for help.

Regards

+2  A: 

Why did you use regular expression for that? Simply iterate over your password string and count number of desired character types. In PHP you can use function like count_chars().

Pseudo code for that:

      foreach(password as char) {
        if (is_digit(char))
           digits++;
        if (is_specialchar(char))
           special++;
        if (is_lower(char))
           lower++;
        if (is_upper(char))
           upper++;
        //etc
      }

Now you can define any requirements you wish

      if (dgits > 0) and (lower > 0) and (special > 0)
         passowrd_ok()
      else
         password_bad()

in your case you can smartly count

     if (lower > 0)
        diversity++;
     if (upper > 0)
        diversity++;
     if (special > 0)
        diversity++;
     if (digit > 0)
        diversity++;

     if (diversity >= 3)   //at least 3 different types of characters in password
        pass_ok()
doc
Thanks for your answer. I have to validate password on ASP (not .NET) site - so I think, the best solution is regular expression.
luk4443
@luk4443: why the hell? You can iterate over a string in VB, C# or whatever. In VB the loop is `For i = 0 To s.Length - 1` and access to each character is possible by `s.Chars(i)` or `Mid(s, i, 1)`
doc
OK, thanks, I'll test.
luk4443
@luk443: Also take a look here, there's a question related to that http://stackoverflow.com/questions/80427/iterate-over-and-check-the-byte-value-of-every-character-in-a-string-vba
doc
A: 

If you have to do it with regular expressions, I'd suggest (for clarity's sake) to check all four conditions after one another. For readability, you could first try to find \d in your password, then [a-z], then [A-Z] and then [@#$%^&+=] (although you might want to use [\W_] instead to allow more than just those few extra characters). Then check if at least three of these worked.

If you have to do it in a single regex, you could use alternation:

^((?=.*[a-z])(?=.*[A-Z])(?=.*\d)|(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])|(?=.*[\W_])(?=.*[A-Z])(?=.*\d)|(?=.*[a-z])(?=.*[\W_])(?=.*\d)).*$

but that is just ugly.

Tim Pietzcker