Senhas com hash explicadas: segurança simples de senhas para fundadores
Entenda o que são senhas com hash, como criar fluxos de login seguros e as armadilhas comuns que levam fundadores a armazenar ou enviar senhas por engano.

Por que a segurança de senhas vira seu problema
Se você roda um app com contas, você está no negócio de senhas. No momento em que coleta uma senha, você está segurando algo que atacantes querem e que os usuários esperam que você proteja.
Apps pequenos também são alvos. Bots escaneiam a internet sem parar em busca de vitórias fáceis: bancos de dados expostos, configurações administrativas fracas, variáveis de ambiente vazadas ou logs de depuração que capturaram dados sensíveis por acidente. Estar em estágio inicial não significa estar mais seguro. Geralmente significa menos gente para perceber um problema rapidamente e menos horas para consertá-lo.
Se senhas vazarem, o dano se espalha além do seu app. Pessoas reutilizam senhas, então um vazamento pode levar a invasões de email, bancos e outros serviços. Você também pode perder confiança da noite para o dia, lidar com estornos e passar semanas limpando em vez de construir.
O objetivo é simples: você nunca deveria conseguir ler a senha de um usuário. Nem no seu banco, nem no painel administrativo, nem em um tíquete de suporte, nem em um email. É por isso que apps armazenam senhas com hash: uma versão unidirecional que pode ser verificada no login, mas não pode ser transformada de volta na senha original.
O manuseio de senhas costuma dar errado de maneiras muito comuns:
- Armazenar senhas em texto claro, mesmo “temporariamente” durante o cadastro
- Enviar senhas por email para usuários ou para sua equipe para suporte
- Logar requisições de cadastro ou login (incluindo senhas) durante a depuração
- Copiar senhas para ferramentas de analytics, planilhas ou mensagens de chat
- Entregar um protótipo gerado por IA que “funciona” mas pula salvaguardas básicas
Um cenário comum: um fundador testa um protótipo construído por IA e pede que os usuários “respondam com a senha que usaram” quando o login falha. Mesmo que você apague o email depois, ele pode ficar em caixas de entrada, backups e ferramentas de suporte. Corrigir isso normalmente significa reconstruir o fluxo de autenticação para que senhas nunca saiam do lugar certo.
Times como FixMyMess veem esse padrão com frequência em builds apressados. A vitória mais rápida é remover todo caminho onde uma senha poderia ser vista, copiada ou reproduzida.
O que “senhas hash” significa em linguagem simples
Uma senha com hash é o que você obtém quando roda uma senha por uma função especial que a transforma em uma longa string de aparência aleatória. Pense nisso como colocar ingredientes num liquidificador e obter um smoothie. Você pode comparar smoothies, mas não consegue tirar os morangos originais de volta.
Então quando as pessoas dizem “nós armazenamos senhas com hash”, querem dizer que o banco guarda o smoothie, não os ingredientes.
O que é salvo normalmente é um registro que inclui a saída do hash, o método usado e uma aleatoriedade extra adicionada durante o hashing (frequentemente armazenada junto).
Hashing é unidirecional de propósito. Se alguém roubar seu banco, não deveria conseguir reverter os valores armazenados para senhas reais. Nem você, como dono do app, deveria conseguir ler as senhas dos usuários.
Por isso também enviar senhas por email é um grande sinal vermelho. Se você consegue enviar, significa que em algum lugar você tem a senha em forma legível.
Como o login funciona se você não armazena a senha? Quando um usuário faz login, seu app faz o hash da senha que ele digitou usando o mesmo método e compara esse resultado com o hash armazenado.
Se baterem, a senha estava correta. Se não, o acesso é negado. Ninguém precisa “procurar” a senha.
Se você herdou um app gerado por IA que armazena senhas em texto claro ou as envia por email durante o cadastro, isso normalmente é rápido de corrigir e remove uma grande parte do risco antes do lançamento.
Hashing vs criptografia vs codificação (comparação rápida)
As pessoas confundem porque todos “mudam” dados. Mas eles foram feitos para trabalhos diferentes, e as senhas têm uma regra clara: você não deve ser capaz de recuperar a senha original a partir do que você armazena.
Hashing é unidirecional. Criptografia é bidirecional. Codificação é apenas uma mudança de formato.
- Hashing transforma uma senha numa string que não pode ser revertida. No login, você hash o que o usuário digitou e compara com o hash armazenado.
- Criptografia embaralha dados de forma que podem ser revertidos com uma chave. Se um atacante roubar a chave, ele pode descriptografar os dados.
- Codificação (Base64, URL encoding, etc.) facilita armazenar ou transmitir dados. Qualquer um pode decodificar. Não oferece segurança.
Se seu sistema diz “nós podemos descriptografar depois”, esse é o modelo errado para senhas. A capacidade de descriptografar senhas vira uma responsabilidade.
Onde a criptografia ainda é útil
Criptografia continua importante, só não para armazenar senhas. Use-a para coisas que o app precisa ler depois, como chaves de API e tokens de acesso, dados sensíveis de usuário, backups e informação que se move entre sistemas.
Um teste simples: se seu app envia por email “sua senha é…”, isso significa que você a armazenou de forma reversível em algum lugar. Conserte antes do lançamento. Um sistema adequado não conhece a senha original depois do cadastro.
Como cadastro e login devem funcionar (passo a passo)
Um sistema de login seguro se resume a uma regra: seu app não deveria precisar lembrar a senha real do usuário depois do momento em que ele a digita.
Fluxo de cadastro e login (versão segura)
A maioria dos apps modernos segue um padrão simples e confiável:
- Cadastro: o usuário digita uma senha, seu servidor a hasha e você armazena apenas o hash.
- Login: o usuário digita a senha, seu servidor hasha o que ele digitou da mesma maneira e compara com o hash salvo.
- Resultado: se os hashes baterem, o login tem sucesso. Se não, falha. Nada é descriptografado.
Mantenha mensagens de erro genéricas. Evite dizer “email não encontrado” vs “senha errada”, pois isso ajuda atacantes a descobrir contas válidas.
O que nunca deve aparecer em logs ou analytics
Muitas violações começam com logging “útil”. Não registre segredos. Isso inclui senhas, hashes de senha, tokens de reset, magic links, tokens de sessão, cabeçalhos de autenticação e corpos completos de requisições de endpoints de auth.
Após um login bem-sucedido, você não deve continuar enviando a senha por aí. O servidor deve criar um token de sessão (uma string randômica que prova que o usuário já fez login) e retorná-lo para o app. O app usa esse token em requisições futuras.
Se você herdou código de auth gerado por IA, verifique se ele segue esse fluxo exato. É comum encontrar senhas logadas, armazenadas em texto claro ou enviadas para analytics “para depuração”. Esses são consertos de alto risco, mas geralmente rápidos de fazer.
Escolhendo o método de hashing certo
Se seu banco vazar, atacantes não deveriam conseguir transformar rapidamente hashes roubados em senhas reais.
A ideia-chave é “hash lento”. Um bom hash de senha é intencionalmente caro de computar. Seu servidor verifica um login por vez. Um atacante tenta bilhões de adivinhações. Hash lento prejudica muito mais o atacante do que você.
Boas opções (e por que são comuns)
A maioria das equipes escolhe um método de hashing bem conhecido para senhas:
- Argon2id: um padrão moderno projetado para ser difícil de quebrar com GPUs.
- bcrypt: mais antigo, amplamente usado e bem entendido.
- scrypt: também difícil em memória e uma opção razoável quando Argon2 não está disponível.
Se você não é especialista em segurança, um padrão sensato é: escolha Argon2id se for suportado, caso contrário bcrypt. Comece com as configurações recomendadas da biblioteca e só ajuste se tiver um motivo claro.
Por que SHA-256 é uma escolha ruim para senhas
Hashes de uso geral como SHA-256 são rápidos por projeto. Isso é ótimo para checagens de arquivo e assinaturas, mas perigoso para senhas. Hashes rápidos permitem que atacantes testem um grande número de tentativas por segundo. Mesmo se você “hashar duas vezes”, geralmente continua rápido demais.
Uma regra prática: não invente sua própria solução. Use uma biblioteca de autenticação bem conhecida ou um recurso confiável do seu framework.
Salts e peppers sem jargão
Se lembrar de uma coisa sobre senhas com hash, que seja esta: a mesma senha não deveria gerar o mesmo valor armazenado para cada usuário.
Salt: um “extra” único por usuário
Um salt é um valor aleatório gerado para cada conta quando a senha é definida. O sistema mistura o salt com a senha antes de hashar e então armazena o salt junto com o hash.
Isso importa em um vazamento de banco. Sem salts, dois usuários que escolheram “Summer2026!” teriam o mesmo hash. Atacantes podem ver repetições e adivinhar senhas comuns mais rapidamente.
Com salts únicos, mesmo que 1.000 pessoas reutilizem a mesma senha, os hashes armazenados parecerão todos diferentes.
Pepper: um segredo fora do banco de dados
Um pepper é outro valor misturado antes do hash, mas diferente do salt, ele não é armazenado no banco. Vive na configuração do servidor para permanecer secreto mesmo se o banco for exposto.
Peppers só são úteis se você consegue proteger e rotacionar segredos do app corretamente. São uma camada extra, não substituem o básico bem feito.
Uma checklist amigável para fundadores:
- O salt deve ser randômico e único por usuário, gerado automaticamente.
- O salt pode ser armazenado no banco junto com o hash.
- O pepper, se usado, deve ficar fora do banco de dados e ser tratado como um segredo de alto valor.
Um problema comum em código de auth gerado por IA é um “salt” fixo e hardcoded compartilhado por todos os usuários. Parece salting, mas anula o propósito.
Erros comuns que criam dívida técnica de segurança instantânea
A maioria dos desastres com senhas não é “mágica de hacker”. Começa com atalhos em builds apressados e vira hábito no produto e no suporte.
O maior sinal de alerta é armazenar senhas em texto claro em qualquer lugar: banco, planilhas, painéis administrativos, notas ou tabelas “temporárias”. Se alguém pode ler, eventualmente vai vazar.
Outro erro comum é enviar senhas por email ou DM, mesmo que temporário. Caixas de entrada são encaminhadas, compartilhadas e sincronizadas em dispositivos. Isso também treina usuários a aceitar mensagens arriscadas que imitam sua marca.
A depuração pode criar o mesmo problema silenciosamente. Se seu app loga corpos de requisição completos em signup ou login, você pode estar salvando senhas em logs de servidor, ferramentas de analytics, relatórios de crash ou tíquetes de suporte. Esses sistemas muitas vezes têm amplo acesso dentro do time.
Padrões que geram dívida de segurança rápido incluem armazenamento legível de senhas, funcionalidades “admin pode ver senha do usuário”, imprimir senhas em logs durante testes, copiar senhas para chats de suporte e pedir que usuários enviem suas senhas “para verificar”.
Uma regra simples ajuda: seu app nunca deve conseguir mostrar a senha original de um usuário, porque só deve armazenar hashes.
Se precisar dar suporte, prefira ferramentas que não exijam acesso a senhas: links de reset, logs e tíquetes redigidos e ações como revogar sessões ou reenviar um reset.
Redefinições de senha e proteções básicas que funcionam de verdade
Um fluxo de “esqueci a senha” não é sobre enviar a senha antiga. Com senhas hasheadas, o servidor só pode checar uma senha, não recuperá-la.
Um reset seguro usa um token único e com tempo limitado. O usuário prova que controla o email (ou telefone) vinculado à conta e então define uma nova senha.
Um fluxo padrão é assim:
- O usuário insere o email e solicita reset.
- Seu app gera um token aleatório, armazena somente uma versão hash desse token e define um prazo (por exemplo 15–60 minutos).
- Você envia uma mensagem de reset contendo o token.
- Quando o usuário abre, você verifica o token e o prazo, então permite que ele defina uma nova senha.
- Você invalida o token após o uso e, opcionalmente, encerra outras sessões.
Não revele se uma conta existe. Mostre sempre a mesma mensagem, por exemplo: “Se existir uma conta para esse email, você receberá um link de redefinição.” Isso previne ataques de enumeração de contas.
Proteções básicas não precisam ser sofisticadas para funcionar. Rate limiting, bloqueios curtos após falhas repetidas, alertas ao usuário por resets ou logins novos e expiração de sessão após um reset impedem muitos abusos.
Em apps gerados por IA, um bug comum em reset é um token que nunca expira, pode ser reutilizado ou é logado em texto claro. Pequenos consertos aqui evitam um incidente grande.
Exemplo realista: consertando uma autenticação quebrada antes do lançamento
Um fundador solo envia um app gerado por IA com um formulário de login que “funciona”. Por baixo, a tabela do banco tem uma coluna password com o texto exato da senha. O app até envia a senha por email durante o cadastro “para os usuários não esquecerem”. Parece útil, mas é perigoso.
O risco aparece de formas normais. Um usuário pede suporte: “Vocês podem me dizer minha senha?” Alguém abre um painel admin e vê senhas em texto claro. Ou um snapshot do banco é compartilhado com um contratado e de repente mais pessoas têm acesso às senhas reais. Às vezes é pior: senhas entram em logs de servidor durante depuração.
A correção não é “esconder a coluna”. A correção é mudar para senhas hasheadas para que o sistema armazene apenas uma impressão unidirecional da senha. Na prática, isso significa adicionar um campo password_hash, atualizar o cadastro para hashar antes de salvar, atualizar o login para verificar o hash, remover qualquer código que envie senhas por email e limpar logs que possam contê-las.
Lidar com usuários existentes é a parte delicada. A maioria das equipes escolhe uma dessas opções:
- Reset forçado: marque todas as contas como precisando reset, envie um link de reset e pare de aceitar as senhas antigas.
- Atualização gradual: mantenha o campo antigo temporariamente e, quando um usuário fizer login com sucesso, substitua pela hash e delete a senha em texto claro.
- Híbrido: force resets para administradores e contas de alto risco, atualize as demais no próximo login.
Depois de escolher, teste jornadas reais de usuário (cadastro, login, reset, logout) e confirme que nada quebrou.
Um estado final seguro se parece com isto:
- Sem senhas em texto claro em nenhum lugar (banco, logs, vistas admin, emails).
- Contas novas armazenam apenas hashes, e o login verifica de forma segura.
- Fluxo de reset funciona e não revela se um email existe.
- Dados antigos de senha são apagados após a migração.
- Proteções básicas estão ativas (rate limits, bloqueios e mensagens de erro seguras).
Checklist rápido antes do lançamento
Faça essas checagens uma vez antes dos primeiros usuários reais. Elas pegam a maioria dos problemas de senhas deixados “para consertar depois”, especialmente em apps construídos rapidamente ou com ferramentas de IA.
- Banco de dados: confirme que você guarda apenas hashes de senha (mais um salt único). Não deve existir backup, tabela “temporária” ou coluna sobrando que mantenha senhas em texto claro.
- Logs e relatórios de erro: force um login falho e um erro de cadastro de propósito e depois inspecione logs de requisição e relatórios de crash. Campos de senha devem estar redigidos.
- Redefinição de senha: teste o fluxo completo. Tokens devem expirar, ser de uso único e ser invalidados depois que a senha muda.
- Ferramentas admin e suporte: verifique se nenhuma interface interna pode revelar ou exportar senhas. Se uma tela de suporte mostrar “senha atual”, trate como bug crítico.
- Segredos e chaves: escaneie seu repositório e configurações de deploy por API keys, URLs de banco ou segredos JWT expostos. Eles devem viver em variáveis de ambiente, não em código ou dashboards compartilhados com contratados.
Uma maneira prática de começar: pesquise no código por password, reset, token, log e debug. Se ver o app armazenando um valor de senha, enviando por email ou logando, trate como issue de embarque proibido.
Se a autenticação parecer frágil (resets quebrados, segredos expostos, comportamento estranho de sessão), uma auditoria focada pode salvar você de um incidente no dia do lançamento.
Próximos passos se seu app foi construído rápido (ou por IA)
Se seu app foi feito rapidamente, assuma que autenticação e tratamento de senhas podem estar errados até provar o contrário. Isso é especialmente verdadeiro com código gerado por IA, onde é comum ver senhas logadas, armazenadas em texto claro ou copiadas para emails durante “testes”. Mesmo que você já use hashes, erros em resets, sessões e segredos ainda podem colocar usuários em risco.
Um bom momento para uma revisão externa é antes de convidar usuários reais, ativar pagamentos ou lançar em domínio público. Outro gatilho é código de auth bagunçado: múltiplas rotas de login, criptografia caseira ou backdoors administrativos “temporários” que nunca foram removidos.
Uma revisão prática de segurança normalmente cobre:
- Cadastro, login, sessões, logout e reset de senha
- Varredura de segredos (API keys, URLs de banco, tokens, commits acidentais)
- Endurecimento (rate limits, lockouts, mensagens seguras, proteções CSRF quando aplicável)
- Tratamento de dados (o que é logado, enviado por email ou armazenado em analytics)
- Uma lista curta de correções ordenadas por risco e esforço
Se você herdou um protótipo gerado por IA, FixMyMess em fixmymess.ai foca em diagnosticar a base de código e corrigir problemas como armazenamento inseguro de senhas, segredos expostos e fluxos de autenticação frágeis para deixar o app pronto para produção.
Prazos podem ser mais rápidos do que você imagina. Muitos projetos podem ser diagnosticados e corrigidos em 48–72 horas, dependendo de quão emaranhado está o código de auth e se existem problemas escondidos como segredos expostos ou checagens de autorização quebradas.
Se você está decidindo entre aplicar patches e reconstruir, use uma regra simples: faça patches quando a estrutura do app for sólida; reconstrua quando a fundação estiver instável.
Sinais de que uma reconstrução é mais segura:
- Lógica de auth espalhada por muitos arquivos com regras inconsistentes
- Fluxos de reset personalizados e difíceis de entender
- Segredos embutidos no frontend ou no histórico do repositório
- Falta de separação clara entre usuários, papéis e permissões
- Correções continuam causando novos bugs em partes não relacionadas do app
Perguntas Frequentes
Por que a segurança de senhas é meu problema se eu só tenho um app pequeno?
Você está coletando um segredo que atacantes procuram ativamente, e as pessoas esperam que você o proteja. Se vazar, quem reutilizou aquela senha pode ser afetado além do seu app, e você passará tempo limpando o problema em vez de construir.
O que “senhas hash” significa na prática?
Hashing transforma a senha em uma “impressão” unidirecional que pode ser comparada no login, mas não pode ser revertida para a senha original. O banco de dados guarda essa impressão, não a senha em si, então nem você consegue lê-la de volta.
Não posso apenas criptografar senhas em vez de hashar?
Não. Criptografar é reversível se alguém tem a chave, o que permite recuperar as senhas originais se a chave vazar. Senhas devem ser armazenadas com funções de hash próprias para senhas, sem nada para descriptografar depois.
Qual é um bom método de hash por padrão para um app web típico?
Use Argon2id se seu stack suportar; caso contrário, bcrypt é uma opção sólida. O objetivo principal é um hash lento e projetado para senhas, para que hashes roubados sejam caros de quebrar.
Preciso de salts ou peppers, e qual a diferença?
Um salt é um valor randômico único, armazenado com o hash do usuário, que garante que senhas idênticas gerem valores armazenados diferentes. Um pepper é um segredo adicional mantido fora do banco de dados; ajuda, mas só se você gerenciar segredos e rotações corretamente.
E se meu app logou senhas por acidente durante a depuração?
Trate como um problema crítico que impede o lançamento. Remova ou redija logs de endpoints de autenticação, rotacione quaisquer tokens expostos e atualize o logging para que corpos de requisição e campos sensíveis nunca sejam armazenados.
Meu recurso “esqueci a senha” deve enviar a senha antiga por email?
Não. Um fluxo de reset adequado envia um link ou código único e com tempo limitado para que o usuário defina uma nova senha, pois você não consegue recuperar a antiga quando armazena apenas hashes.
Meu banco de dados já tem senhas em texto claro — qual a maneira mais segura de consertar?
Não tente só “esconder” a coluna. Mude para armazenar hashes, remova código que envia ou exibe senhas e migre usuários forçando reset ou atualizando para hashes quando fizerem login com sucesso.
Alguma vez é aceitável que um admin veja a senha de um usuário para suporte?
Não. Se uma tela administrativa revela senhas, significa que elas estão armazenadas em forma legível em algum lugar — isso é arriscado. Suporte deve usar resets, revogação de sessões e recuperação segura de conta.
Construí meu app com uma ferramenta de IA — que problemas de senha/autenticação devo esperar?
Assuma que a autenticação está errada até provar o contrário; builds rápidos costumam armazenar senhas, vazar segredos ou usar tokens de reset de forma imprudente. Se quiser uma checagem prática, FixMyMess pode auditar seu código e corrigir tratamentos de senha inseguros rapidamente.