Como guardar senhas de usuários com segurança
Um sistema nunca deve conseguir ler as senhas dos usuários: ele guarda só um hash lento, com sal.
Nada de texto puro
Nem texto puro, nem criptografia reversível.
Sal único
Um sal aleatório por usuário derruba as tabelas prontas.
Função lenta
Argon2id, bcrypt, scrypt ou PBKDF2 com muitas iterações.
Resumo
Um sistema que tem login precisa conferir a senha do usuário, mas não precisa saber qual é a senha. Por isso, o certo é guardar só um hash da senha, calculado com uma função lenta e com um sal diferente para cada usuário. No login, o sistema calcula o hash da senha digitada e compara com o hash guardado.
Se o banco de dados vazar, um bom hash de senha transforma cada tentativa de adivinhar uma senha em um trabalho caro. Um hash fraco, ou a senha em texto puro, entrega as contas de todos os usuários de uma vez.
O que nunca fazer
Nunca guarde senhas em texto puro. Qualquer pessoa com acesso ao banco de dados, a um backup ou a um log vê todas as senhas. Como muita gente repete a mesma senha em vários sites, um vazamento afeta também as contas dos usuários em outros serviços.
Também não use criptografia reversível, como cifrar as senhas com o AES. A chave precisa ficar no próprio servidor para o login funcionar, e quem invade o servidor costuma levar a chave junto. Uma senha nunca precisa ser decifrada; ela só precisa ser conferida.
E não use um hash rápido. MD5, SHA-1 e SHA-256 foram feitos para ser rápidos. Um atacante com placas de vídeo testa bilhões de palpites por segundo contra esses hashes, e senhas comuns caem em minutos. Em 2012, o LinkedIn teve milhões de hashes de senhas vazados. Eles eram SHA-1 sem sal, e a maior parte foi descoberta pouco depois.
O sal
Um sal é um valor aleatório, diferente para cada usuário, que entra no cálculo do hash junto com a senha. Ele não é secreto: fica guardado ao lado do hash. A função dele é fazer com que duas pessoas com a mesma senha tenham hashes diferentes.
Sem sal, um atacante pode usar tabelas arco-íris, listas prontas com o hash de milhões de senhas comuns, e achar as senhas só consultando a tabela. Com um sal único por usuário, essas tabelas não servem, e o atacante precisa atacar cada senha separadamente.
Funções lentas recomendadas
Para senhas, use uma função feita para ser lenta e, de preferência, para gastar muita memória, o que atrapalha as placas de vídeo. O Argon2id e o bcrypt guardam o sal e os parâmetros dentro do próprio hash. Com o PBKDF2 e o scrypt, você precisa gerar e guardar o sal e os parâmetros por conta própria, ao lado do hash.
Ajuste o custo ao seu servidor. Um bom ponto de partida é um cálculo que leve uma fração de segundo. Para o usuário, essa espera no login quase não aparece. Para quem tenta bilhões de palpites, cada palpite fica milhares de vezes mais caro do que com um hash rápido.
- Argon2id: a variante recomendada do Argon2, vencedor da Password Hashing Competition em 2015. É a primeira escolha para sistemas novos.
- scrypt: também usa muita memória. É uma boa alternativa quando o Argon2id não está disponível.
- bcrypt: de 1999, é lento de propósito e tem um fator de custo ajustável. Aceita senhas de até 72 bytes.
- PBKDF2: padrão antigo e muito disponível. A OWASP recomenda 600.000 iterações de HMAC-SHA-256.
Cuidados no dia a dia
Os parâmetros envelhecem, porque os computadores ficam mais rápidos. Guarde a função e os parâmetros junto com cada hash. Quando você aumentar o custo, atualize o hash no próximo login do usuário: nesse momento, o sistema tem a senha correta em mãos e pode calcular o hash novo.
Compare os hashes em tempo constante, com a função de comparação da sua biblioteca. Uma comparação comum para na primeira diferença, e o tempo da resposta pode dar pistas a um atacante.
Por fim, use a biblioteca de senhas da sua linguagem ou do seu framework, e não monte o esquema sozinho. Junto com um bom hash, ofereça login com dois fatores e limite o número de tentativas por conta.
Algoritmos citados
Outros guias
Precisa enviar um segredo?
Use uma nota segura: o texto é criptografado com AES-256-GCM e se apaga sozinho.