检查密码强度的最佳方法是什么?
另请参见如何计算密码复杂性?
确保用户提供密码的最好方法是在注册或更改密码表单时使用强密码?
编辑:我有一个想法(在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
根据不同的语言,我通常使用正则expression式来检查它是否有:
- 至less有一个大写字母和一个小写字母
- 至less有一个号码
- 至less有一个特殊字符
- 长度至less为六个字符
您可以要求以上所有内容,或使用力量计types的脚本。 对于我的力量计,如果密码长度合适,评估如下:
- 满足一个条件:弱密码
- 满足两个条件:中等密码
- 所有条件都符合:强密码
您可以调整以上以满足您的需求。
面向对象的方法将是一组规则。 为每个规则分配一个权重并遍历它们。 在伪代码中:
abstract class Rule { float weight; float calculateScore( string password ); }
计算总分:
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; }
一个示例规则algorithm,基于字符类的数量:
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; }
一般algorithm在维基百科页面( http://en.wikipedia.org/wiki/Random_password_generator#Stronger_methods )中概述。 我还在这里find了几个脚本 – http://webtecker.com/2008/03/26/collection-of-password-strength-scripts/ 。 其中一些是在MIT的许可下,所以你可以看看代码,并找出他们如何计算实力。 我发现维基百科条目也有帮助。
要检查的两个最简单的指标是:
- 长度。 我会说至less8个字符。
- 密码包含的不同字符类的数量。 这些通常是小写字母,大写字母,数字和标点符号等。 强密码将包含至less三个这些类的字符; 如果您强制使用数字或其他非字母字符,则会显着降低字典攻击的有效性。
如果他们每周至less一次都没有弄错,在尝试login的时候就太弱了。
在阅读其他有用的答案之后,这就是我要做的事情:
-1与用户名相同
+0包含用户名
+1超过7个字符
+1超过11个字符
+1包含数字
小写字母和大写字母+1混合
+1包含标点符号
+1不可打印的字符
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
示例用法:
import pwscore score = pwscore(username,passwd) if score < 3: return "weak password (score=" + str(score) + "/" + str(pwscore.max_score) + "), try again."
可能不是最有效的,但似乎是合理的。 不确定FascistCheck =>“与用户名太相似”是值得的。
'abc123ABC!@£'=如果不是用户名的超集,则得分6/6
也许这应该得分较低。
有开放和免费的约翰开膛手密码破解者这是一个伟大的方式来检查现有的密码数据库。
那么这是我使用的:
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; }
我喜欢使用微软的密码检查器
如果你有时间的话,运行一个密码破解者。
通过一系列检查来确保它符合最低标准:
- 至less8个字符
- 包含至less一个非字母数字符号
- 不匹配或包含用户名/电子邮件/等。
- 等等
这是一个报告密码强度的jQuery插件(不是自己尝试的): http : //phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
同样的东西移植到PHP: http : //www.alixaxel.com/wordpress/2007/06/09/php-password-strength-algorithm/
除了混合字母,数字和符号的标准方法之外,我注意到上周在MyOpenId注册时,密码检查器会告诉您密码是否基于字典单词,即使您添加数字或用相似的数字replace字母(使用零而不是“o”,“1”而不是“i”等)。
我印象深刻。
我写了一个小的Javascript应用程序。 看看: 另一个密码表 。 您可以下载源代码并在GPL下使用/修改它。 玩的开心!
我不知道是否有人会发现这个有用,但我真的很喜欢phearbuild议的规则集的想法,所以我去写了一个规则Python 2.6类(虽然它可能与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__()
我希望有人认为这有用!
用法示例:
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
免责声明:未经unit testing
Cracklib非常好,在新的包里有一个可用的Python模块。 但是,在还没有它的系统上,比如CentOS 5,我已经为系统cryptlib写了一个ctypes包装器。 这也适用于你不能安装python-libcrypt的系统。 它确实需要python与ctypes可用,所以对于CentOS 5你必须安装和使用python26包。
它还具有可以取用户名和检查包含它的密码或类似的密码的优点,如libcrypt“FascistGecos”函数,但不需要用户存在于/ etc / passwd中。
我的ctypescracklib库在github上可用
一些示例使用:
>>> 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'
密码强度检查器,如果您有时间+资源(只有在检查多个密码的情况下才合理),请使用彩虹表。