Scripting Games, Advanced Event 5, Strong Password

Check a given password against various specified criteria and rate the password accordingly.  This was mostly an exercise in pattern matching.  I chose to use a Switch block (actually three switch blocks, just because I could:-)

  1 param ($p=$(Read-Host "Enter Password to check"))
  2 $Score=13; $dictionary='c:\scripts\wordlist.txt'
  4 switch ($p) {
  5 	{Select-String "^$_$" -Quiet -Path $dictionary}
  6 		{"Password is in dictionary"; $Score--}
  7 	{Select-String "^$($_.substring(0,$_.length-1))$" -Quiet -Path $dictionary}
  8 		{"Password minus last character is in dictionary"; $Score--}
  9 	{Select-String "^$($_.substring(1))$" -Quiet -Path $dictionary}
 10 		{"Password minus first character is in dictionary"; $Score--}
 11 	{($_ -match '0') -and (Select-String "^$($_.replace('0','o'))$" -Quiet -Path $dictionary)}
 12 		{"Password (replacing zero for O) is in dictionary"; $Score--}
 13 	{($_ -match '1') -and (Select-String "^$($_.replace('1','l'))$" -Quiet -Path $dictionary)}
 14 		{"Password (replacing one for l) is in dictionary"; $Score--}
 15 	{($_.length -lt 10) -or ($_.length -gt 20)}
 16 		{"Password must be between 10 and 20 characters long"; $Score--}
 17 	{!($_ -match '[0-9]')}
 18 		{"Password must include at least one digit"; $Score--}
 19 	{!($_ -cmatch '[A-Z]')}
 20 		{"Password must include at least one uppercase letter"; $Score--}
 21 	{!($_ -cmatch '[a-z]')}
 22 		{"Password must include at least one lowercase letter"; $Score--}
 23 	{!($_ -match '[^a-z0-9]')}
 24 		{"Password must include at least one symbol"; $Score--}
 25 }
 27 switch -case -regex ($p) {
 28 	'[a-z]{4,}'		{"Password includes 4 or more consecutive lowercase characters"; $Score--}
 29 	'[A-Z]{4,}'		{"Password includes 4 or more consecutive uppercase characters"; $Score--}
 30 	'(.).*\1'		{"Password includes duplicate characters"; $Score--}
 31 }
 33 $Strength=$(switch ($score) {
 34 	{$_ -le 6}	{"weak"}
 35 	{$_ -ge 11}	{"strong"}
 36 	default		{"moderately-strong"}
 37 });"Password score $score, indicating a $strength password"

First thing is to read the word list file.  Since we’re going to be using this more than once we cache the content (in $dictionary).  The first five tests are handled by select-string.  Next is a simple length check.  Then some regex checking. 

The second switch block does some further regex pattern matching, including a simple regex to check for duplicate characters:


Although this looks a bit like ascii-art (or a text-message smiley of some kind!) this actually says "Match any single character and remember what is was ‘(.)’; then match zero or more further characters ‘.*’; then match another occurrence of whatever character we matched initially ‘\1’".

This will scan along the string starting with the first character and walk up along the string checking and matching each character in turn until a character is found that occurs at least twice.  At this point, if there are duplicate characters, the regex succeeds.  Otherwise the end of the string is reached without a match and the regex fails.

The final switch block displays the result.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s