it-swarm.it

Qual è il modo migliore per verificare la forza di una password?

Qual è il modo migliore per garantire che una password fornita dall'utente sia una password complessa in una registrazione o un modulo di cambio password?

Un'idea che ho avuto (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
42
Ed L

1: удалить часто используемые пароли
Проверьте введенные пароли по списку часто используемых паролей (см, Например, верхние 100 000 паролей в утечке списка паролей LinkedIn:. 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 правилам).

Расчет энтропии Шеннона
См.: Самый быстрый способ вычисления энтропии in Python

3: не допускайте слишком слабых паролей
Вместо того, чтобы заставлять пользователя подчиняться саморазрушительным правилам, разрешите все, что даст достаточно высокий балл. Как высоко зависит от вашего варианта использования.

È самое главное
Когда вы принимаете пароль и сохраняете его в базе данных, не забудьте засолить и хешировать его! .

4
Johan

A seconda della lingua, di solito uso espressioni regolari per verificare se ha:

  • Almeno una lettera maiuscola e una lettera minuscola
  • Almeno un numero
  • Almeno un personaggio speciale
  • Una lunghezza di almeno sei caratteri

Puoi richiedere tutto quanto sopra o utilizzare un tipo di script per il misuratore di forza. Per il mio misuratore di forza, se la password ha la lunghezza giusta, viene valutata come segue:

  • Una condizione soddisfatta: password debole
  • Sono state soddisfatte due condizioni: password media
  • Tutte le condizioni soddisfatte: password complessa

È possibile regolare quanto sopra per soddisfare le proprie esigenze.

18
VirtuosiMedia

L'approccio orientato agli oggetti sarebbe un insieme di regole. Assegna un peso a ciascuna regola e itera attraverso di esse. In psuedo-code:

abstract class Rule {

    float weight;

    float calculateScore( string password );

}

Calcolo del punteggio totale:

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;

}

Un algoritmo di regole di esempio, basato sul numero di classi di caratteri presenti:

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;

}
9
user9116

Le due metriche più semplici da verificare sono:

  1. Lunghezza. Direi 8 caratteri come minimo.
  2. Numero di diverse classi di caratteri contenute nella password. Di solito sono lettere minuscole, lettere maiuscole, numeri e segni di punteggiatura e altri simboli. Una password sicura conterrà i caratteri di almeno tre di queste classi; se imposti un numero o un altro carattere non alfabetico, riduci in modo significativo l'efficacia degli attacchi di dizionario.
3
Dave Webb

Cracklib è fantastico, e nei pacchetti più recenti c'è un modulo Python disponibile per questo. Tuttavia, su sistemi che ancora non ce l'hanno, come CentOS 5, ho scritto un wrapper ctypes per il cryptlib di sistema. Funzionerebbe anche su un sistema che non è possibile installare python-libcrypt. It does richiede python con ctypes disponibili, quindi per CentOS 5 devi installare e usare il pacchetto python26.

Ha anche il vantaggio di poter prendere il nome utente e controllare le password che lo contengono o sono sostanzialmente simili, come la funzione "FascistGecos" di libcrypt, ma senza richiedere all'utente di esistere in/etc/passwd.

La mia libreria ctypescracklib è disponibile su github

Alcuni esempi di utilizzo:

>>> 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'
2

dopo aver letto le altre risposte utili, questo è quello che sto andando:

-1 uguale al nome utente
+ 0 contiene nome utente
+ 1 più di 7 caratteri
+ 1 più di 11 caratteri
+ 1 contiene cifre
+ 1 mix di lettere maiuscole e minuscole
+ 1 contiene segni di punteggiatura
+ 1 carattere non stampabile

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

esempio di utilizzo:

import pwscore
    score = pwscore(username,passwd)
    if score < 3:
        return "weak password (score=" 
             + str(score) + "/"
             + str(pwscore.max_score)
             + "), try again."

probabilmente non è il più efficiente, ma sembra ragionevole. non sono sicuro che FascistCheck => 'too similar to username' valga la pena.

'abc123ABC! @ £' = punteggio 6/6 se non è un superset di nome utente

forse dovrebbe segnare un punteggio più basso.

2
siznax

C'è l'open e free John the Ripper password cracker che è un ottimo modo per controllare un database di password esistente.

1
tante

Bene, questo è quello che uso:

   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;
} 
1
varun

Ho scritto una piccola applicazione Javascript. Date un'occhiata: Ancora un altro misuratore di password . Puoi scaricare il codice sorgente e usarlo/modificarlo in GPL. Divertiti!

0
ReneS

Non so se qualcuno troverà questo utile, ma mi è davvero piaciuta l'idea di un set di regole come suggerito da phear, quindi sono andato a scrivere una regola della classe Python 2.6 (anche se probabilmente è compatibile con 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__()

Spero che qualcuno lo trovi utile!

Esempio di utilizzo:

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

DICHIARAZIONE DI NON RESPONSABILITÀ: nessuna unità testata

0
SapphireSun

Oltre all'approccio standard di mixare alfa, numerico e simboli, ho notato che quando mi sono registrato con MyOpenId la scorsa settimana, il verificatore della password ti dice se la tua password è basata su un dizionario Word, anche se aggiungi numeri o sostituisci alpha con numeri simili (usando zero invece di "o", "1" invece di "i", ecc.).

Sono rimasto molto colpito.

0
Steve Morgan