No post de hoje, aprenderemos como proteger e manter suas senhas seguras utilizando a biblioteca BCrypt
. Quando temos senhas salvas em um banco de dados, é essencial criptografá-las, pois são dados sensíveis que, em caso de vazamento, podem ser comprometidos.
O que é BCrypt?
BCrypt é uma biblioteca de hashing de senhas para aplicações .NET. Ela utiliza o algoritmo bcrypt, projetado para ser seguro contra ataques de força bruta, dificultando a adivinhação de senhas pelos atacantes. A biblioteca oferece funções para gerar hashes de senhas e verificar se uma senha corresponde a um determinado hash, sendo amplamente utilizada para armazenar senhas de maneira segura em bancos de dados.
Interface
Primeiro, precisamos definir uma interface com os métodos que serão implementados no serviço de criptografia de senhas:
public interface IEncriptadorDeSenha
{
string Encriptar(string senha);
bool Verificar(string senha, string senhaEncriptografada);
}
A interface requer dois métodos:
- Encriptar: Recebe a senha como uma string e a criptografa antes de ser salva no banco de dados.
- Verificar: Método booleano que verifica se a senha fornecida corresponde à senha criptografada armazenada no banco de dados.
Antes de implementar esses métodos, vamos adicionar a biblioteca necessária ao nosso projeto:
dotnet add package BCrypt.Net-Next
Agora, vamos à implementação.
Implementação do Encriptador de Senha
Primeiro, implementamos a interface:
internal class EncriptadorDeSenha : IEncriptadorDeSenha
Método Encriptar
Vamos começar com o método Encriptar
, que é bastante simples:
public string Encriptar(string senha)
{
string senhaEncriptografada = BCrypt.Net.BCrypt.HashPassword(senha);
return senhaEncriptografada;
}
Este método recebe a senha como parâmetro, criptografa utilizando o método HashPassword()
da biblioteca BCrypt
, e retorna a senha criptografada para ser salva no banco de dados.
Método Verificar
Agora, vamos implementar o método de verificação, que também é essencial:
public bool Verificar(string senha, string senhaEncriptografada) => BCrypt.Net.BCrypt.Verify(senha, senhaEncriptografada);
Este método recebe a senha digitada pelo usuário e a senha criptografada armazenada no banco de dados. Utilizando o método Verify
da biblioteca BCrypt
, ele compara as duas senhas e retorna True
se forem iguais, e False
se não forem.
Adicionando o Serviço
Para utilizar o encriptador, precisamos adicionar o serviço no container de injeção de dependência:
services.AddScoped<IEncriptadorDeSenha, EncriptadorDeSenha>();
Podemos também criar um alias para encurtar as chamadas da biblioteca:
using BC = BCrypt.Net.BCrypt;
Código Final
Aqui está o código completo da implementação:
internal class EncriptadorDeSenha : IEncriptadorDeSenha
{
public string Encriptar(string senha)
{
string senhaEncriptografada = BC.HashPassword(senha);
return senhaEncriptografada;
}
public bool Verificar(string senha, string senhaEncriptografada) => BC.Verify(senha, senhaEncriptografada);
}
Agora você está pronto para proteger e manter suas senhas seguras utilizando BCrypt
!
Exemplos Práticos
Vamos ver exemplos práticos de como utilizar o serviço de encriptação de senha com BCrypt.
Exemplo 1: Criando um Usuário
Neste exemplo, mostraremos como encriptamos a senha do Usuário
, utilizando o serviço de encriptação de senha.
private readonly IEncriptadorDeSenha _encriptadorDeSenha;
public RegistrarAdminCommandHandler(IEncriptadorDeSenha encriptadorDeSenha)
{
_encriptadorDeSenha = encriptadorDeSenha;
}
public void RegistrarAdmin(RegistrarAdminRequest request)
{
var admin = new Admin
{
Nome = request.Nome,
Email = request.Email,
Senha = _encriptadorDeSenha.Encriptar(request.Senha),
Telefone = request.Telefone,
IdentificadorUsuario = Guid.NewGuid(),
Role = Roles.ADMIN
};
// Persistir o usuário no banco de dados
}
Neste trecho de código, utilizamos o método Encriptar
do serviço IEncriptadorDeSenha
para criptografar a senha antes de armazená-la no banco de dados.
Exemplo de Senha Encriptografada
Após executar Encriptar
, a senha é transformada em um hash criptografado, como o exemplo a seguir:
$2a$12$h8xn8aE9nEr/EZNCuJme1.tE0MdlB8F5W6Wc4J7c3B36H6zIxFbZq
Este hash é composto por:
$2a$
: Identificador do algoritmo bcrypt.12$
: Fator de custo, indicando quantas iterações de hashing foram realizadas (2^12 no caso).h8xn8aE9nEr/EZNCuJme1.
: O salt gerado aleatoriamente.tE0MdlB8F5W6Wc4J7c3B36H6zIxFbZq
: O hash resultante da senha.
Exemplo 2: Verificando a Senha no Login
No exemplo a seguir, mostramos como verificar a senha durante o processo de login do Usuário
:
private readonly IEncriptadorDeSenha _encriptadorDeSenha;
public LoginAdminCommandHandler(IEncriptadorDeSenha encriptadorDeSenha)
{
_encriptadorDeSenha = encriptadorDeSenha;
}
public async Task<RespostaLoginAdminJson> Handle(LoginAdminCommand request, CancellationToken cancellationToken)
{
var admin = await _adminReadOnlyRepositorio.RecuperarPorEmail(request.Email);
if (admin == null)
throw new LoginInvalidoException();
var senhaCorreta = _encriptadorDeSenha.Verificar(request.Senha, admin.Senha);
if (!senhaCorreta)
throw new LoginInvalidoException();
return new RespostaLoginAdminJson(
admin.Nome,
_geradorTokenAcesso.Gerar(admin)
);
}
Neste código, utilizamos o método Verificar
do serviço IEncriptadorDeSenha
para comparar a senha fornecida durante o login com a senha criptografada armazenada no banco de dados. Se as senhas coincidirem, o login é autorizado; caso contrário, uma exceção de login inválido é lançada.
Considerações Finais
Ao utilizar BCrypt para criptografar senhas, garantimos um nível adicional de segurança ao armazenar informações sensíveis como senhas de usuários em bancos de dados.