Anúncios incomodam? Ir Sem anúncios Hoje

bcrypt para hash de senhas Por que a criptografia sozinha não é suficiente

Publicado em
bcrypt para hash de senhas: por que a criptografia sozinha não é suficiente 1
ANUNCIADO Remover?

Se você estiver armazenando senhas de usuários com AES, RSA ou até mesmo SHA-256, está fazendo isso errado. Não errado de forma leve — errado de forma fundamental. Este é o erro de segurança mais comum na desenvolvimento web, e tem uma solução direta: use uma função adequada de hash de senha, como o bcrypt.

Aqui está por que isso importa, como o bcrypt funciona e como o código pronto para produção se apresenta.

Por que as senhas precisam de tratamento especial

As maioria das operações criptográficas são projetadas para serem reversíveis ou rápidas. A criptografia é reversível por design — isso é seu propósito inteiro. SHA-256 e MD5 são rápidas, processando gigabytes por segundo. Essas duas propriedades são catastróficas para senhas.

Quando um atacante obtém seu banco de dados, ele obtém seus hashes de senhas. Com criptografia, se eles encontrarem a chave, eles descodificam tudo. Com hashes rápidos como MD5 ou SHA-256, eles executam um ataque de força bruta acelerado por GPU — a hardware moderno pode testar bilhões de hashes MD5 por segundo. Sua “complexa” senha é quebrada em minutos.

As senhas precisam ser:

  1. Não reversíveis — mesmo com a chave ou o algoritmo, você não consegue obter o texto claro de volta
  2. Lentas para calcular — a lentidão deliberada torna os ataques de força bruta impraticáveis
  3. Únicas por usuário — senhas idênticas devem produzir hashes diferentes

O bcrypt satisfaz todas as três. As funções de hash genéricas e a criptografia não o fazem.

Hashing vs Criptografia vs Hash de Senha

Essas não são intercambiáveis:

AbordagemReversível?Rápido?Seguro para senhas?
Criptografia (AES, RSA)Sim — com a chaveSimNão
Hash rápido (MD5, SHA-256)NãoSim (por design)Não
Hash de senha (bcrypt, Argon2id)NãoNão (por design)Sim

A reversibilidade da criptografia é um ponto crítico: comprometer a chave compromete todas as senhas. O rápido hashing também é um ponto crítico: a velocidade permite ataques de força bruta. As funções de hash de senha são projetadas para serem lentas — e isso é o ponto.

Como o bcrypt funciona

O bcrypt, desenvolvido em 1999 por Niels Provos e David Mazières, realiza três coisas importantes:

1. Salting. Antes de hashar, o bcrypt gera um sal aleatório (16 bytes) e o inclui na saída do hash. Mesmo que dois usuários tenham a mesma senha, seus hashes são diferentes. Isso elimina completamente os ataques com tabelas de rainbow pré-calculadas.

2. Fator de trabalho (custo). O bcrypt aceita um parâmetro de custo (normalmente 10–14). Cada incremento dobra o tempo de cálculo. No custo 12, o hash leva aproximadamente 250–400ms em hardware moderno. Isso é lentamente perceptível para uma solicitação de login — mas transforma um ataque de força bruta com bilhões de tentativas em uma operação que dura décadas.

3. A saída é autocontida. Um hash bcrypt parece $2b$12$... e codifica a versão do algoritmo, o fator de custo, o sal e o hash juntos. Você não precisa de uma coluna separada para o sal. Armazene a string inteira.

Código de produção: Node.js e Python

Node.js (bcryptjs ou bcrypt)

const bcrypt = require('bcrypt');

const SALT_ROUNDS = 12;

// Hash a password
async function hashPassword(plaintext) {
  return bcrypt.hash(plaintext, SALT_ROUNDS);
}

// Verify a password against a stored hash
async function verifyPassword(plaintext, storedHash) {
  return bcrypt.compare(plaintext, storedHash);
}

// Usage
const hash = await hashPassword('hunter2');
// Store `hash` in your database

const isValid = await verifyPassword('hunter2', hash);
// true

Python (bcrypt)

import bcrypt

COST = 12

def hash_password(plaintext: str) -> bytes:
    salt = bcrypt.gensalt(rounds=COST)
    return bcrypt.hashpw(plaintext.encode('utf-8'), salt)

def verify_password(plaintext: str, stored_hash: bytes) -> bool:
    return bcrypt.checkpw(plaintext.encode('utf-8'), stored_hash)

# Usage
hashed = hash_password('hunter2')
# Store hashed in your database

is_valid = verify_password('hunter2', hashed)
# True

Armazene a string completa do hash. Nunca armazene o texto claro, nunca armazene o sal separadamente, nunca armazene os valores intermediários.

Você pode testar o hashing do bcrypt interativamente com o

O fator de custo correto depende do seu hardware. O objetivo: tornar cada operação de hash levar 200–500ms no seu servidor de produção. Isso é rápido o suficiente para uma boa experiência do usuário, lento o suficiente para frustrar os atacantes.

