Saltar al contenido
>_ITDITDPlataforma de seguridad web

Guías de seguridad

Cómo guardar contraseñas con seguridad — la forma correcta de aplicar hash y salt

Cómo guardar contraseñas con seguridad: por qué fallan el texto plano, el cifrado y los hashes simples, qué aporta un salt por usuario y por qué la respuesta es un hash lento (Argon2/bcrypt/scrypt). Cómo elegirlo, ajustarlo y migrar un sistema.

Publicado 2026-06-27 Actualizado 2026-06-27 6 min de lectura

"¿Cómo debería guardar exactamente las contraseñas de los usuarios en la base de datos?" — todo desarrollador se topa con esta pregunta una vez. La respuesta es clara. Aquí va la forma segura de guardarlas, por orden, sin pasos de ataque.

Por qué el texto plano, el cifrado y los hashes simples fallan todos

Asume que la base de datos se filtrará algún día. Cuando ocurra, el daño difiere enormemente según el método de almacenamiento.

  • Texto plano: toda contraseña queda expuesta en el instante en que se filtra. Peor aún, la reutilización de contraseñas encadena la brecha hacia los otros servicios del usuario. El peor caso.
  • Cifrado (reversible): la clave lo revierte — así que si la clave se filtra junto con ello, vuelves al texto plano. Una contraseña nunca necesita leerse de vuelta, así que ser reversible no te aporta nada.
  • Hash simple (MD5/SHA-256): un hash rápido permite a un atacante probar conjeturas a gran velocidad. Las contraseñas comunes caen ante las tablas rainbow y la fuerza bruta.

Las "cuatro etapas" hacia lo seguro

Lo más rápido es entenderlo como ir añadiendo una corrección a la vez a un método débil.

1. texto plano: se acabó si se filtra
↓ hazlo de un solo sentido
2. hash simple: débil ante las tablas rainbow
↓ añade un salt por usuario
3. hash con salt: tablas derrotadas, pero la fuerza bruta sigue siendo rápida
↓ hazlo deliberadamente lento
4. hash con salt + lento (Argon2id / bcrypt): esta es la respuesta
texto plano → hash simple → con salt → hash lento. Solo al final es realmente 'almacenamiento seguro'.

La idea clave: un salt y un hash lento hacen trabajos distintos. Un salt derrota la precomputación (tablas rainbow) y el descifrado masivo por reutilización. Un hash lento reduce la fuerza bruta a un ritmo impracticable. Necesitas ambos antes de que sea seguro (→ qué es el hashing).

En la práctica: qué hacer ahora

1

Usa Argon2id (o bcrypt)

Para sistemas nuevos, haz de Argon2id la primera opción — también puede exigir memoria, lo que resiste la fuerza bruta por GPU. Si prefieres una implementación muy probada, bcrypt es de sobra suficiente en la práctica. Usa la implementación de la biblioteca estándar tal cual para cualquiera de las dos.

2

Deja que el salt sea automático

bcrypt/Argon2 generan un salt por usuario y lo incrustan dentro de la cadena del hash. No mantienes una columna de salt aparte. Construir a mano MD5(salt + contraseña) es el clásico error que no hay que cometer.

3

Ajusta el coste para tu entorno

Fija el factor de coste de bcrypt, o la memoria/iteraciones/paralelismo de Argon2, tan alto como puedas mientras un inicio de sesión legítimo siga sintiéndose instantáneo. A medida que los servidores se vuelven más rápidos, también los atacantes — revísalo y súbelo cada año.

4

Verifica con la función de comparación estándar

Al iniciar sesión, coteja la entrada con el hash almacenado usando la función de verificación de la biblioteca (la mayoría usa una comparación de tiempo constante, segura ante ataques de temporización). No escribas tu propia igualdad de cadenas.

5

Migra los hashes débiles re-hasheando al iniciar sesión

Si ya guardas MD5/SHA-256, en el momento en que un usuario inicia sesión correctamente, re-hashea con el nuevo esquema y guárdalo. Para los usuarios que no han iniciado sesión, puedes hacer una mejora provisional envolviendo el hash existente dentro de bcrypt (un hash en capas).

Errores comunes vs. la implementación correcta

Error común

  • Cifrar las contraseñas para guardarlas (la clave se filtra → se acabó)
  • Guardar MD5(contraseña) o SHA-256(contraseña) directamente
  • Usar un único salt compartido para todos los usuarios
  • Construir a mano hash(salt + contraseña)

Implementación correcta

  • Hash de un solo sentido con Argon2id / bcrypt
  • Un salt por usuario (la biblioteca lo añade automáticamente)
  • Coste tan alto como resulte aceptable, subido periódicamente
  • Usar las funciones estándar de hash/verificación tal cual

La visión de este sitio: el almacenamiento de contraseñas es un sitio para montar sobre la respuesta aburrida y probada

El almacenamiento de contraseñas no es un sitio para ser creativo. Montar sobre las implementaciones estándar de Argon2/bcrypt, probadas por todo el mundo, es lo más seguro y lo más fácil de operar. Nuestra postura: no innoves aquí. Gasta tu esfuerzo, en cambio, en reducir la dependencia de las contraseñas en general — una autenticación multifactor (MFA) exhaustiva, y un eventual paso a passkeys (sin contraseña). Ni siquiera el hash más fuerte puede salvar una contraseña débil y reutilizada.

Sigue leyendo

FAQ

Q¿No basta con cifrar las contraseñas para guardarlas?
A

No — el cifrado es la herramienta equivocada. El cifrado es reversible con una clave, así que si la clave se filtra, todas las contraseñas vuelven a texto plano. Una contraseña nunca necesita volver a leerse, ni siquiera por ti, así que un 'hash' irreversible es la respuesta correcta. Pero un hash simple no basta; combina un salt por usuario con un hash lento (bcrypt/Argon2).

Q¿bcrypt o Argon2 — cuál usar?
A

Para desarrollo nuevo, Argon2 (Argon2id en especial) es la primera opción: te deja ajustar tanto memoria como cómputo, lo que resiste bien la fuerza bruta por GPU. Si valoras una implementación consolidada y muy probada, bcrypt sigue siendo perfectamente práctico. El punto clave con cualquiera de los dos es usar la implementación de la biblioteca estándar tal cual y no inventarla tú.

QYa guardé contraseñas con MD5/SHA-256. ¿Cómo migro?
A

No puedes reconvertirlas en bloque a texto plano (esa es la idea), así que migra al iniciar sesión. En el momento en que un usuario inicia sesión correctamente, re-hashea la contraseña correcta que acaba de introducir con el nuevo esquema (p. ej. Argon2id) y guárdala. Para los usuarios que no han iniciado sesión, puedes hacer una mejora provisional envolviendo el hash existente dentro de bcrypt (un hash en capas).