What is the best way to check the strength of a password?

See also How do you calculate password complexity?

What is the best way to ensure that the password provided by the user is a strong password in the form of registering or changing the password?

EDIT: I have one idea (in python)

def validate_password(passwd): conditions_met = 0 conditions_total = 3 if len(passwd) >= 6: if passwd.lower() != passwd: conditions_met += 1 if len([x for x in passwd if x.isdigit()]) > 0: conditions_met += 1 if len([x for x in passwd if not x.isalnum()]) > 0: conditions_met += 1 result = False print conditions_met if conditions_met >= 2: result = True return result 
+41
security algorithm passwords
16 Sep '08 at 17:53
source share
17 answers

Depending on the language, I usually use regular expressions to check if it has:

  • At least one uppercase and one lowercase letter
  • At least one number
  • At least one special character
  • At least six characters in length

You can require all of the above or use a script type strength meter. For my strength meter, if the password is the correct length, it is evaluated as follows:

  • One condition is met: weak password
  • Two conditions: middle password
  • All conditions are met: strong password

You can customize the above to suit your needs.

+20
Sep 16 '08 at 18:02
source share
— -
+13
Sep 16 '08 at 17:56
source share

An object-oriented approach will be a set of rules. Assign weight to each rule and pass through them. In psuedo code:

 abstract class Rule { float weight; float calculateScore( string password ); } 

Calculation of the total score:

 float getPasswordStrength( string password ) { float totalWeight = 0.0f; float totalScore = 0.0f; foreach ( rule in rules ) { totalWeight += weight; totalScore += rule.calculateScore( password ) * rule.weight; } return (totalScore / totalWeight) / rules.count; } 

