Dopo aver letto varie risorse sulla sicurezza delle password, sto cercando di creare un algoritmo che fornirà una stima approssimativa di quanta entropia ha una password.
Sto cercando di creare un algoritmo il più completo possibile. A questo punto ho solo pseudocodice, ma l'algoritmo copre quanto segue:
- lunghezza della password
- personaggi ripetuti
- modelli (logici)
- spazi caratteri diversi (LC, UC, Numerico, Speciale, Esteso)
- attacchi al dizionario
NON copre quanto segue e DOVREBBE coprirlo BENE (anche se non perfettamente):
- ordinamento (le password possono essere ordinate rigorosamente dall'output di questo algoritmo)
- modelli (spaziali)
Qualcuno può fornire qualche idea su cosa potrebbe essere debole questo algoritmo? In particolare, qualcuno può pensare a situazioni in cui fornire una password all'algoritmo ne sopravvaluterebbe la forza? Le sottostime sono meno problematiche.
L'algoritmo:
// the password to test
password = ?
length = length(password)
// unique character counts from password (duplicates discarded)
uqlca = number of unique lowercase alphabetic characters in password
uquca = number of uppercase alphabetic characters
uqd = number of unique digits
uqsp = number of unique special characters (anything with a key on the keyboard)
uqxc = number of unique special special characters (alt codes, extended-ascii stuff)
// algorithm parameters, total sizes of alphabet spaces
Nlca = total possible number of lowercase letters (26)
Nuca = total uppercase letters (26)
Nd = total digits (10)
Nsp = total special characters (32 or something)
Nxc = total extended ascii characters that dont fit into other categorys (idk, 50?)
// algorithm parameters, pw strength growth rates as percentages (per character)
flca = entropy growth factor for lowercase letters (.25 is probably a good value)
fuca = EGF for uppercase letters (.4 is probably good)
fd = EGF for digits (.4 is probably good)
fsp = EGF for special chars (.5 is probably good)
fxc = EGF for extended ascii chars (.75 is probably good)
// repetition factors. few unique letters == low factor, many unique == high
rflca = (1 - (1 - flca) ^ uqlca)
rfuca = (1 - (1 - fuca) ^ uquca)
rfd = (1 - (1 - fd ) ^ uqd )
rfsp = (1 - (1 - fsp ) ^ uqsp )
rfxc = (1 - (1 - fxc ) ^ uqxc )
// digit strengths
strength =
( rflca * Nlca +
rfuca * Nuca +
rfd * Nd +
rfsp * Nsp +
rfxc * Nxc ) ^ length
entropybits = log_base_2(strength)
Alcuni input e output entropy_bits desiderati ed effettivi:
INPUT DESIRED ACTUAL
aaa very pathetic 8.1
aaaaaaaaa pathetic 24.7
abcdefghi weak 31.2
H0ley$Mol3y_ strong 72.2
s^fU¬5ü;y34G< wtf 88.9
[a^36]* pathetic 97.2
[a^20]A[a^15]* strong 146.8
xkcd1** medium 79.3
xkcd2** wtf 160.5
* these 2 passwords use shortened notation, where [a^N] expands to N a's.
** xkcd1 = "Tr0ub4dor&3", xkcd2 = "correct horse battery staple"
L'algoritmo si rende conto (correttamente) che l'aumento della dimensione dell'alfabeto (anche di una cifra) rafforza notevolmente le password lunghe, come mostrato dalla differenza in entropy_bits per le password 6a e 7a, che sono entrambe costituite da 36 a, ma la 21a a seconda è capitalizzati. Tuttavia, non tengono conto del fatto che avere una password di 36 a non è una buona idea, si rompe facilmente con un cracker di password debole (e chiunque ti guardi mentre lo digita lo vedrà) e l'algoritmo non riflette che .
Tuttavia, riflette il fatto che xkcd1 è una password debole rispetto a xkcd2, nonostante abbia una maggiore densità di complessità (è anche una cosa?).
Come posso migliorare questo algoritmo?
Addendum 1
Gli attacchi a dizionario e gli attacchi basati su schemi sembrano essere la cosa più importante, quindi mi prenderò cura di affrontarli.
Potrei eseguire una ricerca completa attraverso la password per le parole da un elenco di parole e sostituire le parole con token unici per le parole che rappresentano. I token di parole verrebbero quindi trattati come caratteri e dotati di un proprio sistema di pesi e aggiungere i propri pesi alla password. Avrei bisogno di alcuni nuovi parametri dell'algoritmo (li chiamerò lw, Nw ~ = 2 ^ 11, fw ~ = .5 e rfw) e calcolerei il peso nella password come farei con qualsiasi altro pesi.
Questa ricerca di parole potrebbe essere appositamente modificata per abbinare sia lettere minuscole che maiuscole e sostituzioni di caratteri comuni, come quella di E con 3. Se non aggiungessi maggior peso a tali parole abbinate, l'algoritmo ne sottovaluterebbe un po 'la forza o due per parola, il che è OK. Altrimenti, una regola generale sarebbe, per ogni partita non perfetta del personaggio, dare alla parola un po 'di bonus.
Potrei quindi eseguire semplici controlli del modello, come ricerche di esecuzioni di caratteri ripetuti e test derivati (prendere la differenza tra ciascun carattere), che identificherebbe modelli come "aaaaa" e "12345" e sostituire ogni modello rilevato con un modello token, unico per il modello e la lunghezza. I parametri algoritmici (in particolare, entropia per modello) potrebbero essere generati al volo in base al modello.
A questo punto, prenderei la lunghezza della password. Ogni token di parola e token modello conterebbe come un carattere; ogni token sostituirà i caratteri che rappresentano simbolicamente.
Ho creato una sorta di notazione del motivo, ma include la lunghezza del motivo l, l'ordine del motivo oe l'elemento base b. Queste informazioni potrebbero essere utilizzate per calcolare un peso arbitrario per ciascun modello. Farei qualcosa di meglio nel codice reale.
Esempio modificato:
Password: 1234kitty$$$$$herpderp
Tokenized: 1 2 3 4 k i t t y $ $ $ $ $ h e r p d e r p
Words Filtered: 1 2 3 4 @W5783 $ $ $ $ $ @W9001 @W9002
Patterns Filtered: @P[l=4,o=1,b='1'] @W5783 @P[l=5,o=0,b='$'] @W9001 @W9002
Breakdown: 3 small, unique words and 2 patterns
Entropy: about 45 bits, as per modified algorithm
Password: correcthorsebatterystaple
Tokenized: c o r r e c t h o r s e b a t t e r y s t a p l e
Words Filtered: @W6783 @W7923 @W1535 @W2285
Breakdown: 4 small, unique words and no patterns
Entropy: 43 bits, as per modified algorithm
La semantica esatta di come l'entropia viene calcolata da schemi è in discussione. Stavo pensando a qualcosa del tipo:
entropy(b) * l * (o + 1) // o will be either zero or one
L'algoritmo modificato troverebbe difetti con e ridurrebbe la forza di ogni password nella tabella originale, ad eccezione di s^fU¬5ü;y34G<
, che non contiene parole o schemi.