FlowingDev

Bcrypt e Argon2: Por que suas senhas precisam malhar

Aprenda como algoritmos modernos de hashing de senhas, como o bcrypt e o Argon2, protegem seus dados, tornando as senhas computacionalmente caras e lentas para quebrar.

Testar a ferramenta: Hash Bcrypt & Argon2

Em uma frase

Algoritmos de hashing de senhas como o bcrypt e o Argon2 transformam a senha de um usuário em uma longa e irreversível sequência de caracteres, projetada para ser lenta e cara de computar, tornando dolorosamente difícil para invasores quebrarem senhas, mesmo que eles roubem todo o seu banco de dados de usuários.

O problema que ele resolve

Na idade das trevas digital, os desenvolvedores armazenavam as senhas dos usuários em texto puro. Se um hacker invadisse o banco de dados, ele obteria um arquivo contendo cada nome de usuário e sua senha correspondente. Game over. Você pode imaginar a carnificina.

O primeiro avanço foi o "hashing". Em vez de armazenar S3nh@123, você armazenaria seu hash — uma string de tamanho fixo gerada por um algoritmo como MD5 ou SHA-1. Quando o usuário fizesse login, você faria o hash da senha que ele digitou e veria se ela correspondia ao hash armazenado. Isso era melhor, mas tinha uma falha fatal: as rainbow tables. Como uma função de hash sempre produz a mesma saída para a mesma entrada (por exemplo, password sempre vira 5f4dcc3b5aa765d61d8327deb882cf99 com MD5), os invasores pré-computavam os hashes de bilhões de senhas comuns e os armazenavam em uma tabela de consulta gigante. Um hash roubado poderia ser revertido para sua senha original em milissegundos.

A próxima evolução foi o "salting". Antes de fazer o hash da senha, você adiciona uma string aleatória e única chamada de "salt" (sal). Então, em vez de fazer o hash de S3nh@123, você faria o hash de S3nh@123 + aBcDeFg12345. O salt é então armazenado junto com o hash no banco de dados. Isso neutraliza completamente as rainbow tables, porque agora o hash de cada usuário é único, mesmo que todos tenham escolhido a senha "password". Um invasor teria que gerar uma nova rainbow table para o salt único de cada usuário, o que é computacionalmente inviável.

Mas um novo vilão entrou em cena: o poder de computação bruto. GPUs modernas e hardware customizado (ASICs) podem testar bilhões de combinações de senhas com salt por segundo contra um único hash roubado. Algoritmos de hashing como o SHA-256 são rápidos por design, o que é ótimo para verificar a integridade de arquivos, mas terrível para proteger senhas.

Este é o problema que o bcrypt e o Argon2 nasceram para resolver. Eles são funções de hashing de senha (PHFs), uma classe especial de algoritmo de hash que é deliberadamente, dolorosamente lenta e que consome muitos recursos. Eles tornam tão caro verificar até mesmo uma única senha que a força bruta em um banco de dados roubado se torna um pesadelo econômico e temporal para o invasor.

Como funciona por debaixo dos panos

A mágica por trás do hashing de senha moderno não está apenas no algoritmo; está em fazer esse algoritmo realizar uma quantidade configurável de "trabalho". Isso é frequentemente chamado de "key stretching".

A Ideia Central: Custo Adaptativo

Tanto o bcrypt quanto o Argon2 têm fatores de "custo" ou "trabalho" ajustáveis. Esse é o superpoder deles. É um número que você define que dita quão lento e faminto por recursos o processo de hashing será. A ideia é ajustar esse custo para que o hashing de uma senha em seu servidor leve um tempo razoável (digamos, 100-500 milissegundos) — lento o suficiente para frustrar um invasor, mas rápido o suficiente para não irritar seus usuários.

À medida que os computadores ficam mais rápidos de acordo com a Lei de Moore, você pode simplesmente aumentar o fator de custo a cada poucos anos para manter o mesmo nível de segurança. Seu "treino" de hashing fica mais pesado à medida que o hardware do invasor fica mais forte.

Bcrypt: O Veterano de Confiança

O bcrypt, introduzido em 1999, é baseado na cifra de criptografia Blowfish. Sua principal defesa contra ataques de força bruta é que ele não é apenas computacionalmente intensivo, mas também intensivo em memória.

O algoritmo processa repetidamente a senha e o salt, mas uma parte fundamental de seu estado interno é armazenada de uma forma que requer acesso frequente a um bloco de RAM. Enquanto as CPUs são boas nisso, as GPUs — a arma preferida do invasor — prosperam em cálculos simples e paralelizáveis com acesso mínimo à memória. Ao forçar o processo a mergulhar constantemente na memória, o bcrypt coloca areia na engrenagem das plataformas de quebra de senha baseadas em GPU.

