Sua senha não é apenas uma string: por que a autenticação em C# exige uma abordagem especial
\n\nImagine: você escreveu uma aplicação C# perfeita — com uma interface bonita, consultas rápidas e arquitetura limpa. Mas se a autenticação nela for frágil, todo o trabalho é em vão. Hackers não arrombam portas — eles escolhem chaves. E no mundo moderno, a autenticação segura em C# não é uma opção, mas uma higiene básica de código.
\n\nNeste artigo, abordaremos não apenas a teoria, mas métodos reais de proteção: desde o hash correto de senhas até a implementação de JWT e OAuth. Você aprenderá por que SHA256 sem salt é prejudicial, como não cair em ataques de força bruta e o que fazer se seu projeto já superou os métodos de autenticação "infantis". Vamos lá!
\n\nOs três pilares da segurança: hash, salt e algoritmos lentos
\n\nO antipadrão mais comum de iniciantes é armazenar senhas em texto puro ou usar MD5 simples. Mesmo que você tenha "apenas um projeto de estudo", o hábito se fixa. A autenticação segura em C# começa com três regras:
\n\n- \n
- Nunca armazene senhas em texto puro. Mesmo em um banco de dados local. \n
- Use salt — uma string aleatória para cada usuário. \n
- Escolha algoritmos lentos — BCrypt, PBKDF2, Argon2. \n
Por que "lentos"? Porque um hacker precisa testar bilhões de combinações por segundo. Se o hash leva 0,1 segundo, o ataque se torna economicamente inviável.
\n\nHash correto de senhas em C# com exemplo de BCrypt
\n\nBCrypt é o padrão ouro para desenvolvedores .NET. Ele gera o salt automaticamente e o incorpora no hash. Você não precisa armazenar o salt separadamente.
\n\nInstale o pacote via NuGet:
\nInstall-Package BCrypt.Net-Next\n\nAgora, um exemplo de registro de usuário:
\n\nusing BCrypt.Net;\n\npublic class AuthService\n{\n public string HashPassword(string plainPassword)\n {\n // Work factor = 12 — equilíbrio ideal entre velocidade e segurança\n return BCrypt.HashPassword(plainPassword, workFactor: 12);\n }\n\n public bool VerifyPassword(string plainPassword, string hashedPassword)\n {\n return BCrypt.Verify(plainPassword, hashedPassword);\n }\n}\n\n// Uso:\nvar auth = new AuthService();\nstring hash = auth.HashPassword("MyS3cur3P@ss!");\nbool isValid = auth.VerifyPassword("MyS3cur3P@ss!", hash); // true\n\nObserve: workFactor (fator de custo) determina quantas iterações de hash serão executadas. 12 é um bom valor para 2024. Se seu servidor for potente, pode aumentar para 13-14.
PBKDF2 — ferramenta nativa do .NET
\n\nSe você não quiser bibliotecas de terceiros, use Rfc2898DeriveBytes — a implementação nativa do PBKDF2 no .NET. Exemplo:
using System.Security.Cryptography;\n\npublic static string HashWithPBKDF2(string password, byte[] salt, int iterations = 100_000)\n{\n using var deriveBytes = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256);\n byte[] hash = deriveBytes.GetBytes(32); // 32 bytes = 256 bits\n return Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);\n}\n\n// Geração de salt (16 bytes)\nbyte[] salt = RandomNumberGenerator.GetBytes(16);\nstring result = HashWithPBKDF2("userPassword", salt);\n\nImportante: não use menos de 100.000 iterações. GPUs modernas conseguem testar milhões de hashes por segundo.
\n\nJWT — autenticação moderna sem sessões
\n\nQuando sua aplicação C# cresce para microsserviços ou SPA (React, Vue), armazenar sessões no servidor se torna inconveniente. É aí que entram os JSON Web Tokens (JWT) — tokens de acesso compactos e autossuficientes.
\n\nA autenticação segura em C# com JWT é baseada em três princípios:
\n- \n
- O