Calculadora do fator de custo do bcrypt | Calibre o bcrypt na sua CPU, não em uma tabela genérica
A receita clássica da OWASP («use custo 12») e as tabelas de velocidade que circulam em blogs são bons pontos de partida, mas foram escritas para o hardware de outra pessoa. O fator de custo correto depende da CPU específica que executa a produção, do contêiner em que ela vive e do perfil real de tráfego. Esta página executa o bcryptjs no seu próprio navegador, fator por fator, até encontrar o mais alto que ainda cabe no orçamento de latência de login que você definiu.
💡 Sobre esta ferramenta
A cada incremento do fator de custo do bcrypt, o trabalho dobra. Se o custo 10 leva 50 ms em uma máquina, o custo 12 levará uns 200 ms e o custo 14 uns 800 ms. Esse crescimento exponencial é justamente o que dá ao bcrypt sua resistência contra ataques de força bruta, mas também significa que errar em um ou dois pontos deixa seu login arrastado ou o armazenamento de senhas mais frágil do que deveria.
A medição percorre do custo 4 até o teto que você escolheu, faz um hash com bcryptjs em cada um e mostra o tempo medido em cada linha. O custo mais alto que ainda cabe no seu tempo alvo é destacado e, logo abaixo, aparece o prefixo $2b$NN$ pronto para copiar — esse é exatamente o prefixo que os hashes guardados vão carregar, então dá para colar no teste unitário ou no README de deploy. Se alguma linha passar de 8 segundos, a execução é cortada automaticamente para que um notebook ARM lento não trave a página por meio minuto.
A cadeia digitada em «senha de exemplo» só é passada para bcrypt.hash() dentro do seu navegador. Nada é enviado para fora, mas mesmo assim não convém colar uma senha real de produção em um campo de teste; o valor padrão ou qualquer string descartável já basta.
🧐 Perguntas frequentes
Q. Hospedo em uma VPS barata na América do Sul e meu pico é de manhã. Que custo faz sentido? A. Não tem regra fechada: medir na máquina que de fato roda a produção é a única forma honesta. Se a sua API mora num droplet de 1 vCPU no DigitalOcean São Paulo ou numa AWS Lightsail t3.nano, abra esta página direto da sessão dessa instância (porta encaminhada por SSH, Cloud Shell, ou qualquer console Web) e use o resultado. Para máquinas econômicas típicas da região o número costuma cair entre custo 10 e 12 com alvo de 250 ms.
Q. Continuo com bcrypt ou já migro para Argon2id?
A. Para um sistema novo, Argon2id é a primeira recomendação da OWASP — ele é memory-hard e reduz o ganho de fazendas de GPU. bcrypt continua razoável quando o ecossistema te força: password_hash() padrão do PHP, Devise no Rails, Laravel, ASP.NET Identity, pontes para Active Directory. Esta ferramenta atende ao caso real de «já estamos no bcrypt, qual custo colocar?», não a pergunta abstrata «que algoritmo escolher do zero?».
Q. Por que a primeira linha da tabela aparece estranha?
A. O primeiro bcrypt.hash() paga o aquecimento do JIT do V8 e o download do módulo via esm.sh. Toque em «Executar medição» de novo e confie na segunda passagem para decisões de borda. Variação de 5 a 10 % entre execuções é normal — bcryptjs é JavaScript single-thread, não código nativo de tempo constante.
Q. Se eu subir o custo, os usuários atuais perdem a senha?
A. Não. O custo fica gravado em cada hash ($2b$10$... contra $2b$12$...), então hashes antigos seguem sendo validados com o custo original. O caminho saudável é re-hashear no login: quando a autenticação dá certo, confira bcrypt.getRounds() e, se ficar abaixo do novo alvo, refaça o hash com o custo novo e sobrescreva. A transição se distribui ao longo de semanas de tráfego normal em vez de pesar tudo de uma vez.
Q. Meu MacBook chega tranquilo a custo 13, mas o servidor x86 sofre no custo 11. Qual ganha? A. A produção. O Apple Silicon tem hierarquia de memória que deixa o bcrypt anormalmente rápido, então um custo calibrado em Mac quase sempre fica otimista demais para um x86 modesto. Abra esta página numa sessão dentro da máquina-alvo (SSH com encaminhamento de porta, Cloud Run com shell Web) e use esse resultado.
📚 Curiosidades
O número guardado em $2b$NN$ não é a quantidade de rodadas — é o log₂ da quantidade. Custo 12 significa 4 096 rodadas, custo 13 significa 8 192, custo 31 (o máximo teórico) seriam 2 147 483 648 rodadas. Essa codificação logarítmica é o motivo de a especificação precisar apenas de dois caracteres para o fator de custo e ainda assim cobrir uma faixa de mil para um.
Os prefixos 2a, 2b, 2x, 2y que aparecem em hashes antigos não são algoritmos diferentes, são gerações de correção de bugs. $2a$ é o OpenBSD original de 1999; $2x$ e $2y$ são marcadores específicos do PHP de 2011, depois de uma correção no Crypt_Blowfish; $2b$ é o prefixo moderno e correto que se deve gerar hoje. A maioria dos validadores aceita os quatro por compatibilidade, mas hashes novos — inclusive o prefixo que esta ferramenta produz — usam $2b$.