Depois de ler vários recursos sobre a força da senha, estou tentando criar um algoritmo que fornecerá uma estimativa aproximada de quanta entropia uma senha possui.
Estou tentando criar um algoritmo o mais abrangente possível. Neste ponto, só tenho pseudocódigo, mas o algoritmo cobre o seguinte:
- comprimento da senha
- caracteres repetidos
- padrões (lógicos)
- espaços de caracteres diferentes (LC, UC, Numérico, Especial, Estendido)
- ataques de dicionário
NÃO cobre o seguinte, e DEVE ABRIR BEM (embora não perfeitamente):
- ordenação (as senhas podem ser estritamente ordenadas pela saída desse algoritmo)
- padrões (espaciais)
Alguém pode fornecer algumas dicas sobre o que esse algoritmo pode ser fraco? Especificamente, alguém pode pensar em situações em que a alimentação de uma senha ao algoritmo superestima sua força? Subestimações são menos um problema.
O 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)
Algumas entradas e suas saídas entropy_bits desejadas e reais:
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"
O algoritmo percebe (corretamente) que aumentar o tamanho do alfabeto (mesmo em um dígito) fortalece muito as senhas longas, como mostra a diferença entre entropy_bits das 6ª e 7ª senhas, que consistem em 36 a, mas no segundo 21 é capitalizado. No entanto, eles não levam em conta o fato de que ter uma senha de 36 a não é uma boa idéia, é facilmente quebrada com um cracker de senha fraco (e qualquer pessoa que assiste a digitar o verá) e o algoritmo não reflete isso. .
No entanto, reflete o fato de que xkcd1 é uma senha fraca em comparação com o xkcd2, apesar de ter maior densidade de complexidade (isso é mesmo uma coisa?).
Como posso melhorar esse algoritmo?
Adenda 1
Ataques de dicionário e ataques baseados em padrões parecem ser a grande coisa, então vou tentar resolver esses problemas.
Eu poderia realizar uma pesquisa abrangente na senha por palavras de uma lista de palavras e substituir palavras por tokens exclusivos das palavras que elas representam. Os tokens de palavras seriam tratados como caracteres e teriam seu próprio sistema de ponderação e adicionariam seus próprios pesos à senha. Eu precisaria de alguns novos parâmetros de algoritmo (os chamarei lw, Nw ~ = 2 ^ 11, fw ~ = .5 e rfw) e fatoraria o peso na senha como faria com qualquer outro pesos.
Essa pesquisa de palavras pode ser modificada especialmente para combinar letras minúsculas e maiúsculas, bem como substituições de caracteres comuns, como a de E com 3. Se eu não adicionasse um peso extra a essas palavras correspondentes, o algoritmo subestimaria um pouco sua força. ou dois por palavra, o que é bom. Caso contrário, uma regra geral seria, para cada combinação de caracteres não perfeita, atribuir um pouco de bônus à palavra.
Eu poderia, então, executar verificações simples de padrões, como pesquisas por execuções de caracteres repetidos e testes derivativos (faça a diferença entre cada caractere), que identificariam padrões como 'aaaaa' e '12345' e substituir cada padrão detectado por um padrão token, exclusivo para o padrão e o comprimento. Os parâmetros algorítmicos (especificamente, entropia por padrão) podem ser gerados em tempo real com base no padrão.
Nesse ponto, eu pegaria o comprimento da senha. Cada símbolo de palavra e símbolo de padrão contaria como um caractere; cada token substituiria os caracteres que eles representavam simbolicamente.
Criei algum tipo de notação de padrão, mas inclui o comprimento do padrão l, a ordem do padrão o e o elemento base b. Esta informação pode ser usada para calcular algum peso arbitrário para cada padrão. Eu faria algo melhor no código real.
Exemplo modificado:
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
A semântica exata de como a entropia é calculada a partir de padrões está em discussão. Eu estava pensando em algo como:
entropy(b) * l * (o + 1) // o will be either zero or one
O algoritmo modificado encontraria falhas e reduziria a força de cada senha na tabela original, com exceção de s^fU¬5ü;y34G<
, que não contém palavras ou padrões.