An example rule algorithm based on the number of character classes present:

 float calculateScore( string password ) { float score = 0.0f; // NUMBER_CLASS is a constant char array { '0', '1', '2', ... } if ( password.contains( NUMBER_CLASS ) ) score += 1.0f; if ( password.contains( UPPERCASE_CLASS ) ) score += 1.0f; if ( password.contains( LOWERCASE_CLASS ) ) score += 1.0f; // Sub rule as private method if ( containsPunctuation( password ) ) score += 1.0f; return score / 4.0f; } 
+9
Sep 16 '08 at 18:32
source share

The general algorithm is described on the wikipedia page at http://en.wikipedia.org/wiki/Random_password_generator#Stronger_methods . I also found several scripts here - http://webtecker.com/2008/03/26/collection-of-password-strength-scripts/ . Some of them are under the MIT license, so you can look at the code and find out how they calculate power. I also found entry on wikipedia.

+5
Sep 16 '08 at 18:13
source share

Two simple metrics to check:

  • Length. I would say a minimum of 8 characters.
  • The number of different character classes contained in the password. These are usually lowercase letters, uppercase letters, numbers and punctuation marks, and other characters. A strong password will contain characters from at least three of these classes; if you force a number or other non-alphabetic character, you significantly reduce the effectiveness of dictionary attacks.
+3
Sep 16 '08 at 18:04
source share

If they are not mistaken, at least once a week, when trying to log in, then he is too weak.

+3
Apr 19 '09 at 5:24
source share

after reading other useful answers, here is what I am going to:

-1, like username
+0 contains username
+1 more than 7 characters
+1 more than 11 characters
+1 contains numbers
+1 combination of lower and upper case
+1 contains punctuation
+1 non-print char

pwscore.py:

 import re import string max_score = 6 def score(username,passwd): if passwd == username: return -1 if username in passwd: return 0 score = 0 if len(passwd) > 7: score+=1 if len(passwd) > 11: score+=1 if re.search('\d+',passwd): score+=1 if re.search('[az]',passwd) and re.search('[AZ]',passwd): score+=1 if len([x for x in passwd if x in string.punctuation]) > 0: score+=1 if len([x for x in passwd if x not in string.printable]) > 0: score+=1 return score 

usage example:

 import pwscore score = pwscore(username,passwd) if score < 3: return "weak password (score=" + str(score) + "/" + str(pwscore.max_score) + "), try again." 

probably not the most effective, but seems reasonable. not sure if FascistCheck => 'too similar to username' is worth it.

'abc123ABC! @ £ '= score 6/6 if not superset of username

perhaps it should be lower.

+3
Nov 28 '10 at 19:55
source share

There is the open and free John the Ripper , which is great for checking your existing password database.

+2
Sep 16 '08 at 17:56
source share

Ok, here is what I use:

  var getStrength = function (passwd) { intScore = 0; intScore = (intScore + passwd.length); if (passwd.match(/[az]/)) { intScore = (intScore + 1); } if (passwd.match(/[AZ]/)) { intScore = (intScore + 5); } if (passwd.match(/\d+/)) { intScore = (intScore + 5); } if (passwd.match(/(\d.*\d)/)) { intScore = (intScore + 5); } if (passwd.match(/[!,@#$%^&*?_~]/)) { intScore = (intScore + 5); } if (passwd.match(/([!,@#$%^&*?_~].*[!,@#$%^&*?_~])/)) { intScore = (intScore + 5); } if (passwd.match(/[az]/) && passwd.match(/[AZ]/)) { intScore = (intScore + 2); } if (passwd.match(/\d/) && passwd.match(/\D/)) { intScore = (intScore + 2); } if (passwd.match(/[az]/) && passwd.match(/[AZ]/) && passwd.match(/\d/) && passwd.match(/[!,@#$%^&*?_~]/)) { intScore = (intScore + 2); } return intScore; } 
+2
Sep 02 '11 at 15:02
source share
+1
Sep 16 '08 at 17:55
source share

If you have time, run a password cracker with it.

+1
Sep 16 '08 at 17:55
source share

With a series of checks to ensure compliance with the minimum criteria:

  • at least 8 characters
  • contains at least one character without alphanumeric characters
  • does not match or contains username / email address etc.
  • etc.

Here's the jQuery plugin that reports password strength (haven't tried it myself): http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/

And the same is ported to PHP: http://www.alixaxel.com/wordpress/2007/06/09/php-password-strength-algorithm/

+1
Sep 16 '08 at 17:58
source share

In addition to the standard approaches for blending alpha, numeric characters and characters, I noticed that when I signed up for MyOpenId last week, the password checker tells you if your password is based on a dictionary, even if you add numbers or replace alpha with similar numbers (instead of zero, instead of "i", etc. instead of zero, "1").

I was very impressed.

+1
Sep 16 '08 at 18:30
source share

I wrote a small Javascript application. Take a look: Another password meter . You can download the source code and use / modify it under the GPL. Enjoy!

+1
Jan 12 '09 at 16:38
source share

I don’t know if anyone will find this useful, but I really liked the idea of ​​the ruleset proposed by phear, so I went and wrote a Python 2.6 rule (although it is probably compatible with 2.5):

 import re class SecurityException(Exception): pass class Rule: """Creates a rule to evaluate against a string. Rules can be regex patterns or a boolean returning function. Whether a rule is inclusive or exclusive is decided by the sign of the weight. Positive weights are inclusive, negative weights are exclusive. Call score() to return either 0 or the weight if the rule is fufilled. Raises a SecurityException if a required rule is violated. """ def __init__(self,rule,weight=1,required=False,name=u"The Unnamed Rule"): try: getattr(rule,"__call__") except AttributeError: self.rule = re.compile(rule) # If a regex, compile else: self.rule = rule # Otherwise it a function and it should be scored using it if weight == 0: return ValueError(u"Weights can not be 0") self.weight = weight self.required = required self.name = name def exclusive(self): return self.weight < 0 def inclusive(self): return self.weight >= 0 exclusive = property(exclusive) inclusive = property(inclusive) def _score_regex(self,password): match = self.rule.search(password) if match is None: if self.exclusive: # didn't match an exclusive rule return self.weight elif self.inclusive and self.required: # didn't match on a required inclusive rule raise SecurityException(u"Violation of Rule: %s by input \"%s\"" % (self.name.title(), password)) elif self.inclusive and not self.required: return 0 else: if self.inclusive: return self.weight elif self.exclusive and self.required: raise SecurityException(u"Violation of Rule: %s by input \"%s\"" % (self.name,password)) elif self.exclusive and not self.required: return 0 return 0 def score(self,password): try: getattr(self.rule,"__call__") except AttributeError: return self._score_regex(password) else: return self.rule(password) * self.weight def __unicode__(self): return u"%s (%i)" % (self.name.title(), self.weight) def __str__(self): return self.__unicode__() 

I hope someone finds this useful!

Usage example:

 rules = [ Rule("^foobar",weight=20,required=True,name=u"The Fubared Rule"), ] try: score = 0 for rule in rules: score += rule.score() except SecurityException e: print e else: print score 

DISCLAIMER: Not tested in block

+1
Dec 09 '09 at 9:00
source share

Cracklib is great, and newer packages have the Python module available to it. However, on systems that do not already have it, such as CentOS 5, I wrote a ctypes wrapper for system cryptlib. This will also work on a system that you cannot install python-libcrypt. This requires python with ctypes available, so for CentOS 5 you need to install and use the python26 package.

It also has the advantage that it can accept a username and check passwords that contain it or are essentially similar, for example, the libcrypt function "FascistGecos", but does not require the user to exist in / etc / passwd.

My ctypescracklib library is available on github

Some example uses:

 >>> FascistCheck('jafo1234', 'jafo') 'it is based on your username' >>> FascistCheck('myofaj123', 'jafo') 'it is based on your username' >>> FascistCheck('jxayfoxo', 'jafo') 'it is too similar to your username' >>> FascistCheck('cretse') 'it is based on a dictionary word' 
+1
Nov 16 '10 at 4:05
source share

Password strength checks, and if you have time + resources (it is justified only if you check more than a few passwords), use Rainbow tables.

0
Sep 16 '08 at 17:58
source share



All Articles