What is the best way to check the strength of a pa

2019-01-10 09:52发布

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

One idea I had (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

15条回答
地球回转人心会变
2楼-- · 2019-01-10 10:05

In addition to the standard approach of mixing alpha,numeric and symbols, I noticed when I registered with MyOpenId last week, the password checker tells you if your password is based on a dictionary word, even if you add numbers or replace alphas with similar numbers (using zero instead of 'o', '1' instead of 'i', etc.).

I was quite impressed.

查看更多
Emotional °昔
3楼-- · 2019-01-10 10:08

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 does require python with ctypes available, so for CentOS 5 you have to install and use the python26 package.

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.

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'
查看更多
家丑人穷心不美
4楼-- · 2019-01-10 10:10

The two simplest metrics to check for are:

  1. Length. I'd say 8 characters as a minimum.
  2. 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.
查看更多
在下西门庆
5楼-- · 2019-01-10 10:10

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):

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's 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!

Example Usage:

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 unit tested

查看更多
闹够了就滚
6楼-- · 2019-01-10 10:10

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

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 gets you situations like this. 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.

查看更多
【Aperson】
7楼-- · 2019-01-10 10:11

With a series of checks to ensure it meets minimum criteria:

  • at least 8 characters long
  • contains at least one non-alphanumeric symbol
  • does not match or contain username/email/etc.
  • etc

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

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

查看更多
登录 后发表回答