Adaptive Password Policies

Stanford recently published a new security policy allowing their users to choose length over complexity. 

Password complexity has always been the go-to answer for creating secure passwords. Of late, there has been a big push to change that; and for good reason!

Password complexity isn’t as straight-forward as one would think. For example, it’s logical to assume that an 8 character password, all lower case, could be brute-force cracked in 208 billion guesses (26 characters per letter, 8 characters, 26^8) or roughly 2 seconds. If you add more characters (like capital letters, numbers, and symbols), that number soars to 6,095,689,385,410,816 possible combinations, or about a day to crack on modern hardware. On top of all this, there are dictionary attacks and other statistical attacks that can make this easier. (Note: This is usually calculated as bits of entropy, but lets not complicate it)

There’s no doubt that if we took this complex policy (upper case, lower case, symbols, numbers) and added more length, you would create insanely hard passwords to crack. The problem is that they’re also insanely difficult to remember and to type. Have you ever tried to put a 15 character password into your phone’s Facebook login screen? Not fun… The real problem though, is that we create passwords so complex they we 1) reuse them everywhere, 2) forget them, 3) we change one character on password changes, and so on…

So how do we get around this? Well, if you were to replace the password with a pass-phrase you could create a very long password with a huge keyspace. A passphrase can be a sentence (with spaces!) or just a few select words you can remember. For example, looking around my office and picking items I can readily see, I could make up a password like “DeskLightCatCloset”. That’s an 18 character passphrase with a key space of 7.88×10^30!! In a brute force attack, that’s currently uncrackable (25B centuries! at 100B keys per second). You could even use all lowercase characters and you’d still be at 97 centuries (if you had a cracking array). In short: it’s perfectly possible to create a SIMPLE but long password that’s more secure than these convoluted password policies

So, the folks at Stanford created this algorithm that dynamically changes its complexity requirements based on the length of the password itself:

LengthComplexity
 8 – 11 characters Uppercase, Lowercase, Numbers, Symbols
 12-15 characters Uppercase, Lowercase, Numbers
 16-19 characters Uppercase, Lowercase
 20+ charactersAnything

This actually makes quite a bit of sense, but my worry is how you present this to the user in a way they would understand.

Password Sample: 
 

((?=^.{8,11}$)(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[[email protected]#$%^&*()_+}{/":;'?><,])(?!.*\s).*$)|((?=^.{12,15}$)(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$)|((?=^.{16,19}$)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$)|((?=^.{20,}$).*$)

The JavaScript I used for this could be optimized in a bunch of ways, but this is a rather verbose and simple proof of concept for illustrative purposes:

function checkPassword(strPassword)
{
  
  numberOfCharacters = strPassword.length; 

  requirementsString = "";
  booleanPass = false;
  
  if ( numberOfCharacters < 8 ) {
    requirementsString = "Your password must have at least 8 characters<br>";
  }

  else if ( numberOfCharacters < 12 )
  {
      var patt = new RegExp("((?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[[email protected]#$%^&*()_+}{/:;'?><,/s]).*$)");
      if ( patt.test(strPassword.value) ) {
           requirementsString = "PASS!";
      }
      else
      {
          requirementsString = "Your 8-11 character password must have at least:";
          requirementsString += "<ul>";
          requirementsString += "<li>One lowercase letter";
          requirementsString += "<li>One uppercase letter";
          requirementsString += "<li>One symbol";
          requirementsString += "<li>One number";
          requirementsString += "</ul>";
      }
  }
  
  else if ( numberOfCharacters < 16 )
  {
      var patt = new RegExp("((?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).*$)");
      if ( patt.test(strPassword.value) ) {
           requirementsString = "PASS!";
      }
      else
      {
          requirementsString = "Your 12-15 character password must have at least:";
          requirementsString += "<ul>";
          requirementsString += "<li>One lowercase letter";
          requirementsString += "<li>One uppercase letter";
          requirementsString += "<li>One number";
          requirementsString += "</ul>";
      }
  }
  
  else if ( numberOfCharacters < 20 )
  {
      var patt = new RegExp("((?=.*[a-z])(?=.*[A-Z]).*$)");
      if ( patt.test(strPassword.value) ) {
           requirementsString = "PASS!";
      }
      else
      {
          requirementsString = "Your 16-19 character password must have at least:";
          requirementsString += "<ul>";
          requirementsString += "<li>One lowercase letter";
          requirementsString += "<li>One uppercase letter";
          requirementsString += "</ul>";
      }
  }
  else {
      var patt = new RegExp("(.*$)");
      if ( patt.test(strPassword.value) ) {
           requirementsString = "PASS!";
      }
      else
      {
          requirementsString = "Your 20+ character password can hame:"
          requirementsString += "<ul>";
          requirementsString += "<li>Any Characters!!";
          requirementsString += "</ul>";
      }
  }



  document.getElementById('output').innerHTML = requirementsString;

}

Thought this was a good way to spend a Sunday… 

:)Lee

Leave A Comment

Your email address will not be published.