Bcrypt vs Argon2: ¿qué hash de contraseña en 2026?

Bcrypt y Argon2 son las dos funciones de hash de contraseñas más utilizadas hoy en día. Ambas están diseñadas para ser lentas y resistentes a los ataques por fuerza bruta, a diferencia de MD5 o SHA-256, que son rápidas por construcción. Argon2 ganó la Password Hashing Competition en 2015 y es ahora la opción recomendada por OWASP para las nuevas aplicaciones. Bcrypt sigue siendo una excelente opción madura y ampliamente soportada. Este artículo explica con precisión las diferencias para ayudarte a decidir.

Por qué un hash de contraseña es diferente

Un hash criptográfico clásico como SHA-256 está diseñado para ser rápido: se busca hashear GB de datos por segundo. Para las contraseñas, esta propiedad es un defecto: un atacante que obtiene tu tabla de usuarios puede probar miles de millones de contraseñas por segundo en una GPU. Una función de hash de contraseña (PHF, password hashing function) busca al contrario ser:

  • Lenta por construcción, con un parámetro de coste ajustable
  • Salada, para impedir las rainbow tables y los ataques paralelos sobre varias cuentas
  • Resistente al hardware especializado (GPU, FPGA, ASIC) para limitar el speedup adversarial

La sal y el parámetro de coste se almacenan con el hash, en una cadena única típicamente con la forma $algo$params$sal$hash. Esto permite aumentar el coste con el tiempo sin forzar la migración inmediata de los hashes antiguos.

Bcrypt: 1999, Blowfish, parámetro cost

Bcrypt fue diseñado por Niels Provos y David Mazières para OpenBSD en 1999. Se basa en el algoritmo de cifrado Blowfish, del que aprovecha el alto coste de inicialización de las tablas. Bcrypt expone un único parámetro, cost (o rounds), que define el número de iteraciones con la forma 2^cost. Aumentar cost en 1 duplica el tiempo de cálculo.

Formato de salida típico:

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

Bcrypt limita la entrada a 72 bytes: una contraseña más larga se trunca silenciosamente, lo que es una trampa conocida. La solución habitual es pre-hashear con SHA-256 y luego codificar en base64 antes de bcrypt, pero esto puede introducir null bytes problemáticos en algunas implementaciones. Argon2 no tiene este límite.

Argon2: 2015, ganador de la PHC, 3 variantes

Argon2 fue diseñado por Alex Biryukov, Daniel Dinu y Dmitry Khovratovich. Ganó la Password Hashing Competition en julio de 2015 y está estandarizado por la RFC 9106 (2021). Argon2 expone tres parámetros:

  • Memory cost (m): cantidad de memoria utilizada, en KiB
  • Time cost (t): número de iteraciones sobre el bloque de memoria
  • Parallelism (p): número de hilos paralelos

Argon2 existe en tres variantes:

  • Argon2d: acceso a memoria dependiente de los datos. Más resistente a los ataques GPU, pero sensible a los ataques por canal lateral (timing, caché).
  • Argon2i: acceso a memoria independiente de los datos. Resistente a los side-channels, ligeramente menos resistente a los ataques GPU.
  • Argon2id: híbrido, comienza en modo i y luego pasa a modo d. Recomendado por defecto por la RFC 9106 y OWASP.

Los parámetros recomendados por OWASP en 2026 para Argon2id: m=19456 KiB (19 MiB), t=2, p=1. Formato de salida típico:

$argon2id$v=19$m=19456,t=2,p=1$c2VsX2FsZWF0b2lyZQ$aGFzaF9jYWxjdWxl
 |         |   |                  |                 |
 |         |   parametres          sel base64        hash base64
 |         version
 algo argon2id

Por qué se recomienda Argon2id

La resistencia al hardware especializado es hoy el criterio decisivo. Bcrypt utiliza poca memoria (~4 KiB), lo que permite a una GPU de gama alta probar cientos de miles de hashes por segundo. Argon2id es memory-hard: forzar varios MiB de memoria por intento reduce drásticamente el paralelismo alcanzable en GPU y hace que el diseño de ASIC dedicados sea económicamente no rentable.

El modo híbrido de Argon2id ofrece además una protección contra los ataques por canal lateral durante la primera mitad del cálculo. Es esta combinación la que justifica su posición de recomendación por defecto de OWASP, del NIST SP 800-63B (desde la revisión de 2024) y de la RFC 9106.

Tabla comparativa

