사용자 제공 암호가 등록 또는 암호 변경 양식에서 강력한 암호인지 확인하는 가장 좋은 방법은 무엇입니까?
내가 가진 하나의 아이디어 (파이썬)
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
1 : 자주 사용하는 암호 제거
자주 사용하는 비밀번호 목록과 비교하여 입력 한 비밀번호를 확인합니다 (예 : 유출 된 LinkedIn 비밀번호 목록에서 상위 100.000 개 비밀번호 참조 : http://www.adeptus-mechanicus.com/codex/linkhap/) combo_not.Zip ), leetspeek 대체 : A @, E3, B8, S5 등을 포함해야합니다.
아래 파트 2로 이동하기 전에 입력 된 구문에서이 목록에 대해 적중 된 비밀번호의 일부를 제거하십시오.
2 : 사용자에게 어떤 규칙도 강제하지 마십시오
암호의 황금률은 길수록 좋습니다.
대부분의 사용자가 다음을 수행하기 때문에 대문자, 숫자 및 기호를 강제로 사용하지 마십시오.-첫 글자를 대문자로 만듭니다. -끝에 숫자 1
를 입력하세요. -기호가 필요한 경우 그 뒤에 !
를 입력합니다.
대신 비밀번호 안전성 확인
적절한 시작점은 다음을 참조하십시오 : http://www.passwordmeter.com/
최소한 다음 규칙을 제안합니다.
Additions (better passwords)
-----------------------------
- Number of Characters Flat +(n*4)
- Uppercase Letters Cond/Incr +((len-n)*2)
- Lowercase Letters Cond/Incr +((len-n)*2)
- Numbers Cond +(n*4)
- Symbols Flat +(n*6)
- Middle Numbers or Symbols Flat +(n*2)
- Shannon Entropy Complex *EntropyScore
Deductions (worse passwords)
-----------------------------
- Letters Only Flat -n
- Numbers Only Flat -(n*16)
- Repeat Chars (Case Insensitive) Complex -
- Consecutive Uppercase Letters Flat -(n*2)
- Consecutive Lowercase Letters Flat -(n*2)
- Consecutive Numbers Flat -(n*2)
- Sequential Letters (3+) Flat -(n*3)
- Sequential Numbers (3+) Flat -(n*3)
- Sequential Symbols (3+) Flat -(n*3)
- Repeated words Complex -
- Only 1st char is uppercase Flat -n
- Last (non symbol) char is number Flat -n
- Only last char is symbol Flat -n
passwordmeter 를 따르는 것만으로는 충분하지 않습니다. Password1! 매우 약하지만 매우 약합니다. 점수를 매길 때 첫 번째 대문자와 후행 숫자 및 기호를 무시하십시오 (마지막 3 개 규칙에 따라).
섀넌 엔트로피 계산
참조 : 파이썬에서 엔트로피를 계산하는 가장 빠른 방법
3 : 너무 약한 암호를 허용하지 마십시오
사용자가 자멸적인 규칙을 따르도록 강요하지 말고 충분한 점수를 줄 수있는 모든 것을 허용하십시오. 얼마나 높은지는 사용 사례에 따라 다릅니다.
그리고 가장 중요한 것은
암호를 수락하고 데이터베이스에 저장하면 솔트하고 해시해야합니다! .
언어에 따라 일반적으로 정규식을 사용하여 다음이 있는지 확인합니다.
위의 모든 것을 요구하거나 강도 측정기 유형의 스크립트를 사용할 수 있습니다. 내 강도 측정기의 경우 암호 길이가 올바른 경우 다음과 같이 평가됩니다.
필요에 따라 위의 내용을 조정할 수 있습니다.
객체 지향 접근 방식은 일련의 규칙입니다. 각 규칙에 가중치를 할당하고이를 반복합니다. 의사 코드에서 :
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;
}
존재하는 문자 클래스 수를 기반으로하는 예제 규칙 알고리즘 :
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;
}
확인해야 할 가장 간단한 두 가지 측정 항목은 다음과 같습니다.
Cracklib는 훌륭하며 최신 패키지에는 사용할 수있는 Python 모듈이 있습니다. 그러나 CentOS 5와 같이 아직 모듈이없는 시스템에서는 ctypes 래퍼를 작성했습니다. 시스템 cryptlib의 경우. 이것은 python-libcrypt를 설치할 수없는 시스템에서도 작동합니다. does require 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'
다른 유용한 답변을 읽은 후 다음과 같이하겠습니다.
-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('[a-z]',passwd) and re.search('[A-Z]',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 점
점수가 더 낮을 것입니다.
개방적이고 무료 인 John the Ripper 기존 암호 데이터베이스를 확인하는 좋은 방법 인 암호 크래커가 있습니다.
글쎄, 이것이 내가 사용하는 것입니다.
var getStrength = function (passwd) {
intScore = 0;
intScore = (intScore + passwd.length);
if (passwd.match(/[a-z]/)) {
intScore = (intScore + 1);
}
if (passwd.match(/[A-Z]/)) {
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(/[a-z]/) && passwd.match(/[A-Z]/)) {
intScore = (intScore + 2);
}
if (passwd.match(/\d/) && passwd.match(/\D/)) {
intScore = (intScore + 2);
}
if (passwd.match(/[a-z]/) && passwd.match(/[A-Z]/) && passwd.match(/\d/) && passwd.match(/[!,@#$%^&*?_~]/)) {
intScore = (intScore + 2);
}
return intScore;
}
작은 자바 스크립트 애플리케이션을 작성했습니다. 보세요 : Yet Another Password Meter . 소스를 다운로드하고 GPL에서 사용/수정할 수 있습니다. 즐기세요!
누구도이 기능이 유용하다고 생각할지 모르겠지만 phear가 제안한 규칙 세트 아이디어가 마음에 들었 기 때문에 규칙을 작성했습니다. 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
면책 조항 : 단위 테스트되지 않음
알파벳, 숫자 및 기호를 혼합하는 표준 접근 방식 외에도 지난주에 MyOpenId에 등록했을 때 비밀번호 검사기가 숫자를 추가하거나 알파벳을 비슷한 숫자로 바꾸더라도 비밀번호가 사전 Word를 기반으로하는지 알려줍니다. ( 'o'대신 0 사용, 'i'대신 '1'사용).
나는 매우 감동했습니다.