Recomendação atual: custo 12 como mínimo, 14 para contas de alto valor (administrador, financeiro). Faça uma benchmark no seu hardware real:

// Node.js: benchmark different cost factors
const bcrypt = require('bcrypt');

for (let cost = 10; cost <= 14; cost++) {
  const start = Date.now();
  await bcrypt.hash('benchmark', cost);
  console.log(`Cost ${cost}: ${Date.now() - start}ms`);
}

Se o custo 12 levar menos de 100ms, aumente. Se o custo 14 levar mais de 1000ms, reduza para 13. Revise anualmente — o hardware se torna mais rápido, e seu fator de custo deve acompanhar.

Você pode testar a hashificação com bcrypt interativamente com o IO Tools bcrypt Hash Generator.

bcrypt vs Argon2id vs scrypt

O bcrypt é testado e amplamente suportado. Mas tem uma limitação: não é difícil de memória. Um atacante com hardware especializado (ASICs ou FPGAs) pode paralelizar ataques com mais eficiência do que com alternativas baseadas em memória.

AlgoritmoDifícil de memóriaResistente à paralelizaçãoRecomendação
bcryptNãoParcialBoa opção padrão; use custo ≥12
scryptSimParcialMelhor que o bcrypt, menos ferramentas
Argon2idSimSimRecomendado para novos projetos

Para novos projetos: use Argon2id. Ganhou a Concorrência de Hash de Senha (2015), é difícil de memória, resiste a ataques de GPU e ASIC, e está agora na recomendação do OWASP. A API é quase idêntica ao bcrypt.

Para projetos existentes: se você já está usando bcrypt com um fator de custo razoável, a migração não é urgente. Adicione isso à sua próxima refatoração principal.

Erros comuns na implementação

Hashando o hash. Alguns desenvolvedores hasham a senha no lado do cliente antes de enviar, e depois hasham novamente no lado do servidor. O hash do lado do cliente se torna a “senha”. Agora você está hashando uma string de hexa de comprimento fixo, e não uma senha escolhida pelo usuário — você perde nada com o duplo hash, mas também não ganha nada, e introduz confusão.

O problema da truncação de 72 bytes. O bcrypt ignora silenciosamente tudo além de 72 bytes. Uma senha de 100 caracteres e uma senha de 72 caracteres que compartilham os primeiros 72 bytes são idênticas para o bcrypt. Se seus usuários definirem senhas muito longas, isso representa uma degradação silenciosa de segurança. Mitigação: hash com SHA-256 antes de passar para o bcrypt — mas apenas se você entender plenamente as implicações, e documentar claramente.

Fator de trabalho fraco. O custo 10 era razoável em 2011. Em 2026, use pelo menos 12. Se seus registros existentes usam custo 10, você pode atualizar transparentemente: após um login bem-sucedido, re-hash a senha verificada com o novo custo e armazene o hash atualizado.

A sincronia importa. O bcrypt é intensivo em CPU. Sempre use a API assíncrona (como mostrado acima) no Node.js para evitar bloquear o loop de eventos. O bcrypt síncrono em um servidor Node fará cada outra requisição esperar.

Migração de MD5/SHA para bcrypt

Você não pode re-hashar sem o texto claro original. Mas você pode migrar oportunisticamente:

  1. Adicione uma password_hash coluna ao lado da antiga password_md5 coluna
  2. Em um login bem-sucedido (quando você tem o texto claro), hash com bcrypt e armazene em password_hash, remova a coluna antiga
  3. Após um período de migração, os usuários que não logaram podem ser forçados a resetar suas senhas
  4. Uma vez password_md5 está vazia para todos os usuários, remova a coluna

Este é o método padrão e exige nenhum tempo de inatividade.

O Resultado Final

A criptografia é para dados que você precisa recuperar. O hashing é para dados que você precisa verificar. As senhas devem ser verificadas, não recuperadas — o que significa que a criptografia é a ferramenta errada.

O bcrypt dá a você salting, lentidão configurável e um formato de hash autocontido. Foi a resposta correta há 25 anos. Use-o com custo 12 ou superior, use Argon2id para novos projetos e migre dos MD5 e SHA-256 o mais cedo possível.

Errar nisso não é um risco hipotético. Bancos de dados são violados. Quando isso acontece, senhas corretamente hashadas com bcrypt são computacionalmente impraticáveis de serem quebradas. Os hashes MD5 são quebrados em poucas horas.

Quer eliminar anúncios? Fique sem anúncios hoje mesmo

Instale nossas extensões

Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida

Ao Extensão do Chrome Ao Extensão de Borda Ao Extensão Firefox Ao Extensão Opera

O placar chegou!

Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!

ANUNCIADO Remover?
ANUNCIADO Remover?
ANUNCIADO Remover?

Notícias com destaques técnicos

Envolver-se

Ajude-nos a continuar fornecendo ferramentas gratuitas valiosas

Compre-me um café
ANUNCIADO Remover?