Saltar al contenido principal

Hashing criptográfico - Protección de contraseñas almacenadas

Lectura de 2 min aprox.

Un hash es una función unidireccional que transforma datos de longitud arbitraria en un valor de longitud fija. Desempeña un papel fundamental en el almacenamiento de contraseñas, ya que se utiliza para guardarlas de forma segura en un formato del que no se puede recuperar la contraseña original. La misma entrada siempre produce el mismo valor hash, pero calcular los datos originales a partir de un valor hash es computacionalmente inviable.

La diferencia entre el hash y el cifrado

El hash y el cifrado son conceptos que se confunden con facilidad, pero existe una diferencia decisiva entre ellos. El cifrado es una transformación bidireccional: con la clave correcta, los datos originales pueden descifrarse. El hash, por el contrario, es una transformación unidireccional que no puede revertirse a los datos originales, y el concepto de descifrado no existe. El hash es adecuado para almacenar contraseñas, ya que el servicio no necesita conservar el texto plano de la contraseña y, aunque la base de datos sufra una filtración, las contraseñas originales no quedan directamente expuestas. Por el contrario, el cifrado es adecuado para proteger los datos en tránsito, pues no tendría sentido si el destinatario no pudiera leer los datos.

Uso en el almacenamiento de contraseñas

En los sistemas seguros, las contraseñas no se almacenan en texto plano, sino como valores con hash. Al iniciar sesión, la contraseña introducida se procesa con hash y se compara con el valor hash almacenado. Entre los algoritmos hash representativos se encuentran SHA-256, bcrypt y Argon2. SHA-256 es rápido, pero demasiado rápido para el uso con contraseñas, por lo que se recomiendan bcrypt y Argon2, que aumentan deliberadamente el costo computacional. En 2025, OWASP posiciona a Argon2id como el algoritmo de hash de contraseñas más recomendado. Cuanto mayor sea el costo computacional, mayor será la resistencia a los ataques de fuerza bruta.

Por qué la migración desde un hash antiguo no puede hacerse de una sola vez

Cuando un sistema que usa un algoritmo antiguo para almacenar contraseñas se migra a un esquema nuevo, la propia unidireccionalidad del hash se convierte en la restricción. Como solo se almacenan valores hash y no pueden revertirse a las contraseñas originales, los valores de la base de datos no pueden convertirse en bloque a los hashes del nuevo algoritmo. El único momento en que el servicio puede tocar la contraseña en texto plano es cuando el usuario inicia sesión y la introduce. Por eso, en la práctica la migración avanza de forma gradual: cuando un inicio de sesión se verifica con el esquema antiguo, el texto plano se vuelve a procesar en el acto con el nuevo algoritmo y se reemplaza el valor almacenado. Los datos de los usuarios que no inician sesión conservan el hash antiguo, así que durante el período de migración el sistema necesita un mecanismo para distinguir entre ambos formatos y verificar en consecuencia. Es un buen ejemplo de cómo la ventaja de diseño de no guardar nunca contraseñas en texto plano se convierte en trabajo adicional a la hora de migrar.

El proceso de hash

Entrada de contraseña
Añadir sal
Transformar con función hash
Valor hash de longitud fija
Almacenar en la base de datos

Errores prácticos y contramedidas

El hash simple por sí solo es vulnerable a los ataques de tabla arcoíris. Como contramedida, el enfoque estándar es añadir una sal (datos aleatorios) antes de aplicar el hash. Un error común en la práctica es usar algoritmos antiguos como MD5 o SHA-1 para el hash de contraseñas. Estos son tan rápidos que un ataque con GPU puede calcular una enorme cantidad de hashes en poco tiempo. Una contraseña larga y aleatoria conserva una fuerte resistencia a los ataques de fuerza bruta incluso en su estado con hash.

Términos relacionados

¿Te resultó útil este artículo?