¿Qué es una función hash?
Una función hash criptográfica toma una entrada de cualquier longitud y produce una salida de longitud fija (el hash o resumen). Tres propiedades definen una buena función hash:
- **Determinista**: la misma entrada da siempre la misma salida
- **De un solo sentido**: no puedes dar marcha atrás para recuperar la entrada
- **Resistente a colisiones**: debería ser inviable encontrar dos entradas distintas que produzcan el mismo hash
Cada algoritmo ofrece un equilibrio distinto entre velocidad, resistencia a colisiones y resistencia a los ataques de fuerza bruta.
MD5 (salida de 128 bits)
MD5 se diseñó en 1991 y fue el algoritmo estándar durante buena parte de los años noventa y dos mil. Produce un hash de 128 bits (32 caracteres hexadecimales). El problema: en 2004 se demostraron ataques de colisión contra MD5, y después llegaron los ataques prácticos. Hoy puedes generar una colisión de MD5 en menos de un segundo con hardware normal.
**Todavía aceptable para:** sumas de verificación de integridad donde la seguridad no importa, como comprobar que un archivo descargado coincide con el hash publicado cuando nadie intenta sustituirlo a propósito. Es rápido y lo admite todo el mundo.
**No lo uses nunca para:** contraseñas, firmas, certificados ni nada donde alguien pueda intentar falsificar un hash.
MD5("hello") = 5d41402abc4b2a76b9719d911017c592
SHA-256 (salida de 256 bits)
SHA-256 forma parte de la familia SHA-2, diseñada por la NSA y publicada en 2001. Produce una salida de 256 bits (64 caracteres hexadecimales) y no existe ningún ataque de colisión práctico. Es el estándar actual para firmas digitales, certificados TLS, firma de código y comprobación de integridad.
**Úsalo para:** verificar la integridad de archivos, autenticación con HMAC, firmas digitales, cadenas de bloques (Bitcoin usa SHA-256), firma de peticiones de API y cualquier suma de verificación que deba ser segura.
**No lo uses para:** guardar contraseñas. SHA-256 está diseñado para ser rápido, y rápido significa que una tarjeta gráfica calcula miles de millones de hashes por segundo, lo que hace viables los ataques de fuerza bruta.
SHA-256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
HMAC-SHA256
HMAC (código de autenticación de mensajes basado en hash) combina una clave secreta con SHA-256 para producir un hash. A diferencia de un SHA-256 a secas, un HMAC no se puede falsificar sin conocer la clave. Es lo que usan los JWT en su firma: la cabecera y el contenido van firmados con un secreto del servidor, así que quien recibe el token no puede manipularlo.
Bcrypt (la salida incluye la sal y el factor de coste)
Bcrypt se diseñó en 1999 específicamente para guardar contraseñas. Su característica clave es un factor de trabajo configurable (también llamado coste o rondas). Duplicar ese factor duplica el tiempo de cálculo, lo que permite ajustar bcrypt para que siga siendo lento a medida que el hardware mejora y los ataques de fuerza bruta sigan siendo impracticables.
Un hash de bcrypt tiene este aspecto: $2b$12$..., donde $12$ es el factor de trabajo (12 rondas equivalen a 2^12 iteraciones). Un servidor actual tarda entre 100 y 300 ms en verificar un hash con factor 12, algo asumible al iniciar sesión pero inviable para un ataque masivo.
**Úsalo para:** guardar contraseñas en una base de datos. Para eso y solo para eso.
**No lo uses para:** integridad de archivos, firmas ni nada que tenga que ser rápido.
Argon2 (ganador del concurso de hashing de contraseñas)
Argon2 ganó el concurso de funciones de hash para contraseñas de 2015 y es hoy el algoritmo recomendado para guardar contraseñas. Tiene tres variantes: Argon2i (resistente a ataques de canal lateral), Argon2d (la más rápida) y Argon2id (la recomendada para contraseñas). A diferencia de bcrypt, Argon2 permite configurar también el consumo de memoria, lo que dificulta mucho más los ataques con tarjetas gráficas y circuitos dedicados.
Si empiezas un proyecto nuevo, usa Argon2id en lugar de bcrypt.
Resumen rápido
| Algoritmo | Tamaño de salida | Velocidad | Para qué sirve |
|---|---|---|---|
| MD5 | 128 bits | Muy rápido | Solo sumas de verificación heredadas |
| SHA-256 | 256 bits | Rápido | Firmas, HMAC, integridad de archivos |
| HMAC-SHA256 | 256 bits | Rápido | Autenticación de API, JWT |
| Bcrypt | 60 caracteres | Lento (ajustable) | Guardar contraseñas |
| Argon2id | Variable | Lento y con mucha memoria | Guardar contraseñas (preferible) |
Una regla que no se olvida
Rápido es bueno para casi todo. Rápido es peligroso para las contraseñas. El objetivo entero de bcrypt y de Argon2 es ser lentos: esa es la virtud, no el defecto. No guardes nunca contraseñas usando solo MD5, SHA-1 o SHA-256.