.NET Tip: Creating a Password-Checking Function

As much as I hate having to remember a password for every Web site I visit, password security is one of the easiest ways to tighten access to any application. Password security can have complexity rules, such as length or character type, expiration, or remembering previous passwords so the user is forced to create a brand new password.

The function this tip provides will let you check a password against a set of rules, as well as a set of previously used passwords. The function uses a parameter array for the list of passwords, as well as a flag enumeration to make it easier to specify which rules to enforce.

The first part of the code is an enumerated type called PasswordRules:

[Flags]
public enum PasswordRules
{
   /// <summary>
   /// Password must contain a digit
   /// </summary>
   Digit = 1,
   /// <summary>
   /// Password must contain an uppercase letter
   /// </summary>
   UpperCase = 2,
   /// <summary>
   /// Password must contain a lowercase letter
   /// </summary>
   LowerCase = 4,
   /// <summary>
   /// Password must have both upper and lower case letters
   /// </summary>
   MixedCase = 6,
   /// <summary>
   /// Password must include a non-alphanumeric character
   /// </summary>
   SpecialChar = 8,
   /// <summary>
   /// All rules should be checked
   /// </summary>
   All = 15,
   /// <summary>
   /// No rules should be checked
   /// </summary>
   None = 0
}

Note the [Flags] entry at the top of this enumeration. It indicates that the values can be used as binary flag values. Each value (except for 6 and 15) is a power of 2, and 15 is a combination of 1, 2, 4, and 8. By using this model, you can check whether a flag is set using binary operators. Here's the function that uses these flags:

public static bool IsPasswordValid(string password,
                                   PasswordRules rules,
                                   params string[] ruleOutList)
{
   bool result         = true;
   const string lower  = "abcdefghijklmnopqrstuvwxyz";
   const string upper  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   const string digits = "0123456789";
   string allChars     = lower + upper + digits;

   //Check Lowercase if rule is enforced
   if(Convert.ToBoolean(rules & PasswordRules.LowerCase))
   {
      result &= (password.IndexOfAny(lower.ToCharArray()) >= 0);
   }

   //Check Uppercase if rule is enforced
   if(Convert.ToBoolean(rules & PasswordRules.UpperCase) )
   {
      result &= (password.IndexOfAny(upper.ToCharArray()) >= 0);
   }

   //Check to for a digit in password if digit is required
   if(Convert.ToBoolean(rules & PasswordRules.Digit))
   {
      result &= (password.IndexOfAny(digits.ToCharArray()) >= 0);
   }

   //Check to make sure special character is included if required
   if(Convert.ToBoolean(rules & PasswordRules.SpecialChar))
   {
      result &= (password.Trim(allChars.ToCharArray()).Length > 0);
   }

   if (ruleOutList != null)
   {
      for(int i = 0; i < ruleOutList.Length; i++)
         result &= (password != ruleOutList[i]);
   }

   return result;
}

Each test does a binary AND on the rules value and the flag in question. If the test comes back true, the rule is checked and the result is ANDed together with the previous tests. The final test checks the other passwords that were passed to the function to see whether the new password matches any of them. If it matches, the test fails.

Although this function doesn't have any error messages, you easily could return an array of strings with the particular errors or tests that failed. You also can use the flag enumeration for other similar functions. I also use it to specify validation rules for fields, and there are many other options for using this C# feature.

About the Author

Eric Smith is the owner of Northstar Computer Systems, a Web-hosting company based in Indianapolis, Indiana. He also is a MCT and MCSD who has been developing with .NET since 2001. In addition, he has written or contributed to 12 books covering .NET, ASP, and Visual Basic. Send him your questions and feedback via e-mail at questions@techniquescentral.com.



Comments

  • Additional Functionality

    Posted by davidmknoble on 10/04/2006 03:54pm

    Overloaded methods could be added for IsPasswordValid that include an integer indicating the number of digits that must be included. The test can be used by comparing this with the result of an InStr function. Also a function for the required minimum length of the password could be added.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 19, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT In response to the rising number of data breaches and the regulatory and legal impact that can occur as a result of these incidents, leading analysts at Forrester Research have developed five important design principles that will help security professionals reduce their attack surface and mitigate vulnerabilities. Check out this upcoming eSeminar and join Chris Sherman of Forrester Research to learn how to deal with the influx of new device …

  • Specialization and efficiency are always in need. Whether it's replacing an aging roof, getting a haircut, or tuning up a car, most seek the assistance of trusted experts. The same is true in the business world, where an increasing number of companies are seeking the help of others to administer their IT systems and services. This special edition of Unleashing IT highlights a new breed of IT caretaker -- Cisco Powered service providers -- and the business advantages and operational efficiencies they …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds