¿Qué es un hash?
Una función hash criptográfica toma cualquier dato de entrada —una palabra, un archivo, una contraseña— y produce una cadena de longitud fija que funciona como su «huella digital». La misma entrada siempre da el mismo resultado, pero es imposible en la práctica hacer el camino inverso: a partir del hash no se puede reconstruir el texto original.
Un ejemplo real. Esto es lo que produce SHA-256, una de las funciones hash más conocidas, para la palabra contraseña (codificada en UTF-8):
SHA-256("contraseña")
edf9cf90718610ee7de53c0dcc250739239044de9ba115bb0ca6026c3e4958a5
Y esto es lo que sale si añadimos solo un punto al final:
SHA-256("contraseña.")
30a1812c8df24d48061fe88f0a3680f2c4588879aaae5f80dba3ce491ddd06a4
Un cambio mínimo en la entrada produce una salida completamente distinta. Es lo que se llama efecto avalancha, y es una de las propiedades que hacen útiles a estas funciones. Puedes comprobarlo tú mismo en una terminal con printf 'contraseña' | shasum -a 256 en macOS o sha256sum en Linux.
Propiedades de una buena función hash
- Determinista: la misma entrada produce siempre la misma salida.
- Longitud fija: da igual que hashees una letra o un libro entero; SHA-256 devuelve siempre 256 bits (64 caracteres hexadecimales).
- Resistencia a preimagen: conociendo el hash, no hay forma eficiente de encontrar una entrada que lo produzca.
- Resistencia a colisiones: debe ser inviable encontrar dos entradas distintas con el mismo hash.
- Efecto avalancha: cambiar un solo bit de la entrada altera aproximadamente la mitad de los bits de la salida.
¿En qué se diferencia un hash del cifrado?
Es la confusión más habitual. El cifrado es reversible: si tienes la clave, recuperas el texto original. Sirve para proteger datos que alguien necesita leer más tarde, como un mensaje o una copia de seguridad. El hash es de un solo sentido: no existe una clave que «deshaga» el hash.
Para las contraseñas, eso es justo lo que queremos. Un servicio no necesita saber cuál es tu contraseña; solo necesita comprobar que la que escribes es la correcta. Al registrarte guarda el hash; al iniciar sesión calcula el hash de lo que tecleas y compara ambos resultados. Si un servicio guardara las contraseñas cifradas, bastaría con robar la clave de cifrado para leerlas todas.
¿Por qué MD5, SHA-1 o SHA-256 a secas no sirven para contraseñas?
Aquí está el matiz importante. Funciones como MD5, SHA-1 o SHA-256 se diseñaron para ser rápidas: verificar la integridad de un archivo de varios gigas, firmar documentos, construir estructuras de datos. Esa rapidez es un problema cuando se usan para guardar contraseñas.
Si un atacante roba una base de datos de hashes, no puede «invertirlos», pero sí puede adivinar: toma una lista de contraseñas probables, calcula el hash de cada una y busca coincidencias. Con funciones rápidas y hardware moderno (las tarjetas gráficas son especialmente eficaces en esto) se pueden probar miles de millones de candidatos por segundo en el caso de MD5. Así, contraseñas cortas o de las más comunes caen en minutos o incluso segundos.
MD5 y SHA-1 tienen además ataques de colisión conocidos y se consideran rotos para usos criptográficos. Pero el problema de fondo para contraseñas no es ese, sino la velocidad: incluso SHA-256, que sigue siendo perfectamente seguro para otros usos, es una mala elección si se aplica directamente a una contraseña.
Tablas arcoíris y por qué existe la sal
Si todo el mundo usara SHA-256 a secas, un atacante podría calcular una sola vez los hashes de millones de contraseñas y reutilizar ese trabajo contra cualquier base de datos robada. Las tablas arcoíris (rainbow tables) son una forma optimizada de hacer exactamente eso: estructuras precalculadas que intercambian espacio en disco por tiempo de cálculo.
La defensa es la sal (salt): un valor aleatorio y único que se genera para cada usuario y se combina con su contraseña antes de calcular el hash. La sal no es secreta; se guarda junto al hash. Su función es otra:
- Dos usuarios con la misma contraseña tienen hashes distintos, así que no se delata quién comparte clave.
- Las tablas precalculadas dejan de servir, porque habría que generar una distinta para cada sal.
- El atacante se ve obligado a atacar cada cuenta por separado.
La guía de identidad digital del NIST estadounidense (SP 800-63B) exige que las contraseñas almacenadas lleven sal y se procesen con una función de derivación de claves adecuada, precisamente por estos motivos.
¿Y la pimienta?
La pimienta (pepper) es un secreto adicional, común a todos los usuarios, que se guarda fuera de la base de datos: en la configuración del servidor o, mejor aún, en un módulo de seguridad hardware. Si un atacante roba solo la base de datos, sin la pimienta no puede ni siquiera empezar a probar contraseñas. La OWASP Password Storage Cheat Sheet la presenta como una capa de defensa en profundidad, útil pero opcional, que complementa a la sal sin sustituirla.
Funciones lentas: bcrypt, scrypt, PBKDF2 y Argon2id
La solución al problema de la velocidad es usar funciones diseñadas para ser lentas y configurables. Para el usuario legítimo, que el servidor tarde una fracción de segundo en comprobar su contraseña es imperceptible. Para el atacante, que tiene que repetir ese cálculo miles de millones de veces, es un muro.
- Argon2id: ganó la Password Hashing Competition en 2015 y es la opción que la OWASP recomienda en primer lugar. Además de lenta, es exigente en memoria, lo que encarece mucho los ataques con tarjetas gráficas o hardware especializado.
- scrypt: también exigente en memoria; la OWASP la propone como alternativa cuando Argon2id no está disponible.
- bcrypt: veterana y muy extendida. Sigue siendo aceptable para sistemas existentes, con una limitación conocida: solo procesa los primeros 72 bytes de la contraseña.
- PBKDF2: aplica una función como SHA-256 cientos de miles de veces. Es la opción cuando se necesita cumplir el estándar FIPS-140, aunque no es exigente en memoria.
Todas ellas incorporan sal y un factor de coste que se puede subir con el tiempo, a medida que el hardware se vuelve más potente.
¿Qué significa todo esto para ti como usuario?
No puedes saber cómo guarda cada web tu contraseña
Desde fuera es imposible comprobar si un servicio usa Argon2id o MD5 sin sal. Hay pistas —la señal del correo que te devuelve tu contraseña, o límites de longitud absurdamente bajos—, pero ninguna garantía. Lo sensato es asumir que algún servicio que uses lo hace mal y protegerte en consecuencia.
La longitud sigue siendo tu mejor defensa
Una función lenta frena al atacante, pero no hace milagros: si tu contraseña es verano2024, aparecerá en las primeras listas que pruebe. Una contraseña larga y aleatoria, como las que crea nuestro generador de contraseñas, queda fuera del alcance práctico incluso si el servicio usó un hash rápido. Por eso el NIST SP 800-63B pone el énfasis en la longitud y en rechazar contraseñas conocidas, más que en reglas de composición. Si quieres profundizar, repasa cómo crear una contraseña segura.
El verdadero peligro es la reutilización
Cuando se descifra un hash de una filtración, el atacante obtiene un par correo-contraseña que probará de forma automática en otros servicios (el llamado credential stuffing). Si usas la misma clave en varios sitios, la seguridad de todos ellos queda al nivel del peor. Una contraseña distinta para cada cuenta, guardada en un gestor de contraseñas, convierte cualquier filtración en un problema aislado.
Los hashes también te ayudan a comprobar filtraciones
Un uso curioso: el servicio Pwned Passwords de Have I Been Pwned permite comprobar si una contraseña aparece en filtraciones sin enviarla. Tu dispositivo calcula su hash SHA-1 y solo envía los cinco primeros caracteres; el servidor devuelve todos los hashes que empiezan igual y la comparación final se hace en local. Es una técnica llamada k-anonimato. Puedes ver cómo aprovecharla en nuestra guía sobre cómo saber si tu contraseña fue filtrada.