Bcrypt vs Argon2: que hash de palavra-passe em 2026

Bcrypt e Argon2 são as duas funções de hash de palavras-passe mais utilizadas atualmente. Ambas foram concebidas para serem lentas e resistentes a ataques de força bruta, ao contrário de MD5 ou SHA-256, que são rápidas por construção. O Argon2 venceu a Password Hashing Competition em 2015 e é hoje a escolha recomendada pela OWASP para novas aplicações. O Bcrypt continua a ser uma excelente opção, madura e amplamente suportada. Este artigo explica com precisão as diferenças para te ajudar a decidir.

Porque é que um hash de palavra-passe é diferente

Um hash criptográfico clássico como SHA-256 foi concebido para ser rápido: pretende-se processar GB de dados por segundo. Para palavras-passe, essa propriedade é um defeito: um atacante que obtenha a tua tabela de utilizadores pode testar milhares de milhões de palavras-passe por segundo numa GPU. Uma função de hash de palavras-passe (PHF, password hashing function) procura, pelo contrário, ser:

  • Lenta por construção, com um parâmetro de custo ajustável
  • Com sal, para impedir rainbow tables e ataques paralelos sobre várias contas
  • Resistente a hardware especializado (GPU, FPGA, ASIC) para limitar o speedup adversarial

O sal e o parâmetro de custo são armazenados com o hash, numa cadeia única tipicamente com a forma $algo$params$sal$hash. Isto permite aumentar o custo com o tempo sem forçar a migração imediata dos hashes antigos.

Bcrypt: 1999, Blowfish, parâmetro cost

O Bcrypt foi concebido por Niels Provos e David Mazières para o OpenBSD em 1999. Baseia-se no algoritmo de cifra Blowfish, do qual explora o elevado custo de inicialização das tabelas. O Bcrypt expõe um único parâmetro, cost (ou rounds), que define o número de iterações na forma 2^cost. Aumentar cost em 1 duplica o tempo de cálculo.

Formato de saída típico:

$2y$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
 |  |  |                      |
 |  |  cost = 12               sal + hash em base64
 |  variante (2y = openbsd)
 algo bcrypt

O Bcrypt limita a entrada a 72 bytes: uma palavra-passe mais longa é truncada silenciosamente, o que é uma armadilha conhecida. A solução habitual é fazer pré-hash com SHA-256 e depois codificar em base64 antes do bcrypt, mas isto pode introduzir null bytes problemáticos em algumas implementações. O Argon2 não tem essa limitação.

Argon2: 2015, vencedor PHC, 3 variantes

O Argon2 foi concebido por Alex Biryukov, Daniel Dinu e Dmitry Khovratovich. Venceu a Password Hashing Competition em julho de 2015 e está normalizado pelo RFC 9106 (2021). O Argon2 expõe três parâmetros:

  • Memory cost (m): quantidade de memória utilizada, em KiB
  • Time cost (t): número de iterações sobre o bloco de memória
  • Parallelism (p): número de threads paralelas

O Argon2 existe em três variantes:

  • Argon2d: acesso à memória dependente dos dados. Mais resistente a ataques GPU, mas sensível a ataques por canal lateral (timing, cache).
  • Argon2i: acesso à memória independente dos dados. Resistente a side-channels, ligeiramente menos resistente a ataques GPU.
  • Argon2id: híbrido, começa em modo i e depois passa para modo d. Recomendado por omissão pelo RFC 9106 e pela OWASP.

Os parâmetros recomendados pela OWASP em 2026 para Argon2id: m=19456 KiB (19 MiB), t=2, p=1. Formato de saída típico:

$argon2id$v=19$m=19456,t=2,p=1$c2VsX2FsZWF0b2lyZQ$aGFzaF9jYWxjdWxl
 |         |   |                  |                 |
 |         |   parametros          sal base64        hash base64
 |         versao
 algo argon2id

Porque é que o Argon2id é recomendado

A resistência a hardware especializado é hoje o critério decisivo. O Bcrypt utiliza pouca memória (~4 KiB), o que permite a uma GPU topo de gama testar centenas de milhares de hashes por segundo. O Argon2id é memory-hard: forçar vários MiB de memória por tentativa reduz drasticamente o paralelismo atingível em GPU e torna a conceção de ASIC dedicados economicamente inviável.

O modo híbrido do Argon2id oferece ainda proteção contra ataques por canal lateral durante a primeira metade do cálculo. É esta combinação que justifica o seu lugar de recomendação por omissão da OWASP, do NIST SP 800-63B (desde a revisão de 2024) e do RFC 9106.

Tabela comparativa

