<p>What is the best way of ensuring that a user supplied password is a strong password in a registration or change password form?</p>

<p>One idea I had (in python)</p>

<pre><code>def validate_password(passwd):
    conditions_met = 0
    conditions_total = 3
    if len(passwd) &gt;= 6: 
        if passwd.lower() != passwd: conditions_met += 1
        if len([x for x in passwd if x.isdigit()]) &gt; 0: conditions_met += 1
        if len([x for x in passwd if not x.isalnum()]) &gt; 0: conditions_met += 1
    result = False
    print conditions_met
    if conditions_met &gt;= 2: result = True
    return result
</code></pre>

[{'answer_id': 75108, 'author': 'Mostlyharmless', 'author_id': 12881, 'author_profile': 'https://Stackoverflow.com/users/12881', 'pm_score': -1, 'selected': False, 'text': '<p>Password strength checkers, and if you have time+resources (its justified only if you are checking for more than a few passwords) use Rainbow Tables.</p>\n'}, {'answer_id': 75109, 'author': 'Peter Boughton', 'author_id': 9360, 'author_profile': 'https://Stackoverflow.com/users/9360', 'pm_score': -1, 'selected': False, 'text': '<p>With a series of checks to ensure it meets minimum criteria:<ul>\n<li>at least 8 characters long</li>\n<li>contains at least one non-alphanumeric symbol</li>\n<li>does not match or contain username/email/etc.</li>\n<li>etc</li>\n</ul></p>\n\n<p>Here\'s a jQuery plugin that reports password strength (not tried it myself):\n<a href="http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/" rel="nofollow noreferrer">http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/</a></p>\n\n<p>And the same thing ported to PHP:\n<a href="http://www.alixaxel.com/wordpress/2007/06/09/php-password-strength-algorithm/" rel="nofollow noreferrer">http://www.alixaxel.com/wordpress/2007/06/09/php-password-strength-algorithm/</a></p>\n'}, {'answer_id': 75149, 'author': 'VirtuosiMedia', 'author_id': 13281, 'author_profile': 'https://Stackoverflow.com/users/13281', 'pm_score': 4, 'selected': False, 'text': '<p>Depending on the language, I usually use regular expressions to check if it has:</p>\n\n<ul>\n<li>At least one uppercase and one\nlowercase letter</li>\n<li>At least one number</li>\n<li>At least one special character</li>\n<li>A length of at least six characters</li>\n</ul>\n\n<p>You can require all of the above, or use a strength meter type of script. For my strength meter, if the password has the right length, it is evaluated as follows:</p>\n\n<ul>\n<li>One condition met: weak password</li>\n<li>Two conditions met: medium password</li>\n<li>All conditions met: strong password</li>\n</ul>\n\n<p>You can adjust the above to meet your needs.</p>\n'}, {'answer_id': 75173, 'author': 'David Webb', 'author_id': 3171, 'author_profile': 'https://Stackoverflow.com/users/3171', 'pm_score': 2, 'selected': False, 'text': "<p>The two simplest metrics to check for are:</p>\n\n<ol>\n<li>Length.  I'd say 8 characters as a minimum.</li>\n<li>Number of different character classes the password contains.  These are usually, lowercase letters, uppercase letters, numbers and punctuation and other symbols.  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.</li>\n</ol>\n"}, {'answer_id': 75498, 'author': 'user9116', 'author_id': 9116, 'author_profile': 'https://Stackoverflow.com/users/9116', 'pm_score': 3, 'selected': False, 'text': "<p>The object-oriented approach would be a set of rules. Assign a weight to each rule and iterate through them. In psuedo-code:</p>\n\n<pre><code>abstract class Rule {\n\n    float weight;\n\n    float calculateScore( string password );\n\n}\n</code></pre>\n\n<p>Calculating the total score:</p>\n\n<pre><code>float getPasswordStrength( string password ) {     \n\n    float totalWeight = 0.0f;\n    float totalScore  = 0.0f;\n\n    foreach ( rule in rules ) {\n\n       totalWeight += weight;\n       totalScore  += rule.calculateScore( password ) * rule.weight;\n\n    }\n\n    return (totalScore / totalWeight) / rules.count;\n\n}\n</code></pre>\n\n<p>An example rule algorithm, based on number of character classes present:</p>\n\n<pre><code>float calculateScore( string password ) {\n\n    float score = 0.0f;\n\n    // NUMBER_CLASS is a constant char array { '0', '1', '2', ... }\n    if ( password.contains( NUMBER_CLASS ) )\n        score += 1.0f;\n\n    if ( password.contains( UPPERCASE_CLASS ) )\n        score += 1.0f;\n\n    if ( password.contains( LOWERCASE_CLASS ) )\n        score += 1.0f;\n\n    // Sub rule as private method\n    if ( containsPunctuation( password ) )\n        score += 1.0f;\n\n    return score / 4.0f;\n\n}\n</code></pre>\n"}, {'answer_id': 1872514, 'author': 'SapphireSun', 'author_id': 210920, 'author_profile': 'https://Stackoverflow.com/users/210920', 'pm_score': 0, 'selected': False, 'text': '<p>I don\'t know if anyone will find this useful, but I really liked the idea of a ruleset as suggested by phear so I went and wrote a rule Python 2.6 class (although it\'s probably compatible with 2.5):</p>\n\n<pre><code>import re\n\nclass SecurityException(Exception):\n    pass\n\nclass Rule:\n    """Creates a rule to evaluate against a string.\n    Rules can be regex patterns or a boolean returning function.\n    Whether a rule is inclusive or exclusive is decided by the sign\n    of the weight. Positive weights are inclusive, negative weights are\n    exclusive. \n\n\n    Call score() to return either 0 or the weight if the rule \n    is fufilled. \n\n    Raises a SecurityException if a required rule is violated.\n    """\n\n    def __init__(self,rule,weight=1,required=False,name=u"The Unnamed Rule"):\n        try:\n            getattr(rule,"__call__")\n        except AttributeError:\n            self.rule = re.compile(rule) # If a regex, compile\n        else:\n            self.rule = rule  # Otherwise it\'s a function and it should be scored using it\n\n        if weight == 0:\n            return ValueError(u"Weights can not be 0")\n\n        self.weight = weight\n        self.required = required\n        self.name = name\n\n    def exclusive(self):\n        return self.weight &lt; 0\n    def inclusive(self):\n        return self.weight &gt;= 0\n    exclusive = property(exclusive)\n    inclusive = property(inclusive)\n\n    def _score_regex(self,password):\n        match = self.rule.search(password)\n        if match is None:\n            if self.exclusive: # didn\'t match an exclusive rule\n                return self.weight\n            elif self.inclusive and self.required: # didn\'t match on a required inclusive rule\n                raise SecurityException(u"Violation of Rule: %s by input \\"%s\\"" % (self.name.title(), password))\n            elif self.inclusive and not self.required:\n                return 0\n        else:\n            if self.inclusive:\n                return self.weight\n            elif self.exclusive and self.required:\n                raise SecurityException(u"Violation of Rule: %s by input \\"%s\\"" % (self.name,password))\n            elif self.exclusive and not self.required:\n                return 0\n\n        return 0\n\n    def score(self,password):\n        try:\n            getattr(self.rule,"__call__")\n        except AttributeError:\n            return self._score_regex(password)\n        else:\n            return self.rule(password) * self.weight\n\n    def __unicode__(self):\n        return u"%s (%i)" % (self.name.title(), self.weight)\n\n    def __str__(self):\n        return self.__unicode__()\n</code></pre>\n\n<p>I hope someone finds this useful!</p>\n\n<p>Example Usage:</p>\n\n<pre><code>rules = [ Rule("^foobar",weight=20,required=True,name=u"The Fubared Rule"), ]\ntry:\n    score = 0\n    for rule in rules:\n        score += rule.score()\nexcept SecurityException e:\n    print e \nelse:\n    print score\n</code></pre>\n\n<p>DISCLAIMER: Not unit tested</p>\n'}, {'answer_id': 4191130, 'author': 'Sean Reifschneider', 'author_id': 267126, 'author_profile': 'https://Stackoverflow.com/users/267126', 'pm_score': 2, 'selected': False, 'text': '<p>Cracklib is great, and in newer packages there is a Python module available for it.  However, on systems that don\'t yet have it, such as CentOS 5, I\'ve written a ctypes wrapper for the system cryptlib.  This would also work on a system that you can\'t install python-libcrypt.  It <em>does</em> require python with ctypes available, so for CentOS 5 you have to install and use the python26 package.</p>\n\n<p>It also has the advantage that it can take the username and check for passwords that contain it or are substantially similar, like the libcrypt "FascistGecos" function but without requiring the user to exist in /etc/passwd.</p>\n\n<p>My <a href="http://github.com/linsomniac/python-ctypescracklib" rel="nofollow">ctypescracklib library is available on github</a></p>\n\n<p>Some example uses:</p>\n\n<pre><code>&gt;&gt;&gt; FascistCheck(\'jafo1234\', \'jafo\')\n\'it is based on your username\'\n&gt;&gt;&gt; FascistCheck(\'myofaj123\', \'jafo\')\n\'it is based on your username\'\n&gt;&gt;&gt; FascistCheck(\'jxayfoxo\', \'jafo\')\n\'it is too similar to your username\'\n&gt;&gt;&gt; FascistCheck(\'cretse\')\n\'it is based on a dictionary word\'\n</code></pre>\n'}, {'answer_id': 4298717, 'author': 'siznax', 'author_id': 59037, 'author_profile': 'https://Stackoverflow.com/users/59037', 'pm_score': 2, 'selected': False, 'text': '<p>after reading the other helpful answers, this is what i\'m going with:</p>\n\n<p>-1 same as username<br>\n+0 contains username<br>\n+1 more than 7 chars<br>\n+1 more than 11 chars<br>\n+1 contains digits<br>\n+1 mix of lower and uppercase<br>\n+1 contains punctuation<br>\n+1 non-printable char  </p>\n\n<p>pwscore.py:</p>\n\n<pre><code>import re\nimport string\nmax_score = 6\ndef score(username,passwd):\n    if passwd == username:\n        return -1\n    if username in passwd:\n        return 0\n    score = 0\n    if len(passwd) &gt; 7:\n        score+=1\n    if len(passwd) &gt; 11:\n        score+=1\n    if re.search(\'\\d+\',passwd):\n        score+=1\n    if re.search(\'[a-z]\',passwd) and re.search(\'[A-Z]\',passwd):\n        score+=1\n    if len([x for x in passwd if x in string.punctuation]) &gt; 0:\n        score+=1\n    if len([x for x in passwd if x not in string.printable]) &gt; 0:\n        score+=1\n    return score\n</code></pre>\n\n<p>example usage:</p>\n\n<pre><code>import pwscore\n    score = pwscore(username,passwd)\n    if score &lt; 3:\n        return "weak password (score=" \n             + str(score) + "/"\n             + str(pwscore.max_score)\n             + "), try again."\n</code></pre>\n\n<p>probably not the most efficient, but seems reasonable. \nnot sure FascistCheck => \'too similar to username\' is \nworth it.</p>\n\n<p>\'abc123ABC!@£\' = score 6/6 if not a superset of username</p>\n\n<p>maybe that should score lower.</p>\n'}, {'answer_id': 7285380, 'author': 'varun', 'author_id': 95967, 'author_profile': 'https://Stackoverflow.com/users/95967', 'pm_score': 1, 'selected': False, 'text': '<p>Well this is what I use:</p>\n\n<pre><code>   var getStrength = function (passwd) {\n    intScore = 0;\n    intScore = (intScore + passwd.length);\n    if (passwd.match(/[a-z]/)) {\n        intScore = (intScore + 1);\n    }\n    if (passwd.match(/[A-Z]/)) {\n        intScore = (intScore + 5);\n    }\n    if (passwd.match(/\\d+/)) {\n        intScore = (intScore + 5);\n    }\n    if (passwd.match(/(\\d.*\\d)/)) {\n        intScore = (intScore + 5);\n    }\n    if (passwd.match(/[!,@#$%^&amp;*?_~]/)) {\n        intScore = (intScore + 5);\n    }\n    if (passwd.match(/([!,@#$%^&amp;*?_~].*[!,@#$%^&amp;*?_~])/)) {\n        intScore = (intScore + 5);\n    }\n    if (passwd.match(/[a-z]/) &amp;&amp; passwd.match(/[A-Z]/)) {\n        intScore = (intScore + 2);\n    }\n    if (passwd.match(/\\d/) &amp;&amp; passwd.match(/\\D/)) {\n        intScore = (intScore + 2);\n    }\n    if (passwd.match(/[a-z]/) &amp;&amp; passwd.match(/[A-Z]/) &amp;&amp; passwd.match(/\\d/) &amp;&amp; passwd.match(/[!,@#$%^&amp;*?_~]/)) {\n        intScore = (intScore + 2);\n    }\n    return intScore;\n} \n</code></pre>\n'}, {'answer_id': 50489987, 'author': 'Johan', 'author_id': 650492, 'author_profile': 'https://Stackoverflow.com/users/650492', 'pm_score': 4, 'selected': True, 'text': '<p><strong>1: Eliminate often used passwords</strong><br>\nCheck the entered passwords against a list of often used passwords (see e.g. the top 100.000 passwords in the leaked LinkedIn password list: <a href="http://www.adeptus-mechanicus.com/codex/linkhap/combo_not.zip" rel="noreferrer">http://www.adeptus-mechanicus.com/codex/linkhap/combo_not.zip</a>), make sure to include <a href="http://www.gamehouse.com/blog/leet-speak-cheat-sheet/" rel="noreferrer">leetspeek substitutions</a>:\nA@, E3, B8, S5, etc.<br>\nRemove parts of the password that hit against this list from the entered phrase, before going to part 2 below.</p>\n\n<p><strong>2: Don\'t force any rules on the user</strong>  </p>\n\n<p>The golden rule of passwords is that longer is better.<br>\nForget about forced use of caps, numbers, and symbols because (the vast majority of) users will:\n- Make the first letter a capital;\n- Put the number <code>1</code> at the end;\n- Put a <code>!</code> after that if a symbol is required.</p>\n\n<p><strong>Instead check password strength</strong>  </p>\n\n<p>For a decent starting point see: <a href="http://www.passwordmeter.com/" rel="noreferrer">http://www.passwordmeter.com/</a> </p>\n\n<p>I suggest as a minimum the following rules:</p>\n\n<pre><code>Additions (better passwords)\n-----------------------------\n- Number of Characters              Flat       +(n*4)   \n- Uppercase Letters                 Cond/Incr  +((len-n)*2)     \n- Lowercase Letters                 Cond/Incr  +((len-n)*2)     \n- Numbers                           Cond       +(n*4)   \n- Symbols                           Flat       +(n*6)\n- Middle Numbers or Symbols         Flat       +(n*2)   \n- Shannon Entropy                   Complex    *EntropyScore\n\nDeductions (worse passwords)\n----------------------------- \n- Letters Only                      Flat       -n   \n- Numbers Only                      Flat       -(n*16)  \n- Repeat Chars (Case Insensitive)   Complex    -    \n- Consecutive Uppercase Letters     Flat       -(n*2)   \n- Consecutive Lowercase Letters     Flat       -(n*2)   \n- Consecutive Numbers               Flat       -(n*2)   \n- Sequential Letters (3+)           Flat       -(n*3)   \n- Sequential Numbers (3+)           Flat       -(n*3)   \n- Sequential Symbols (3+)           Flat       -(n*3)\n- Repeated words                    Complex    -       \n- Only 1st char is uppercase        Flat       -n\n- Last (non symbol) char is number  Flat       -n\n- Only last char is symbol          Flat       -n\n</code></pre>\n\n<p>Just following <a href="http://www.passwordmeter.com/" rel="noreferrer">passwordmeter</a> is not enough, because sure enough its naive algorithm sees <kbd>Password1!</kbd> as good, whereas it is exceptionally weak.\nMake sure to disregard initial capital letters when scoring as well as trailing numbers and symbols (as per the last 3 rules).</p>\n\n<p><strong>Calculating Shannon entropy</strong><br>\nSee: <a href="https://stackoverflow.com/questions/15450192/fastest-way-to-compute-entropy-in-python">Fastest way to compute entropy in Python</a></p>\n\n<p><strong>3: Don\'t allow any passwords that are too weak</strong><br>\nRather than forcing the user to bend to self-defeating rules, allow anything that will give a high enough score. How high depends on your use case. </p>\n\n<p><strong>And most importantly</strong><br>\nWhen you accept the password and store it in a database, <a href="https://stackoverflow.com/questions/4578431/how-to-hash-and-salt-passwords">make sure to salt and hash it!</a>.</p>\n'}, {'answer_id': 54055977, 'author': 'Braiam', 'author_id': 792066, 'author_profile': 'https://Stackoverflow.com/users/792066', 'pm_score': -1, 'selected': False, 'text': '<blockquote>\n  <p>What is the best way of ensuring that a user supplied password is a strong password in a registration or change password form?</p>\n</blockquote>\n\n<p>Don\'t evaluate complexity and or strength, users will find a way to fool your system or get so frustrated that they will leave. That will only get you situations <a href="https://xkcd.com/936/" rel="nofollow noreferrer">like this</a>. Just require certain length and that leaked passwords aren\'t used. Bonus points: make sure whatever you implement allows the use of password managers and/or 2FA.</p>\n'}]
['https://Stackoverflow.com/questions/75057', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/13099/']