9

I need to enforce the following password policy :

at least 9 characters, with at least one character from each of the 4 character classes (alphabetic lower and upper case; numeric, symbols).

Any regex experts can help out here ? (I am using a Java regex engine)

While we're at it, is there any online tool that can generate a regex for these kind of tasks ?

Thanks !

Michael
  • 22,196
  • 33
  • 132
  • 187
  • A good reference for regex is at http://www.vogella.de/articles/JavaRegularExpressions/article.html. Please post the reg ex that you've tried already – Chetter Hummin Mar 29 '12 at 08:47
  • 2
    Possible duplicate of http://stackoverflow.com/questions/3387785/password-validation-regular-expression – cmbuckley Mar 29 '12 at 08:47
  • 1
    @FelixKling nothing is wrong with it, but there are so many other stuff i want to learn first ;) – Michael Mar 29 '12 at 08:48
  • 1
    Don't! This has been answered so many times on SO, see e.g. http://stackoverflow.com/a/3466868/297323 Break it up into different function, where each performs one single check. This approach is future-proof and above all it's maintainable. – Fredrik Pihl Mar 29 '12 at 08:48
  • 2
    alright, learned my lesson. thanks for the links, it will start investigating. – Michael Mar 29 '12 at 08:49

3 Answers3

11
(?=.{9,})(?=.*?[^\w\s])(?=.*?[0-9])(?=.*?[A-Z]).*?[a-z].*

Note that this pattern doesn't include special utf chars like ö. I would not do this in one regex. I would split it and search for each thing, if you want to validate it.

Dave Halter
  • 15,556
  • 13
  • 76
  • 103
  • if you are in javascript land and using jquery I'd recommend jquery validation plugin, here's a strong password gist https://gist.github.com/mrgcohen/9806928 – mc. Mar 27 '14 at 12:56
  • @mc if you validate data only on js-side of an app, you have no security at all. The server validation has to be performed regardless. – Dariusz Apr 17 '15 at 09:48
  • @Dariusz agreed, however it's nice to have things happen client side too so they are pretty :) - if you wanted you could try to save and run validation on the backend (remotely). But it's nice validating before it hits your machine (if possible). – mc. Apr 23 '15 at 19:51
6

Here's how I would do it (using positive lookahead):

(?=.{9,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\p{Punct}).*

Full example and test:

                       //    Regexp                Description
Pattern p = Pattern.compile("(?=.{9,})"   +     // "" followed by 9+ symbols
                            "(?=.*[a-z])" +     // --- ' ' --- at least 1 lower
                            "(?=.*[A-Z])" +     // --- ' ' --- at least 1 upper
                            "(?=.*[0-9])" +     // --- ' ' --- at least 1 digit
                            "(?=.*\\p{Punct})"+ // --- ' ' --- at least 1 symbol
                            ".*");              // the actual characters
String[] tests = {
        "aB99",         // too short
        "abcdefghijk",  // missing A
        "abcdefGHIJK",  // missing 5
        "12345678910",  // missing a
        "abcDEF12345",  // missing punct
        "abcDEF-2345"   // works!
};

for (String s : tests) {
    boolean matches = p.matcher(s).matches();
    System.out.printf("%-12s: %b%n", s, matches);
}

Output:

aB99        : false
abcdefghijk : false
abcdefGHIJK : false
12345678910 : false
abcDEF12345 : false
abcDEF-2345 : true

Final remark: The problem with this approach is that it's not very user friendly. If you are to give a sensible response to a user, such as "The password is missing a digit-symbol" you need to do the work again (to figure out which requirement failed).

aioobe
  • 413,195
  • 112
  • 811
  • 826
0

I would use multiple regexp's to solve this:

9 chars - you can regexp this but .length() >= 9 is much better!

For the character classes you should use one pr class:

[a-z]+
[A-Z]+
[0-9]+
[£$%&{[...]+ //all the possible symbols you want to accept
or perhaps: 
[:punct:]+ // this depends on your programming language..
or like in the suggestion by @david-halter:
[^\w\s]+  // not alphanumeric or spaces
barsju
  • 4,408
  • 1
  • 19
  • 24