tags:

views:

117

answers:

2

I'm creating a regexp for password validation that will be used in a Java Application as a configuration parameter.

The regexp is:

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

The password policy is:

  • At least 8 chars
  • Contains at least one digit
  • Contains at least one lower alpha char and one upper alpha char
  • Contains at least one char within a set of special char (@#%$^ etc.)
  • Not containing blank, tab etc.

I'm missing just the point 5. I'm not able to include into the regexp the check on not containing blank tab carriage return etc.

Anyone could help me?

+1  A: 

Please take a step back. Why do you restrict the special characters? What's wrong with underscore, for example? Can't your DB handle spaces?

If your database can handle any character code, you should allow your users to use any character they like in the password. For example, hörgh3 is a very secure password because most keyboards in the world simply don't have an ö

Aaron Digulla
It's not that the underscore would be forbidden if I read the requirements correctly. ;-)
Tomalak
Well we have a set of special character to use...this is just an example. I have to include also an underscore.
Kerby82
+7  A: 

Try this:

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

Explanation:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=[^\s]+$)       # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

The (?=.*[xyz]) construct eats the entire string (.*) and backtracks to the first occurrence where [xyz] can match. It succeeds if [xyz] is found, it fails otherwise.

The alternative would be using a reluctant qualifier: (?=.*?[xyz]). For a password check, this will hardly make any difference, for much longer strings it could be the more efficient variant.

The most efficient variant (but hardest to read and maintain, therefore the most error-prone) would be (?=[^xyz]*[xyz]), of course. For a regex of this length and for this purpose, I would dis-recommend doing it that way, as it has no real benefits.

Tomalak
It does not check for not blank or tab and etc.
Kerby82
@Kerby82: I've added a section that does.
Tomalak
I don't know why but it won't compile with the '\s'. The error is: Exception in thread "main" java.lang.Error: Unresolved compilation problem: Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
Kerby82
@Kerby82: In Java strings, backslashes must be escaped. Try to use `\\s`. That's a Java requirement, not a regex requirement.
Tomalak
beautiful solution (+1)
seanizer
Multi-line mode won't make a difference; after all you're checking for `(?=[^\s\t]+$)` (where, by the way, you could drop the `\t`).
Tim Pietzcker
yes \t is pointless since \s include A whitespace character: [ \t\n\x0B\f\r]. But backslashing the \s now in java works perfectly. Thanks a lot!
Kerby82
@Tim You are right with the `\t`, of course. Do `\n` and `\r` fall into `\s`? I'm never sure… — @Keby: Hm, okay. Then forget my warning about multi-line mode. I'll include these last changes with my answer.
Tomalak
You can switch off multi-line mode explicitly as part of the regex if you need to by using (?-m: ... ) around everything else
Adrian Pronk