Critério Bcrypt Argon2id
Ano19992015
NormalizaçãoDe facto, USENIX 1999RFC 9106 (2021)
Parâmetroscostmemory, time, parallelism
Memória utilizada~4 KiBConfigurável (~19 MiB recomendado)
Memory-hardNãoSim
Resistência a GPUModeradaForte
Resistência a side-channelBoa (constant-time)Boa (modo id)
Limite de entrada72 bytesNenhum
Recomendação OWASP 2026AceitávelPreferido
Maturidade do ecossistemaMuito amplaAmpla desde ~2018

Desempenho e resistência a ataques

Num servidor moderno, um bcrypt com cost=12 demora cerca de 250 ms e um argon2id com os parâmetros OWASP cerca de 100 a 300 ms consoante a máquina. O tempo absoluto não é o critério: o que importa é a relação entre o teu custo (um cálculo, uma vez por login) e o do atacante (milhares de milhões de cálculos em GPU para quebrar um dump).

Numa RTX 4090, o hashcat atinge cerca de 200 000 bcrypt/s com cost=12, contra algumas dezenas de milhares de argon2id a 19 MiB. Para o mesmo tempo de cálculo do lado do servidor, o Argon2id atrasa o atacante 5 a 10 vezes mais do que o bcrypt, e a diferença aumenta com as novas gerações de GPU.

Exemplos PHP

O PHP suporta ambos nativamente através de password_hash() e password_verify() desde o PHP 7.2 para Argon2i (e 7.3 para Argon2id). O construtor PHP gere sal e formato automaticamente.

Bcrypt

$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$ok   = password_verify($password, $hash);

if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
    $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
}

Argon2id

$opts = [
    'memory_cost' => 19456,  // 19 MiB
    'time_cost'   => 2,
    'threads'     => 1,
];
$hash = password_hash($password, PASSWORD_ARGON2ID, $opts);
$ok   = password_verify($password, $hash);

if (password_needs_rehash($hash, PASSWORD_ARGON2ID, $opts)) {
    $hash = password_hash($password, PASSWORD_ARGON2ID, $opts);
}

Podes gerar ou identificar hashes de todos os tipos com o nosso gerador de hash e o nosso identificador de hash.

Recomendação

Para uma nova aplicação em 2026, escolhe Argon2id com os parâmetros OWASP como baseline (m=19456, t=2, p=1), a ajustar conforme o tempo pretendido (tipicamente 250 a 500 ms). Se manténs uma aplicação existente em bcrypt, não há urgência em migrar: bcrypt com cost=12 ou superior continua seguro em 2026. Aproveita um password_needs_rehash() no próximo login para migrar progressivamente os utilizadores ativos para Argon2id.

Evita absolutamente MD5, SHA-1 e SHA-256 simples para palavras-passe (ver o nosso comparativo MD5 vs SHA-256). Nenhum destes algoritmos foi concebido para esse uso.

Perguntas frequentes

O Bcrypt ainda é seguro em 2026?

Sim, desde que se utilize um cost suficiente (12 no mínimo, 14 se possível). O Bcrypt não tem nenhuma falha criptográfica conhecida. A sua única fraqueza relativa face ao Argon2id é a sua reduzida utilização de memória, que o torna mais acessível a ataques GPU e FPGA.

É preciso migrar uma base bcrypt para Argon2id?

Não com urgência. Uma migração progressiva com password_needs_rehash() é a abordagem recomendada: a cada login bem-sucedido, voltas a calcular o hash da palavra-passe em Argon2id. Ao fim de alguns meses, a maioria dos utilizadores ativos está migrada, e podes forçar uma reposição para as contas inativas.

Qual é o número correto de threads para Argon2id?

A OWASP recomenda p=1 por omissão. Aumentar p não traz nada se o teu servidor web já trata muitos pedidos em paralelo, e complica o tuning. Prefere antes aumentar m (memória), que é a principal alavanca de resistência a GPU.

O que é um « bcrypt decrypter »?

Não existe um descodificador bcrypt: a função é de sentido único por construção. As ferramentas que afirmam « descodificar » bcrypt limitam-se a testar dicionários de palavras-passe comuns contra o hash. É exatamente o mesmo que faria um atacante que tivesse a tua tabela.

Argon2i ou Argon2id?

Argon2id em todos os casos para palavras-passe. O Argon2i é ligeiramente mais seguro face a side-channels, mas mais fraco face a ataques GPU. O Argon2id combina as vantagens de ambos e é explicitamente recomendado pelo RFC 9106 para o hash de palavras-passe.

É preciso aplicar pepper além do sal?

O sal é suficiente para a grande maioria das aplicações. Um pepper (chave secreta armazenada fora da base de dados e usada como HMAC antes do hash) acrescenta uma camada em caso de fuga da base sem comprometimento do servidor aplicacional. O Argon2id não o fornece nativamente, é preciso compô-lo manualmente.