C# - Verificando a força da Senha


Muitas vezes somos solicitados a criar uma conta cadastrando um login e uma senha para ter acesso a um web site ou a dados sensíveis de um sistema. Como algumas senhas são fáceis de quebrar usando técnicas de força bruta, é comum dar o feedback aos usuários para mostrar a força da senha escolhida sinalizando ao usuário se a sua senha é ou não tão segura.

Neste artigo vou mostrar como podemos verificar a força de uma senha fornecida por um usuário fornecendo informações que indicam se a senha é fraca ou forte.

Algumas senhas são muito fracas e nunca devem ser utilizadas, geralmente elas incluem data de nascimento, números de telefone, números ou letras repetidos e nomes pessoais.

Outras podem ser descritas como fracas ou fortes de acordo com o comprimento da senha e do tipo de caracteres que ela contém. Por exemplo, se sua aplicação permite senhas de quatro caracteres de comprimento com a utilização das 26 letras do alfabeto, o número máximo de senhas possíveis é de aproximadamente 450.000. Este é um número pequeno para um computador moderno e um ataque de força bruta poderá quebrar a senha com certa facilidade.

Podemos aumentar o número de senhas possíveis, permitindo que caracteres adicionais sejam incluídos na senha. Se continuarmos com uma senha de quatro caracteres mas permitimos uma combinação de letras maiúsculas e minúsculas, as combinações possíveis aumentam de 450.000 para cerca de 7,5 milhões. Adicionando dígitos numéricos, símbolos e espaços para aumentar o conjunto de caracteres a 100 podemos chegar a 100 milhões de senhas possíveis com apenas quatro caracteres, o que é um número considerável.

Outra forma de aumentar o número de combinações possíveis é aumentar o comprimento da senha. Com os cem caracteres fornecidos por letras, dígitos e símbolos, estendendo a senha para dez caracteres de tamanho temos 100.000.000.000.000.000.000 combinações possíveis. Um número tão alto faz com que um ataque de força bruta não seja tão temido.

Neste artigo vamos criar uma classe que permite que a força de uma senha seja verificada. A classe vai marcar senhas com um valor entre zero e cem (0 a 100); com zero, indicando uma senha muito fraca e 100 uma senha muito forte.

As regras que serão aplicadas para calcular a pontuação baseiam-se no comprimento da palavra-passe introduzida e os tipos de caracteres utilizados, da seguinte forma:

  1. Seis pontos serão atribuídos para cada caractere na senha, até um máximo de sessenta pontos.
  2. Cinco pontos serão concedidos se a senha inclui uma letra minúscula. Dez pontos serão atribuídos se mais de uma letra minúscula estiver presente.
  3. Cinco pontos serão concedidos se a senha incluir uma letra maiúscula. Dez pontos serão atribuídos se mais de uma letra maiúscula estiver presente.
  4. Cinco pontos serão concedidos se a senha incluir um dígito numérico. Dez pontos serão atribuídos se mais de um dígito numérico estiver presente.
  5. Cinco pontos serão concedidos se a senha incluir qualquer caractere diferente de uma letra ou um dígito. Isto inclui símbolos e espaços em branco. Dez pontos serão concedidos se houver dois ou mais de tais caracteres.

Este conjunto de regras é mínima, mas dará uma pontuação razoável para senha. Você pode adicionar novas regras, como detectar a presença de caracteres repetidos. Cada uma delas devera diminuir a pontuação.

Para tornar mais amigável a informação ao usuário vamos definir mensagens de informação sobre a senha da força a intervalos numéricos que representam a pontuação adotado conforme a tabela abaixo:

Intervalo Mensagem
0-49 Inaceitavel
50-59 Fraca
60-79 Aceitavel
80-99 Forte
100 Segura

Criando o projeto no Visual C#

Vamos agora criar o projeto no Visual C# 2010 Express Edition.

Eu vou criar um projeto do tipo Windows Forms Application por ser mais simples implementar e testar, mas você pode criar um projeto do tipo Class Library para depois referenciar a DLL gerada em outros projetos.

Abra o Visual C# 2010 Express Edition e no menu File clique em New Project;

Selecione o template Windows Forms Application e informe o nome VerificarForcaSenha;

No formulário form1.cs criado inclua um controle TextBox (txtSenha) e um botão de comando (btnVerificaForcaSenha) e dois controles Labels : lblForcaSenha e lblPontosSenha;

O leiaute do formulário deverá ser o seguinte:

Agora vamos incluir no projeto definir o arquivo que conterá uma enumeração que indicara a força da senha informada pelo usuário;

Clique no menu Project e a seguir selecione Add Class e informe o nome ForcaDaSenha.cs.

A seguir digite o código abaixo neste arquivo:

namespace VerificaForcaSenha
{
        public enum ForcaDaSenha
        {
            Inaceitavel,
            Fraca,
            Aceitavel,
            Forte,
            Segura
        }
}

A seguir vamos incluir outra classe no projeto onde implementaremos o código para verificar a força da senha conforme a tabela de pontos e as regras definidas;