Criterio Bcrypt Argon2id
Año19992015
EstandarizaciónDe facto, USENIX 1999RFC 9106 (2021)
Parámetroscostmemory, time, parallelism
Memoria utilizada~4 KiBConfigurable (~19 MiB recomendado)
Memory-hardNo
Resistencia GPUModeradaFuerte
Resistencia side-channelBuena (constant-time)Buena (modo id)
Límite de entrada72 bytesNinguno
Recomendación OWASP 2026AceptablePreferido
Madurez del ecosistemaMuy ampliaAmplia desde ~2018

Rendimiento y resistencia a los ataques

En un servidor moderno, un bcrypt con cost=12 tarda alrededor de 250 ms y un argon2id con los parámetros OWASP entre 100 y 300 ms según la máquina. El tiempo absoluto no es el criterio: lo que cuenta es la relación entre tu coste (un cálculo, una vez por login) y el del atacante (miles de millones de cálculos en GPU para romper un dump).

En una RTX 4090, hashcat alcanza unos 200 000 bcrypt/s con cost=12, frente a unas pocas decenas de miles de argon2id a 19 MiB. Para el mismo tiempo de cálculo en el servidor, Argon2id ralentiza al atacante 5 a 10 veces más que bcrypt, y la brecha se ensancha con las nuevas generaciones de GPU.

Ejemplos PHP

PHP soporta ambos de forma nativa mediante password_hash() y password_verify() desde PHP 7.2 para Argon2i (y 7.3 para Argon2id). El constructor de PHP gestiona la sal y el formato automáticamente.

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);
}

Puedes generar o identificar hashes de todo tipo con nuestro generador de hash y nuestro identificador de hash.

Recomendación

Para una nueva aplicación en 2026, elige Argon2id con los parámetros OWASP como base (m=19456, t=2, p=1), a ajustar según el tiempo objetivo (típicamente entre 250 y 500 ms). Si mantienes una aplicación existente con bcrypt, no hay urgencia para migrar: bcrypt con cost=12 o más sigue siendo seguro en 2026. Aprovecha un password_needs_rehash() en el siguiente login para migrar progresivamente a los usuarios activos a Argon2id.

Evita absolutamente MD5, SHA-1 y SHA-256 a secas para las contraseñas (consulta nuestra comparativa MD5 vs SHA-256). Ninguno de estos algoritmos está diseñado para este uso.

Preguntas frecuentes

¿Es bcrypt todavía seguro en 2026?

Sí, siempre que utilices un cost suficiente (12 como mínimo, 14 si es posible). Bcrypt no tiene ninguna vulnerabilidad criptográfica conocida. Su única debilidad relativa frente a Argon2id es su baja huella de memoria, que lo hace más accesible a los ataques con GPU y FPGA.

¿Hay que migrar una base bcrypt a Argon2id?

No urgentemente. Una migración progresiva con password_needs_rehash() es el enfoque recomendado: en cada login exitoso, vuelves a hashear la contraseña con Argon2id. Al cabo de unos meses, la mayoría de los usuarios activos están migrados, y puedes forzar un restablecimiento para las cuentas inactivas.

¿Cuál es el buen número de hilos para Argon2id?

OWASP recomienda p=1 por defecto. Aumentar p no aporta nada si tu servidor web ya procesa muchas peticiones en paralelo, y complica el tuning. Es preferible aumentar m (memoria), que es la principal palanca de resistencia a GPU.

¿Qué es un «bcrypt decrypter»?

No existe ningún descifrador de bcrypt: la función es de un solo sentido por construcción. Las herramientas que pretenden «descifrar» bcrypt solo prueban diccionarios de contraseñas comunes contra el hash. Es exactamente lo mismo que haría un atacante que tuviera tu tabla.

¿Argon2i o Argon2id?

Argon2id en todos los casos para las contraseñas. Argon2i es ligeramente más seguro frente a los side-channels pero más débil frente a los ataques GPU. Argon2id combina las ventajas de ambos y está explícitamente recomendado por la RFC 9106 para el hash de contraseñas.

¿Hay que pimentar (pepper) además de la sal?

La sal basta para la gran mayoría de las aplicaciones. Una pimienta (clave secreta almacenada fuera de la base de datos y utilizada como HMAC antes del hash) añade una capa en caso de fuga de la base de datos sin compromiso del servidor de aplicación. Argon2id no la proporciona de forma nativa, hay que componerla manualmente.