Validating Strong Pass Phrases Snippet

In case you missed it, the title isn't "Validating Strong Passwords" because by now the inherent weaknesses of traditional passwords are well-known. Even with pass phrases, enforcing "strong" by policy is a good idea to boost entropy.

Most of the available regular expressions check for at least one uppercase, lowercase and numeric character. What they all seem to miss is a declaration of acceptable characters in the first place. I've created a pair of suitable expressions to check against. One ensures that certain characters exist, the other ensures that only those characters exist. If my RegEx skills were better perhaps I could combine the two into a single expression.

The goal is to ensure a user's password is strong according to Microsoft's definition of a strong password, particularly:

  • at least seven characters long
  • contains at least one character from each of the four groups: uppercase, lowercase, numerals, and symbols found on the keyboard.

Since this will validate pass phrases rather than passwords the minimum length will be 14, not 7 (a number suggested by MS PSS lead Robert Hensing). On the upper bound, Windows (from NT forward) allows passwords of up to 128 characters so this method will accept that too. Note that the old limit was 14 characters and this boundary may be in effect on networks still configured to accept connections from older clients.

Other "strong" criteria exist (e.g. does not contain the user or company name, and does not contain a dictionary word) but we will stick to what we can cover with regular expressions. In the end, the OS or Active Directory will be the final arbiter, we just want to eliminate the bulk of invalid requests to update the password.

I've removed a few special characters from the list to demonstrate that you can and should customize this to suit your own needs, policy, or comfort level (in this case the \, <, >, and " characters).

Wherever you use this you will need to drop in the following reference:
using System.Text.RegularExpressions;

/// <summary>
/// Check whether the provided string is a strong password.
/// The string must contain at least one uppercaseone lowercase,
/// one numeral, and one special character.
/// The method allows uppercaselowercasedigits,
/// and keyboard characters except for\ < > "
/// </summary>
/// <param name="password">The password tovalidate.</param>
/// <returns>True if the password is a strong password, false otherwise.</returns>
public static bool IsStrongPassword(String password)
{
   // Special Characters (update here then cut & paste to 2 locations below)
   // \-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:;  ',/

   // Defines minimum appearance of characters
   String ex1 = @"
      ^        # anchor at the start
      (?=.*\d)    # must contain at least one digit
      (?=.*[a-z])    # must contain at least one lowercase
      (?=.*[A-Z])    # must contain at least one uppercase
      (?=.*[\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:;  ',/])  # must contain at least one special character
      .{14,128}    # minmax length
      $        # anchor at the end"; 

   // Allow only defined characters
   String ex2 = @"
      ^        # anchor at the start
      [\w\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:;  ',/] # alphanumerics and special characters only
      {14,128}      # minmax length
      $        # anchor at the end"; 

   return (IsMatch(passwordex1RegexOptions.IgnorePatternWhitespace&&
      IsMatch(passwordex2RegexOptions.IgnorePatternWhitespace));
}

Generated using PrettyCode.Encoder

/// <summary>
/// Match a regular expression against a provided string.
/// </summary>
/// <param name="input">The input string to validate.</param>
/// <param name="pattern">The regular expression pattern used to
/// validate the input.</param>
/// <param name="options">A bitwise OR combination of the
/// RegExOption enumeration values</param>
/// <returns>True if the parameters produce a match, false
/// otherwise.</returns>
public static bool IsMatch(String inputString patternRegexOptions options)
{
   System.Text.RegularExpressions.Regex regex = new Regex(pattern,options);
   System.Text.RegularExpressions.Match m = regex.Match(input);
   if (m.Success)
      return true;
   else
      return false;
}


Generated using PrettyCode.Encoder

Published Wednesday, September 29, 2004 5:33 PM by erobillard
Filed under: ,

Comments

Tuesday, October 05, 2004 2:10 PM by Steve Wonderful

# re: Validating Strong Pass Phrases Snippet

Wonderful, thank you for sharing this server validation code. Although we still need to have this validation in the client side. I created a classical ASP page, attached at the bottom, trying to see if these regex also work. Unfortunately, I was not successful. Could someone point it out what's wrong. Will apprecitate it. Just copy and paste to create your own test page.

-- Test page --
<%@ Language=VBScript %>
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">

<script language="javascript">
function isStrongPassword()
{
// These are the RE from server ccontrol, used to create JS RE objects
// String ex1 = @"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:; ',/]).{14,128}$"
// String ex2 = @"^[\w\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:; ',/]{14,128}$"

// Defines minimum appearance of characters
var pattern1 = "^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:; ',/]).{8,128}$";
// Allow only defined characters
var pattern2 = "^[\w\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:; ',/]{8,128}$";
//var pattern2 = "^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\-\+\?\*\$\[\]\^\.\(\)\|`~!@#%&_ ={}:; ',/]).{8,128}$";

var re1 = new RegExp( pattern1 );

alert( '11111' ); // Used to pinpoint where the JS error is, will not see this alert popup if moved after the next re2 statement, meaning re2 cannot be created due to possibly bad pattern2

var re2 = new RegExp( pattern2 );
var obj = document.form1.password;


var text = obj.value;

alert(text);

if( re1.test( text ) )
{
if( re2.test( text ) )
{
alert( 'This is a strong password.' );
return true;
}
else
{
alert( 'It is not a strong password at 2nd pattern.' );
}
return false;
}
else
{
alert( 'It is not a strong password at 1st pattern.' );
return true;
}
}
</script>

</HEAD>
<BODY>

<P><h2>Registration</h2>
<form id=form1 name=form1>
<table>
<tr><td>Login:</td>
<td><INPUT id=login name=login></td>
</tr>
<tr><td>Password:</td>
<td><INPUT id=password name=password></td>
</tr>
</table>
<P><INPUT id=register type=button value=Register name=register onclick='javascript:isStrongPassword()'></P>
</form>
</BODY>
</HTML>
-- End of test page
Wednesday, October 27, 2004 9:11 AM by vinod

# Regular Expression ,Anyone ???

i want to put following constraints for password validations using regular Expression:
1)IT should start from 2 lower case letters(non consecutive)
2)after that it must contain 2 same numbers.
3)after that it must contain 3 Capital Letters which should be same
4)then any (letter or number) for next two positions
e.g. vn55CCCxy or pn88AAAab or km99BBB99
Thursday, June 28, 2007 2:51 PM by Julie

# re: Validating Strong Pass Phrases Snippet

Here is a regex if you want the following criteria:

Passwords will contain at least (1) upper case letter

Passwords will contain at least (1) lower case letter

Passwords will contain at least (1) number or special character

Passwords will contain at least (8) characters in length

Password maximum length should not be arbitrarily limited

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$

Tuesday, June 10, 2008 10:25 AM by Nathan Loding

# re: Validating Strong Pass Phrases Snippet

This is YEARS after this original post, but to answer the question of why the ASP code snippet doesn't work ... In both patterns the "/" is not escaped.

Leave a Comment

(required) 
(required) 
(optional)
(required)