No menu Project clique em Add Class e informe o nome ChecaForcaSenha.cs e a seguir digite o código abaixo neste arquivo:

using System;
using System.Text.RegularExpressions;

namespace VerificaForcaSenha
{
    public class ChecaForcaSenha
    {
        public int geraPontosSenha(string senha)
        {
            if (senha == null) return 0;
            int pontosPorTamanho = GetPontoPorTamanho(senha);
            int pontosPorMinusculas = GetPontoPorMinusculas(senha);
            int pontosPorMaiusculas = GetPontoPorMaiusculas(senha);
            int pontosPorDigitos = GetPontoPorDigitos(senha);
            int pontosPorSimbolos = GetPontoPorSimbolos(senha);
            int pontosPorRepeticao = GetPontoPorRepeticao(senha);
            return pontosPorTamanho + pontosPorMinusculas + pontosPorMaiusculas + pontosPorDigitos + pontosPorSimbolos - pontosPorRepeticao;
        }

        private int GetPontoPorTamanho(string senha)
        {
            return Math.Min(10, senha.Length) * 6;
        }

        private int GetPontoPorMinusculas(string senha)
        {
            int rawplacar = senha.Length - Regex.Replace(senha, "[a-z]", "").Length;
            return Math.Min(2, rawplacar) * 5;
        }

        private int GetPontoPorMaiusculas(string senha)
        {
            int rawplacar = senha.Length - Regex.Replace(senha, "[A-Z]", "").Length;
            return Math.Min(2, rawplacar) * 5;
        }

        private int GetPontoPorDigitos(string senha)
        {
            int rawplacar = senha.Length - Regex.Replace(senha, "[0-9]", "").Length;
            return Math.Min(2, rawplacar) * 5;
        }

        private int GetPontoPorSimbolos(string senha)
        {
            int rawplacar = Regex.Replace(senha, "[a-zA-Z0-9]", "").Length;
            return Math.Min(2, rawplacar) * 5;
        }

        private int GetPontoPorRepeticao(string senha)
        {
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"(\w)*.*\1");
            bool repete = regex.IsMatch(senha);
            if (repete)
            {
                return 30;
            }
            else
            {
                return 0;
            }
        }

        public ForcaDaSenha GetForcaDaSenha(string senha)
        {
            int placar = geraPontosSenha(senha);

            if (placar < 50)
                return ForcaDaSenha.Inaceitavel;
            else if (placar < 60)
                return ForcaDaSenha.Fraca;
            else if (placar < 80)
                return ForcaDaSenha.Aceitavel;
            else if (placar < 100)
                return ForcaDaSenha.Forte;
            else
                return ForcaDaSenha.Segura;
        }
    }
}

O método geraPontosSenha() calcula o número de pontos da senha informada chamando métodos auxiliares implementados para cada regra definida. Assim temos os seguintes métodos:

O retorno da função irá calcular o número total de pontos obtido pela fórmula:

TotalPontos = pontosPorTamanho + pontosPorMinusculas + pontosPorMaiusculas + pontosPorDigitos + pontosPorSimbolos - pontosPorRepeticao

O método GetForcaDaSenha() irá se basear nos pontos obtidos e na enumeração definida e retornar a mensagem ao usuário.

Abaixo temos o resultado obtido após a execução do projeto (F5) :

Gostaria de lembrar que o exemplo aqui mostrado procura dar uma ideia básica de como verificar a força de uma senha. Em um projeto mais complexo ou mais exigente quanto a segurança talvez as regras definidas deveriam ser mais rigorosas. Cabe a você definir as regras aproveitando a ideia do artigo e indo além com regras mais elaboradas como impedir a informação de dados pessoais, etc.

Pegue o projeto completo aqui: VerificarForcaDaSenha.zip

Joã 14:6 Respondeu-lhe Jesus: Eu sou o caminho, e a verdade, e a vida; ninguém vem ao Pai, senão por mim.

Joã 12:46 Eu, que sou a luz, vim ao mundo, para que todo aquele que crê em mim não permaneça nas trevas.

Joã 10:9 Eu sou a porta; se alguém entrar a casa; o filho fica entrará e sairá, e achará pastagens.

Joã 6:35 Declarou-lhes Jesus. Eu sou o pão da vida; aquele que vem a mim, de modo algum terá fome, e quem crê em mim jamais terá sede.

Joã_15:1 Eu sou a videira verdadeira, e meu Pai é o viticultor.

Joã 10:11 Eu sou o bom pastor; o bom pastor dá a sua vida pelas ovelhas.

Joã_13:13 Vós me chamais Mestre e Senhor; e dizeis bem, porque eu o sou.

Joã 10:14 Eu sou o bom pastor; conheço as minhas ovelhas, e elas me conhecem,
Joã 10:15
assim como o Pai me conhece e eu conheço o Pai; e dou a minha vida pelas ovelhas.

Joã 11:25 Declarou-lhe Jesus: Eu sou a ressurreição e a vida; quem crê em mim, ainda que morra, viverá;

Referências:


José Carlos Macoratti