Uma string de hash bcrypt típica se parece com isso:

$2b$12$J9yLsf9dTOZiCEpT1zO97uF2Yp3uG/yG4Q6V.C1rCg8u6d5qO5GqS

Vamos analisar:

Parte Exemplo Significado
Algoritmo $2b Identifica o algoritmo e a versão do bcrypt.
Fator de Custo 12 O fator de trabalho. O número de iterações é 212. Aumentar este número em 1 dobra o tempo.
Salt e Hash J9yLsf...d5qO5GqS Os primeiros 22 caracteres são o salt codificado em Base64. O resto é o digest do hash da senha propriamente dito.

Crucialmente, toda a informação necessária para verificar uma senha — o algoritmo, o custo e o salt — está armazenada ali mesmo, em uma única string conveniente.

Argon2: O Campeão Moderno

O Argon2 foi o vencedor da Competição de Hashing de Senhas (PHC) em 2015, um esforço de vários anos para encontrar um novo algoritmo de hashing de senha padronizado. Ele é projetado para ser ainda mais resistente a ataques de hardware modernos do que o bcrypt.

Ele oferece três alavancas distintas para ajustar seu custo:

  1. Custo de Memória (m): A quantidade de memória (em KiB) que o algoritmo usará. Esta é sua principal defesa contra a aceleração por hardware, pois pode ser ajustado para exigir mais memória do que a disponível em um único núcleo de GPU.
  2. Custo de Tempo (t): O número de iterações, ou passagens, que o algoritmo faz sobre a memória. Isso aumenta o tempo total de computação.
  3. Paralelismo (p): O número de threads ou "pistas" que podem ser usadas. Isso permite que o algoritmo aproveite CPUs multi-core para o hashing, mas também significa que um invasor pode usar o mesmo paralelismo. É um parâmetro de equilíbrio.

A variante recomendada é a Argon2id, que é um híbrido de outras duas versões. Ela fornece uma resistência equilibrada contra ataques de side-channel (onde um invasor analisa efeitos do sistema, como consumo de energia) e ataques de quebra por GPU.

Uma string de hash Argon2id é similarmente autocontida:

$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTIT0T7cKLfgflAIk124

Parte Exemplo Significado
Algoritmo $argon2id Identifica o algoritmo Argon2id.
Versão v=19 O número da versão do algoritmo.
Parâmetros m=65536,t=3,p=4 Os custos de memória, tempo e paralelismo.
Salt c29tZXNhbHQ O salt aleatório codificado em Base64. (Isso decodifica para "somesalt").
Hash Rdescudv...flAIk124 O digest do hash da senha codificado em Base64.

O Processo de Verificação

Esta é a parte genial. Você nunca descriptografa um hash. A verificação é uma via de mão única.

  1. Um usuário tenta fazer login com S3nh@123.
  2. Sua aplicação recupera a string de hash completa dele do banco de dados (por exemplo, a string Argon2id da tabela acima).
  3. Seu código analisa essa string, extraindo o algoritmo (argon2id), a versão (19), os fatores de custo (m=65536, t=3, p=4) e o salt (c29tZXNhbHQ).
  4. Em seguida, ele pega a senha que o usuário acabou de digitar (S3nh@123) e gera um hash usando exatamente esses mesmos parâmetros.
  5. Finalmente, ele compara o hash recém-gerado com a parte do hash da string do banco de dados. Se forem idênticos, a senha está correta. Se não, o acesso é negado.

Histórias do mundo real

O Vazamento do LinkedIn de 2012: Uma Lição sobre Velocidade

Em 2012, o LinkedIn sofreu um vazamento massivo, e mais de 6,5 milhões de hashes de senhas de usuários foram parar em um fórum de hackers russo. O problema? Os hashes eram SHA-1 sem salt. Em questão de horas, entusiastas de segurança e black hats iniciaram uma corrida para quebrá-los. Listas de senhas quebradas com sucesso cresciam a cada minuto. Como os hashes eram "rápidos" e sem salt, uma única e massiva rainbow table foi tudo o que foi preciso. O dano à reputação foi imenso.

Lição: Um hash rápido e sem salt é pouco melhor que texto puro. O vazamento do LinkedIn foi um enorme alerta para a indústria que impulsionou inúmeras empresas a finalmente adotarem hashing lento e com salt, como o bcrypt.

