Close Menu
Código Simples .NETCódigo Simples .NET
    Facebook X (Twitter) Instagram
    Trending
    • Model Context Protocol (MCP): O Futuro da Interação com Modelos de IA
    • Processamento Assíncrono: Os Desafios da Escalabilidade
    • NewSQL em 2025: O Estado Atual, Tendências e o Futuro dos Bancos de Dados Relacionais Escaláveis
    • 12 Regras Essenciais para Reduzir a Latência de Aplicações
    • Cache Hit Ratio: Como uma Simples Métrica Pode Revolucionar sua Arquitetura
    • Como a Uber calcula o tempo estimado de chegada
    • 30 APIs Gratuitas para desenvolvedores
    • Por que escalar escrita é tão mais difícil do que escalar leitura?
    Facebook X (Twitter) Instagram
    Código Simples .NETCódigo Simples .NET
    Código Simples .NETCódigo Simples .NET
    Home»Asp.net»Boas práticas de criação, armazenamento e validação de senhas em .NET

    Boas práticas de criação, armazenamento e validação de senhas em .NET

    Jhonathan SoaresBy Jhonathan Soares9 de julho de 20248 Mins Read Asp.net
    Share
    Facebook Twitter LinkedIn WhatsApp Copy Link

    Armazenar senhas de maneira segura no banco de dados é uma prática essencial para garantir a integridade e a segurança dos dados dos usuários. Neste artigo, vamos explorar como criar, armazenar senhas de forma segura e como validar uma senha utilizando .NET. Também abordaremos práticas recomendadas adicionais para desempenho e segurança.

    Antes de mais nada, o que NÃO fazer

    🔹 Armazenar senhas em texto simples: Guardar senhas em texto simples no banco de dados é uma prática extremamente perigosa, pois qualquer pessoa com acesso interno pode visualizá-las.

    🔹 Armazenar hashes de senhas diretamente: Embora seja melhor do que armazenar senhas em texto simples, armazenar apenas o hash da senha não é suficiente. Isso porque hashes simples estão vulneráveis a ataques de precomputação, como tabelas arco-íris.

    🔹 Salting inadequado: Para mitigar ataques de precomputação, é essencial adicionar um “sal” às senhas antes de hasheá-las.

    Tá, mas o que é um Salt?

    De acordo com as diretrizes da OWASP, “um salt é uma string única e aleatoriamente gerada que é adicionada a cada senha como parte do processo de hashing”. O objetivo do salt é garantir que o resultado do hash seja único para cada senha, mesmo que duas senhas iguais sejam usadas.

    Como armazenar uma senha e um salt?

    1️⃣ Armazenamento do Salt: O salt não precisa ser criptografado e pode ser armazenado em texto simples no banco de dados. Sua finalidade é assegurar que o hash resultante seja único para cada senha.

    2️⃣ Armazenamento da Senha: A senha deve ser armazenada no banco de dados no seguinte formato: hash(senha + salt). Isso garante que cada hash é único, mesmo para senhas idênticas.

    Funcionamento do Processo de Hashing com Salt

    1. Geração do Salt: Quando um usuário cria ou altera uma senha, um salt único e aleatório é gerado.
    2. Combinação com a Senha: O salt é concatenado (ou combinado de alguma forma) com a senha do usuário.
    3. Hashing: A senha combinada com o salt é então passada por uma função de hash criptográfica (como SHA-256, bcrypt, Argon2, etc.), resultando em um hash de senha único.
    4. Armazenamento: Tanto o salt quanto o hash resultante são armazenados no banco de dados. Quando o usuário tenta fazer login, o sistema pega a senha fornecida, adiciona o salt correspondente, faz o hash e compara com o hash armazenado.

    Exemplo Prático

    1. Usuário Escolhe Senha: A senha escolhida é “minhaSenha123”.
    2. Geração do Salt: Um salt aleatório é gerado, por exemplo, “randomSalt12345”.
    3. Combinação: A senha e o salt são combinados, resultando em “minhaSenha123randomSalt12345”.
    4. Hashing: A combinação “minhaSenha123randomSalt12345” é passada por uma função de hash, resultando em algo como “5f4dcc3b5aa765d61d8327deb882cf99”.
    5. Armazenamento: O salt “randomSalt12345” e o hash “5f4dcc3b5aa765d61d8327deb882cf99” são armazenados no banco de dados.

    Boas Práticas Adicionais

    1. Utilizar Algoritmos de Hashing Fortes: Utilize algoritmos como PBKDF2, bcrypt ou Argon2 que são projetados para serem computacionalmente intensivos e, portanto, mais resistentes a ataques de força bruta.
    2. Configurar Iterações Adequadas: Para PBKDF2, recomenda-se usar um número elevado de iterações (por exemplo, 10000 ou mais) para aumentar a dificuldade de ataques.
    3. Comprimento Adequado do Salt: Utilize um salt de pelo menos 16 bytes para garantir a segurança contra ataques de tabelas arco-íris.
    4. Atualizar Periodicamente: Atualize periodicamente o número de iterações e a complexidade do algoritmo de hashing conforme a capacidade computacional aumenta ao longo do tempo.
    5. Monitoramento e Auditoria: Implemente monitoramento e auditoria para detectar tentativas de acesso não autorizado e outras atividades suspeitas.
    6. Armazenamento Seguro: Utilize práticas de segurança adequadas para proteger o banco de dados onde os hashes de senhas e salts são armazenados, incluindo criptografia de dados em repouso.
    7. Evitar Reutilização de Salts: Certifique-se de que cada senha tem um salt único para prevenir que hashes idênticos revelem senhas iguais.

    Considerações de Desempenho

    • Balanceamento de Iterações: O número de iterações deve ser alto o suficiente para ser seguro, mas também deve ser balanceado para não prejudicar o desempenho da aplicação.
    • Uso de Cache: Considere o uso de cache para armazenar temporariamente salts e hashes se houver uma necessidade de validação frequente para melhorar a performance.

    Exemplo completo de uma aplicação em .Net

    Todo código está disponível aqui: https://github.com/jhomarolo/ValidacaoSenhas

    Program.cs

    Crie um novo projeto console application e adicione o seguinte código na classe principal:

    using System;
    
    namespace PasswordSecurityExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Cadastro de Usuário:");
                Console.Write("Digite uma senha: ");
                string password = Console.ReadLine();
    
                // Verificar a força da senha
                if (!PasswordManager.IsValidPassword(password))
                {
                    Console.WriteLine("A senha deve ter no mínimo 6 caracteres e pelo menos 1 número, 1 letra e 1 caracter especial.");
                    return;
                }
    
                // Gerar o hash e salt da senha
                var (hash, salt) = PasswordManager.HashPassword(password);
                Console.WriteLine($"Senha Hash: {hash}");
                Console.WriteLine($"Salt: {salt}");
    
                // Simular armazenamento no banco de dados
                // Normalmente você armazenaria hash e salt no banco de dados aqui
    
                // Validação de senha
                Console.WriteLine("\nValidação de Usuário:");
                Console.Write("Digite a senha novamente: ");
                string enteredPassword = Console.ReadLine();
    
                bool isValid = PasswordManager.ValidatePassword(enteredPassword, hash, salt);
                if (isValid)
                {
                    Console.WriteLine("Senha válida!");
                }
                else
                {
                    Console.WriteLine("Senha inválida!");
                }
            }
        }
    }
    

    PasswordManager.cs

    Agora, crie um novo arquivo chamado PasswordManager.cs e adicione o seguinte código:

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace PasswordSecurityExample
    {
        public class PasswordManager
        {
            public static (string Hash, string Salt) HashPassword(string password)
            {
                // Gerando um salt aleatório
                byte[] saltBytes = new byte[16];
                using (var provider = new RNGCryptoServiceProvider())
                {
                    provider.GetBytes(saltBytes);
                }
                string salt = Convert.ToBase64String(saltBytes);
    
                // Concatenando senha e salt e gerando o hash
                var hash = ComputeHash(password, salt);
                
                return (hash, salt);
            }
    
            public static bool ValidatePassword(string enteredPassword, string storedHash, string storedSalt)
            {
                // Gerar o hash da senha inserida com o salt armazenado
                var hashToValidate = ComputeHash(enteredPassword, storedSalt);
                
                // Comparar o hash gerado com o hash armazenado
                return hashToValidate == storedHash;
            }
    
            private static string ComputeHash(string password, string salt)
            {
                var pbkdf2 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);
                byte[] hash = pbkdf2.GetBytes(20);
                return Convert.ToBase64String(hash);
            }
    
            public static bool IsValidPassword(string password)
            {
                // Verificar se a senha atende aos critérios de força
                if (password.Length < 6)
                    return false;
    
                bool hasLetter = false, hasDigit = false, hasSpecialChar = false;
                foreach (char c in password)
                {
                    if (char.IsLetter(c)) hasLetter = true;
                    else if (char.IsDigit(c)) hasDigit = true;
                    else hasSpecialChar = true;
                }
    
                return hasLetter && hasDigit && hasSpecialChar;
            }
        }
    }
    

    Funcionamento

    1. O programa solicitará que você digite uma senha para cadastro.
    2. Verificará se a senha atende aos critérios de força: no mínimo 6 caracteres, contendo pelo menos 1 número, 1 letra e 1 caractere especial.
    3. Ele exibirá o hash da senha e o salt gerados.
    4. Em seguida, solicitará que você digite a senha novamente para validação.
    5. O programa verificará se a senha digitada é válida comparando o hash gerado com o hash armazenado.

    Implementando essas práticas em suas aplicações .NET, você aumentará significativamente a segurança das senhas armazenadas e protegerá melhor os dados dos seus usuários contra ataques maliciosos.

    Dicas Adicionais para Gerenciamento de Senhas

    Para aumentar ainda mais a segurança das senhas, aqui estão algumas práticas adicionais e recomendações que podem ser implementadas:

    1. Políticas de Senhas Fortes

    Além das verificações básicas mencionadas anteriormente, considere implementar políticas de senha mais robustas:

    • Comprimento Mínimo: Requerer senhas com pelo menos 8-12 caracteres.
    • Complexidade: Garantir a presença de letras maiúsculas, letras minúsculas, números e caracteres especiais.
    • Proibição de Senhas Comuns: Utilizar uma lista de senhas comuns (como “123456”, “password”, etc.) e impedir que os usuários as utilizem.
    • Proibição de Reutilização: Impedir que os usuários reutilizem suas senhas anteriores.

    2. Expiração de Senhas

    • Rotatividade de Senhas: Exigir que os usuários alterem suas senhas periodicamente (por exemplo, a cada 90 dias).
    • Avisos de Expiração: Notificar os usuários antes que suas senhas expirem para incentivá-los a atualizá-las.

    3. Proteção Contra Ataques de Força Bruta

    • Limitação de Tentativas: Implementar uma limitação de tentativas de login, bloqueando temporariamente o usuário após um número definido de tentativas falhas.
    • CAPTCHA: Adicionar CAPTCHA em formulários de login após um certo número de tentativas falhas.

    4. Verificação Multifator (MFA)

    • Autenticação de Dois Fatores (2FA): Requerer um segundo fator de autenticação, como um código enviado por SMS, email ou gerado por um aplicativo de autenticação.
    • Hardware Tokens: Utilizar dispositivos de hardware (como YubiKey) para fornecer um fator de autenticação adicional.

    5. Monitoramento e Auditoria

    • Registro de Atividades: Registrar todas as tentativas de login (bem-sucedidas e falhas) e outras ações relacionadas à conta do usuário.
    • Análise de Padrões: Monitorar padrões de login suspeitos, como tentativas de login de locais geográficos incomuns.

    6. Segurança no Frontend

    • Criptografia em Trânsito: Garantir que todas as comunicações entre o cliente e o servidor sejam criptografadas usando HTTPS.
    • Proteção Contra CSRF: Implementar medidas para proteger contra ataques de falsificação de solicitação entre sites (CSRF).
    • Sanitização de Entrada: Sanitizar todas as entradas de usuário para prevenir ataques de injeção (como SQL Injection).

    Agora com essas dicas, acredito que você vai armazenar muito melhor suas senhas, não é mesmo?

    Todo código está disponível aqui: https://github.com/jhomarolo/ValidacaoSenhas

    Share. Facebook Twitter LinkedIn Telegram WhatsApp Copy Link
    Jhonathan Soares
    • Website
    • Facebook
    • X (Twitter)
    • LinkedIn

    Criador do blog Código Simples e com mais 15 anos de experiência em TI, com títulos de MVP Microsoft na área de Visual Studio Development, Neo4j Top 50 Certificate, Scrum Master e MongoDB Evangelist.

    Posts Relacionados

    Como escolher bibliotecas para seu projeto: Uma análise crítica de dependências

    Boas práticas 20 de setembro de 20245 Mins Read

    O que é a Ecma e qual é sua relação com C#?

    C# Post do Leitor 29 de julho de 20247 Mins Read

    Comentários no código – Vilões ou Mocinhos?

    Boas práticas 24 de julho de 20246 Mins Read
    Newsletter

    Digite seu endereço de e-mail para receber notificações de novas publicações por e-mail.

    Junte-se a 25mil outros assinantes
    Posts recentes
    • Model Context Protocol (MCP): O Futuro da Interação com Modelos de IA
    • Processamento Assíncrono: Os Desafios da Escalabilidade
    • NewSQL em 2025: O Estado Atual, Tendências e o Futuro dos Bancos de Dados Relacionais Escaláveis
    • 12 Regras Essenciais para Reduzir a Latência de Aplicações
    • Cache Hit Ratio: Como uma Simples Métrica Pode Revolucionar sua Arquitetura
    Categorias
    • Arquitetura (15)
      • Testes (2)
    • Asp.net (120)
      • C# (89)
      • Mvc (13)
    • Banco de dados (90)
      • NoSql (58)
      • Sql (38)
    • Boas práticas (29)
      • Gestão & Produtividade (1)
      • Metodologias Ágeis (6)
    • Cursos (52)
    • Dicas (105)
    • Front-End (92)
    • IA (2)
    • Linux (6)
    • NodeJS (4)
    • Post do Leitor (9)
    • Python (5)
    • Seo (12)
    • Tecnologia (30)
      • ITIL (1)
      • Padrões de Projeto (4)
    • Testes (2)

    VEJA TAMBÉM

    Cursos
    12 de fevereiro de 20166 Mins Read

    1000 livros gratuitos sobre programação!

    Olha que dica bacana! A pagina só com livros sobre programação é mantida no GitHub…

    30 APIs Gratuitas para desenvolvedores

    Facebook X (Twitter) Instagram LinkedIn

    Type above and press Enter to search. Press Esc to cancel.

    Vá para versão mobile