Guias de Segurança
Como armazenar senhas com segurança — a forma certa de fazer hash e salt
Como você deve armazenar as senhas dos usuários? Por que texto puro, criptografia e hashes crus falham, o que um salt por usuário faz e a resposta de verdade — um hash lento (bcrypt/Argon2/scrypt): como escolher, ajustar e migrar um sistema existente. Defensivo e voltado para devs, sem passos de ataque.
"Como exatamente devo armazenar as senhas dos usuários no banco de dados?" — todo construtor esbarra nessa pergunta uma vez. A resposta é clara. Aqui está a forma segura de armazená-las, em ordem, sem passos de ataque.
Por que texto puro, criptografia e hashes crus falham
Presuma que o banco de dados vai vazar algum dia. Quando vazar, o dano difere muito conforme o método de armazenamento.
- Texto puro: toda senha é exposta no instante em que vaza. Pior, a reutilização de senhas encadeia a invasão para os outros serviços do usuário. O pior caso.
- Criptografia (reversível): a chave a reverte — então se a chave vazar junto, você volta ao texto puro. Uma senha nunca precisa ser lida de volta, então ser reversível não traz benefício nenhum.
- Hash cru (MD5/SHA-256): um hash rápido permite ao atacante testar tentativas rapidamente. Senhas comuns caem para rainbow tables e força bruta.
Os "quatro estágios" até o seguro
É mais rápido entender adicionando uma correção por vez a um método fraco.
A percepção-chave: um salt e um hash lento fazem trabalhos diferentes. Um salt derrota a pré-computação (rainbow tables) e a quebra em massa por reutilização. Um hash lento reduz a força bruta a uma taxa impraticável. Você precisa dos dois antes de estar seguro (→ o que é hashing).
Na prática: o que fazer agora
Use Argon2id (ou bcrypt)
Para sistemas novos, faça do Argon2id a primeira escolha — ele também pode exigir memória, o que resiste à força bruta por GPU. Se você prefere uma implementação testada em batalha, o bcrypt é mais do que suficiente na prática. Use a implementação da biblioteca padrão como está para qualquer um dos dois.
Deixe o salt ser automático
bcrypt/Argon2 geram um salt por usuário e o embutem dentro da string de hash. Você não mantém uma coluna de salt separada. Montar à mão MD5(salt + senha) é o clássico que não se deve fazer.
Ajuste o custo para o seu ambiente
Defina o fator de custo do bcrypt, ou memória/iterações/paralelismo do Argon2, o mais alto que conseguir enquanto um login legítimo ainda parecer instantâneo. Conforme os servidores ficam mais rápidos, os atacantes também — revisite e eleve anualmente.
Verifique com a função de comparação padrão
No login, compare a entrada com o hash armazenado usando a função de verificação da biblioteca (a maioria usa uma comparação de tempo constante, segura contra timing). Não escreva sua própria igualdade de strings.
Migre hashes fracos refazendo o hash no login
Se você já armazena MD5/SHA-256, no momento em que um usuário faz login com sucesso, refaça o hash com o novo esquema e salve. Para usuários que não fizeram login, você pode atualizar provisoriamente envolvendo o hash existente dentro do bcrypt (um hash em camadas).
Erros comuns vs. a implementação correta
Erro comum
- Criptografar senhas para armazenar (chave vaza → acabou)
- Armazenar
MD5(senha)ouSHA-256(senha)diretamente - Usar um único salt compartilhado para todos os usuários
- Montar à mão
hash(salt + senha)
Implementação correta
- Hash de mão única com Argon2id / bcrypt
- Um salt por usuário (a biblioteca o adiciona automaticamente)
- Custo o mais alto que parecer OK, elevado periodicamente
- Usar as funções padrão de hash/verificação como estão
A visão deste site: armazenamento de senha é lugar de seguir a resposta chata e comprovada
Armazenamento de senha não é lugar de ser criativo. Seguir as implementações padrão do Argon2/bcrypt, testadas pelo mundo todo, é o mais seguro e o mais fácil de operar. Nossa posição: não inove aqui. Gaste seu esforço, em vez disso, em reduzir a dependência de senhas em si — autenticação multifator (MFA) minuciosa e uma eventual migração para passkeys (sem senha). Nem o hash mais forte salva uma senha fraca e reutilizada.
Leia a seguir
- Glossário: o que é hashing de senha / o que é um salt
- Fundamentos: guardando senhas do jeito certo (lado do usuário) / escolhendo um gerenciador de senhas
- Defesa: escolhendo MFA do jeito certo (reduza a dependência de senhas)
- Glossário: o que é uma passkey (rumo ao sem senha)
FAQ
QNão basta criptografar as senhas para armazenar?
Não — criptografia é a ferramenta errada. Criptografia é reversível com uma chave, então se a chave vazar, toda senha volta a texto puro. Uma senha nunca precisa ser lida de volta, nem por você, então um 'hash' irreversível é a resposta certa. Mas um hash cru não basta; combine um salt por usuário com um hash lento (bcrypt/Argon2).
Qbcrypt ou Argon2 — qual usar?
Para desenvolvimento novo, o Argon2 (Argon2id especialmente) é a primeira escolha: permite ajustar memória e processamento, o que resiste bem à força bruta por GPU. Se você valoriza uma implementação consagrada e testada em batalha, o bcrypt ainda é perfeitamente prático. O ponto-chave em qualquer um é usar a implementação da biblioteca padrão como está e não inventar a sua.
QEu já armazenei senhas com MD5/SHA-256. Como migro?
Você não consegue converter em massa de volta para texto puro (esse é o ponto), então migre no login. No momento em que um usuário faz login com sucesso, refaça o hash da senha correta que ele acabou de digitar com o novo esquema (ex.: Argon2id) e salve. Para usuários que não fizeram login, você pode atualizar provisoriamente envolvendo o hash existente dentro do bcrypt (um hash em camadas).