O E-commerce que Ganhou Tempo

Um desenvolvedor experiente de uma startup, a "CircuitCraze", insistiu em usar Argon2id para seu novo banco de dados de clientes, ajustando os parâmetros para levar cerca de 300ms por login. Um ano depois, um bucket de armazenamento em nuvem mal configurado expôs um backup do banco de dados. A tabela users, com todos os seus hashes Argon2id, foi baixada por um invasor. A equipe imediatamente forçou uma redefinição global de senhas. O invasor, diante da perspectiva de gastar milhares de dólares em computação em nuvem apenas para quebrar um punhado de senhas de um conjunto de dados agora inútil, simplesmente desistiu e partiu para alvos mais fáceis.

Lição: O hashing de senha forte é sua principal defesa após um vazamento. Ele não impede o vazamento, mas transforma um derramamento catastrófico de dados em um incidente gerenciável, comprando tempo crucial para você reagir.

A Escalada do Fator de Custo

Uma equipe lançou um novo aplicativo da web em 2015, escolhendo sabiamente o bcrypt com um fator de custo de 10. Funcionou muito bem. Avançando para os dias de hoje. A Lei de Moore fez seu trabalho, e um fator de custo de 10 agora é considerado fraco. Uma auditoria de segurança o sinaliza como um risco de alta prioridade. A equipe agora enfrenta um dilema: como eles atualizam a segurança para milhões de usuários sem forçar uma redefinição de senha em massa? A solução elegante: na próxima vez que um usuário fizer login, o sistema verifica sua senha contra o hash antigo com custo 10. Se estiver correto, ele imediatamente gera um novo hash da mesma senha com um novo custo de 13 e substitui o hash antigo no banco de dados.

Lição: A segurança de senhas não é do tipo "configure uma vez e esqueça". Os fatores de custo são uma configuração viva que deve ser periodicamente revisada e aumentada para acompanhar as capacidades dos invasores.

Erros e armadilhas comuns

  • Usar um hash rápido. Não use. MD5, SHA-1, SHA-256, SHA-512... eles são para checksums, não para senhas. Eles são projetados para serem rápidos, que é exatamente o que você não quer.
  • Criar sua própria criptografia do zero. Nunca tente inventar seu próprio esquema de hashing, como sha512(password + salt). Use uma biblioteca padrão, revisada por pares e testada em batalha para bcrypt ou Argon2 que faça isso da maneira certa.
  • Usar um salt estático ou reutilizado. Um salt deve ser criptograficamente aleatório e único para cada senha que você armazena. Armazenar um salt único ao lado de cada hash é a prática correta e padrão.
  • Definir o custo muito baixo. Um fator de custo do bcrypt abaixo de 12 (em 2024) ou parâmetros fracos do Argon2 anulam todo o propósito. Você está apenas facilitando a vida do invasor. Ajuste-o para ser o mais lento que você puder tolerar.
  • Definir o custo muito alto. Se o hashing levar 10 segundos, seu formulário de login dará timeout e parecerá quebrado. Pior, você abre seu servidor para um ataque de Negação de Serviço (DoS), onde alguém pode levar suas CPUs à exaustão apenas postando repetidamente no formulário de login.
  • Armazenar apenas o digest do hash. As strings geradas pelo bcrypt e Argon2 contêm o algoritmo, os custos e o salt por um motivo. Você deve armazenar essa string inteira (por exemplo, em uma coluna VARCHAR(255)) para poder verificar as senhas no futuro.

Por que isso deve estar no seu radar

Se o seu trabalho envolve construir qualquer coisa que tenha um formulário de login, você precisa entender isso.

  • Devs de Backend e Full-Stack: Esta é sua responsabilidade direta. Se você errar nisso, coloca todos os seus usuários em risco.
  • Engenheiros de Segurança e DevOps: Vocês são os que definem políticas, realizam auditorias e gerenciam a infraestrutura. Vocês precisam saber como é um bom padrão e como testá-lo.
  • Devs de Frontend: Entender que um login seguro pode levar algumas centenas de milissegundos explica por que você precisa fornecer feedback ao usuário (como um spinner de carregamento) para evitar que ele clique furiosamente no botão "Entrar".

Resumindo, se as palavras "usuário", "conta" ou "senha" aparecem em qualquer lugar nos requisitos do seu projeto, o hashing de senha é um conceito fundamental que você não pode se dar ao luxo de ignorar.

Aprofunde-se

Teoria feita. Hora de pôr a mão na massa — 100% no seu navegador.

Testar a ferramenta: Hash Bcrypt & Argon2