tags:

views:

314

answers:

3

I need a regex to validate passwords with the following specs:

It must be between 6 and 20 characters with at least one upper case letter, one lower case letter and one digit

+1  A: 

Regexes are used for searching, not for validation. You should not strive to do this in a single regex.

That being said, since you are looking for character classes, and since regexes support them very well, I would suggest using two or three regexes, checking for a match of each one.

    bool IsPasswordValid(string password)
    {
        if (string.IsNullOrEmpty(password) ||
            password.Length > 20 ||
            password.Length < 6)
        {
            return false;
        }
        else if(!Regex.IsMatch(password, "\d") ||
            !Regex.IsMatch(password, "[a-z]") ||
            !Regex.IsMatch(password, "[A-Z]"))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

This is WAY more efficient than trying to encode all of the possible combinations in an overly complicated Regex.

John Gietzen
Regexes are used all the time for validation.
Steve Wortham
Agreed, but that is not what they are made for. The regex to FIND all valid IP addresses is WAY simpler and more efficient than the regex to VALIDATE an IP address. Regexes are a search tool. Useful for validation, yes, but not made for it.
John Gietzen
-1: Searching a pattern it's a validation type; while this regex can ends complicated, I think this is a valid approach
Rubens Farias
I get your point. But I don't think this task is too complicated for a single regex.
Steve Wortham
I agree and this is much easier to read and maintain. Think about someone trying to maintain the other regexes posted.
JonMR
It is completely incorrect to say that regular expressions are not used for validation. *Regular expressions* were *invented* as a way to concisely characterize membership rules for *regular languages*. The regular languages are those languages whose members can be *decided*, ie, verified, by a finite state machine. That regular expressions can be used for search came later in the history of the study of regular languages. If this subject interests you, I started (but never completed) a series of articles on it: http://blogs.msdn.com/ericlippert/archive/tags/Regular+Expressions/default.aspx
Eric Lippert
+4  A: 

I think this works:

^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{6,20}$

Here it is with test cases in Regex Hero.

The idea is to use positive lookaheads to ensure that at least one lower case letter, one upper case letter, and one digit are contained within the password. And then as a last step I simply specify a dot to allow any characters in the 6-20 character range.

Steve Wortham
+1: loved this, ty
Rubens Farias
That does not work. That will pass values of 100 or more characters.
John Gietzen
Will that match a string like "a1A===="? That would seem to meet Jangwenyi's criteria.
Jim Lewis
Don't forget ^ and $ or it will match unlimited password length: ^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])[A-Za-z0-9]{6,20}$
Darin Dimitrov
John, did you test it? I don't get what you mean. It doesn't allow a 21 character password if that's what you're getting at. The {6,20} part prevents that.
Steve Wortham
Good, but this doesn't prevent other characters from breaking the length limit. Also, strictly speaking Jangwenyi didn't say that only [a-zA-Z0-9]{6} were required. So %%%Aa1 should be allowed and ABCDEabcde1234512345%%%%%%%%% should be forbidden, but your regex does the opposite.
Beta
@Steve, no it doesn't you don't have anchors. Also, you aren't allowing other characters than alpha numeric.
John Gietzen
Jim, good point I just fixed that. Darin, also a good point, I've added the ^ and $. Beta, I think this latest version solves that.
Steve Wortham
John, I think I just solved both of those problems.
Steve Wortham
And how many edits were required to get it right?
John Gietzen
Yes, I think that does the trick. (Personally I make my edits explicit in a case like this.)
Beta
John - just one edit I think. You know, I don't completely disagree with your method. It's just that there are times when a single regex is preferred for brevity. There are other times when a solution such as yours may be needed to handle extreme complexity.
Steve Wortham
No, yeah, I understand that regexps are powerful, but there are often so many pitfalls and unforeseen issues that they end up being overly complicated and unreliable.
John Gietzen
A: 

This allows spaces and special characters, but should follow your specs:

^(?=.\d)(?=.[A-Z])(?=.*[a-z]).{6,20}$

I use Expresso to help test my .Net regular expressions.

grant