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

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
  • A length of at least six characters

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:

  • One condition met: weak password
  • Two conditions met: medium password
  • All conditions met: strong password

You can adjust the above to meet your needs.

查看更多
别忘想泡老子
3楼-- · 2019-01-10 10:16

The object-oriented approach would be a set of rules. Assign a weight to each rule and iterate through them. In psuedo-code:

abstract class Rule {

    float weight;

    float calculateScore( string password );

}

Calculating 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 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;

}
查看更多
放荡不羁爱自由
4楼-- · 2019-01-10 10:17

If you have the time, run a password cracker against it.

查看更多
聊天终结者
5楼-- · 2019-01-10 10:19

after reading the other helpful answers, this is what i'm going with:

-1 same as username
+0 contains username
+1 more than 7 chars
+1 more than 11 chars
+1 contains digits
+1 mix of lower and uppercase
+1 contains punctuation
+1 non-printable 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('[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

example usage:

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 efficient, but seems reasonable. not sure FascistCheck => 'too similar to username' is worth it.

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

maybe that should score lower.

查看更多
Viruses.
6楼-- · 2019-01-10 10:24

1: Eliminate often used passwords
Check the entered passwords against a list of often used passwords (see e.g. the top 100.000 passwords in the leaked LinkedIn password list: http://www.adeptus-mechanicus.com/codex/linkhap/combo_not.zip), make sure to include leetspeek substitutions: A@, E3, B8, S5, etc.
Remove parts of the password that hit against this list from the entered phrase, before going to part 2 below.

2: Don't force any rules on the user

The golden rule of passwords is that longer is better.
Forget about forced use of caps, numbers, and symbols because (the vast majority of) users will: - Make the first letter a capital; - Put the number 1 at the end; - Put a ! after that if a symbol is required.

Instead check password strength

For a decent starting point see: http://www.passwordmeter.com/

I suggest as a minimum the following rules:

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

Just following passwordmeter is not enough, because sure enough its naive algorithm sees Password1! as good, whereas it is exceptionally weak. Make sure to disregard initial capital letters when scoring as well as trailing numbers and symbols (as per the last 3 rules).

Calculating Shannon entropy
See: Fastest way to compute entropy in Python

3: Don't allow any passwords that are too weak
Rather 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.

And most importantly
When you accept the password and store it in a database, make sure to salt and hash it!.

查看更多
再贱就再见
7楼-- · 2019-01-10 10:24

There's the open and free John the Ripper password cracker which is a great way to check an existing password database.

查看更多
登录 后发表回答