Cómo guardar contraseñas: hash, salt y algoritmo lento
En pocas palabras: Los sitios seguros no guardan tu contraseña: guardan un hash lento con salt único por usuario. OWASP recomienda Argon2id con un mínimo de 19 MiB de memoria, 2 iteraciones y paralelismo 1. El cifrado es reversible con una clave; el hash no se puede revertir.
Para saber cómo guardar contraseñas de forma segura, el sitio tiene que guardar un hash lento con salt único por usuario, no la contraseña ni una versión cifrada. OWASP recomienda Argon2id con al menos 19 MiB de memoria, 2 iteraciones y paralelismo 1.
El hashing de contraseñas es el proceso de convertir una contraseña en una huella de largo fijo mediante una función de un solo sentido, de modo que el sitio pueda verificar un login sin conocer ni poder recuperar la contraseña original. El cifrado, en cambio, es reversible con una clave. Los desarrolladores usan hashing con salt y costo ajustable; los usuarios dependen de que lo hagan bien.
En este artículo:
- En 30 segundos
- ¿Por qué cifrar las contraseñas no alcanza si filtran la base de datos?
- ¿Qué falló en la filtración de LinkedIn de 2012 con SHA-1 sin salt?
- ¿Para qué sirve el salt y tiene que ser secreto?
- ¿Cómo guardar contraseñas: Argon2id, bcrypt o scrypt?
- ¿Qué tiene que revisar hoy un equipo de desarrollo en su sistema de login?
- Errores comunes al guardar contraseñas
- Preguntas Frecuentes
- Conclusión
- Fuentes
En 30 segundos
- Hash no es cifrado. El hash no se revierte; el cifrado sí, con la clave. OWASP pide hash para las contraseñas.
- No hay una filtración nueva. El post de dev.to del 9 de octubre de 2026 repasa casos viejos: RockYou (2009), LinkedIn (2012) y Adobe (2013).
- Salt único por usuario. No es secreto, pero reutilizar el mismo para todos anula la protección. RFC 9106 recomienda 16 bytes.
- Algoritmo lento y ajustable. Argon2id con m=19 MiB, t=2, p=1 como mínimo; bcrypt con factor 10 o más en sistemas legacy; PBKDF2 con 600.000 iteraciones si exigen FIPS-140.
- Como usuario no podés auditar nada. Gestor de contraseñas y una clave distinta por sitio.
¿Por qué cifrar las contraseñas no alcanza si filtran la base de datos?
Porque el cifrado se deshace con la clave, y esa clave suele vivir en la misma máquina que la base de datos. Quien se lleva una se lleva la otra. El hash, en cambio, no se revierte: el sitio guarda la huella de la contraseña y, en el próximo login, la calcula de nuevo y compara.
Hay tres formas de guardar una contraseña, y dos son malas. En texto plano, RockYou filtró en 2009 unos 32 millones de contraseñas (sí, en serio), según el post de Autional en dev.to. Con cifrado, el problema es que la clave queda cerca y que la misma contraseña produce siempre el mismo texto cifrado; el post cita el caso de Adobe en 2013, con 3DES-ECB, como ejemplo de manual. Con hash, el sitio nunca necesita saber tu clave.
OWASP lo dice sin vueltas: “Passwords should never be stored in plain text” (las contraseñas nunca deben guardarse en texto plano).
La guía deja una excepción para el cifrado: cuando la aplicación necesita la contraseña original para autenticarse contra otro sistema que no tiene un mecanismo moderno de acceso, como OpenID Connect. Para un login común no aplica. Una aclaración de contexto: el post es del 9 de octubre de 2026 y repasa casos viejos (2009, 2012, 2013), no informa ninguna filtración nueva.
¿Qué falló en la filtración de LinkedIn de 2012 con SHA-1 sin salt?
Usaron un hash rápido y sin salt. Sin salt, la misma contraseña da siempre la misma huella, así que los diccionarios precalculados, que cubren cientos de millones de contraseñas comunes, las resuelven por búsqueda. Según el post de dev.to, muchas contraseñas de LinkedIn se recuperaron en pocos días.
El mecanismo lo describe OWASP: el atacante elige una contraseña candidata, calcula su hash y lo compara con el de la víctima; si coinciden, ya conoce la clave. Repite con listas de otros sitios comprometidos, diccionarios y fuerza bruta. Con GPUs y servidores de alquiler en la nube, el costo de probar es relativamente bajo, sobre todo si no se siguen las buenas prácticas. SHA-1 sin salt hacía ese trabajo casi gratis, porque un solo cálculo servía contra toda la base (esto último es inferencia mía a partir de la explicación de OWASP sobre el salt).
Usar hash a secas da una falsa sensación de seguridad. OWASP también descarta algoritmos rápidos como SHA-256 para este uso, porque dejan que el atacante pruebe una gran cantidad de intentos en poco tiempo.
¿Para qué sirve el salt y tiene que ser secreto?
El salt es un valor aleatorio y único por usuario que se mezcla con la contraseña antes de hashear, así dos usuarios con la misma clave terminan con hashes distintos. No es secreto y se guarda junto al hash. Lo peligroso es reutilizar el mismo salt para todos.
Con salt único, el atacante tiene que crackear los hashes de a uno, y el tiempo crece en proporción a la cantidad de hashes, según OWASP. El salt también frena las rainbow tables y oculta si dos usuarios comparten contraseña. Conviene no confundirlo con el pepper:
- Salt: único por usuario, no secreto, va junto al hash.
- Pepper: compartido entre todas las contraseñas, secreto, guardado aparte de la base (en un vault o un HSM). Si se compromete hay que cambiarlo y forzar el reseteo de todas las contraseñas que protegía, según OWASP.
Sobre el tamaño: RFC 9106 recomienda 16 bytes de salt para Argon2 y que sea único por contraseña. El post de dev.to habla de un mínimo de 32 bits y lo atribuye a NIST SP 800-63B. Ojo: la página de NIST aclara que esa revisión quedó reemplazada por la SP 800-63-4 desde el 1 de agosto de 2025, y el fragmento que revisamos no llega a esa cifra, así que verificala en la versión vigente.
La buena noticia: OWASP aclara que las librerías más usadas generan y manejan el salt solas.
¿Cómo guardar contraseñas: Argon2id, bcrypt o scrypt?
Para un sistema nuevo, Argon2id. OWASP lo pone primero con un mínimo de 19 MiB de memoria, 2 iteraciones y paralelismo 1; scrypt si Argon2id no está disponible; bcrypt para sistemas legacy; PBKDF2 solo si hace falta cumplir FIPS-140.
| Algoritmo | Cuándo usarlo | Parámetros mínimos (OWASP) | Nota |
|---|---|---|---|
| Argon2id | Primera opción, sistemas nuevos | m=19456 KiB (19 MiB), t=2, p=1 | Ganó la Password Hashing Competition de 2015 y está descrito en el RFC 9106 |
| scrypt | Si no hay Argon2id | N=2^17 (128 MiB), r=8, p=1 | RFC 7914, según el post de dev.to |
| bcrypt | Sistemas legacy | Factor de trabajo 10 o más | Límite de 72 bytes de contraseña |
| PBKDF2 | Si se exige FIPS-140 | 600.000 iteraciones o más con HMAC-SHA-256 | Función interna HMAC-SHA-256 |

OWASP también lista variantes de Argon2id con el mismo nivel de defensa que cambian CPU por RAM: 46 MiB con t=1, 12 MiB con t=3, 9 MiB con t=4 o 7 MiB con t=5, siempre con p=1. Sirve si tu servidor anda corto de memoria.
Son mínimos, no objetivos. OWASP dice que no hay una regla de oro para el costo, que hay que medirlo en el servidor real y que calcular un hash debería tardar menos de un segundo; si lo subís demasiado, un atacante puede agotar tu CPU con muchos intentos de login. Ponele que un equipo lo configura una vez y lo deja andando con los parámetros mínimos, nadie lo vuelve a mirar, el hardware de los atacantes mejora y el hash que era razonable ese día termina siendo barato de romper (hipotético, pero es el motivo por el que el costo es ajustable).
RFC 9106, que es informativo y no un estándar de Internet, explica por qué Argon2id es la variante principal: trabaja como Argon2i en la primera mitad de la primera pasada y como Argon2d después, para resistir ataques de canal lateral y ahorros por compromiso entre tiempo y memoria. Mi lectura: si arrancás hoy, no hay motivo para elegir otra cosa que Argon2id.
¿Qué tiene que revisar hoy un equipo de desarrollo en su sistema de login?
Cuatro cosas: un hash estándar y lento, un salt único por usuario, un costo que subas con el tiempo y cero contraseñas en los logs. Después, comprobá que eso esté aplicado de verdad y no solo escrito en la documentación.
- Usá la función del lenguaje o framework. OWASP señala que la mayoría tiene soporte nativo; en PHP, por ejemplo, existe password_hash.
- Re-hasheá en el próximo login. Es el enfoque que describe OWASP para subir el factor de trabajo; los usuarios que no vuelven conservan el hash viejo, y ahí decidís si forzás un reseteo.
- No escribas contraseñas en los logs. Lo recomienda el post de dev.to y es barato de cumplir.
- Anotá qué versión de NIST seguís. La 800-63B está reemplazada por la 800-63-4.
Una propuesta de verificación, que es criterio editorial nuestro y no viene de las fuentes ni la probamos: en un entorno de pruebas, creá dos usuarios con la misma contraseña y comparalos en la base. Si los hashes son idénticos, no hay salt por usuario. Si el valor guardado no indica algoritmo ni parámetros (OWASP dice que el factor de trabajo suele ir en la salida del hash), revisá cómo se genera. Y buscá la contraseña de prueba en los logs.
Una salvedad sobre la fuente: el post lo escribe Autional, una capa de identidad open-core que aplica estas prácticas, y cierra con un enlace a su producto. Tomalo como contexto de vendor, no como fuente neutral. Por eso las recomendaciones de acá las respaldo con OWASP, RFC 9106 y NIST.
Si sos usuario, el post no te dice cómo guarda tu clave un sitio en particular, y desde afuera no hay forma de comprobarlo. Lo que sí podés decidir: usar un gestor de contraseñas y no repetir claves, así una filtración no se lleva el resto de tus cuentas. Si un sitio te manda tu contraseña original por mail al “recuperarla”, sospechá: lo más probable es que la guarde en texto plano o cifrada (inferencia, no dato de las fuentes).
Errores comunes al guardar contraseñas
- Confiar en SHA-256 a secas. Es rápido por diseño y OWASP lo marca como no apto. Corrección: Argon2id o, si no está, scrypt o bcrypt.
- Usar un salt fijo para toda la base. El post de dev.to lo señala como el peligro real. Corrección: uno aleatorio por usuario, generado por la librería.
- Cifrar con la clave al lado. Es el patrón del caso Adobe 2013. Corrección: hash, no cifrado.
- Subir el costo sin medir. Un factor demasiado alto sirve para agotar la CPU con muchos logins. Corrección: medir en el servidor real y apuntar a menos de un segundo por hash.
Preguntas Frecuentes
¿Cuál es la diferencia entre hash y cifrado de contraseñas?
El hash es de un solo sentido y el cifrado es reversible con una clave. Por eso OWASP pide hashear las contraseñas: aunque un atacante se lleve la base, no puede descifrarlas, solo probar candidatas una por una.
¿Para qué sirve el salt en una contraseña?
El salt es un valor aleatorio único por usuario que hace que dos contraseñas iguales den hashes distintos. Obliga al atacante a crackear cada hash por separado y frena las tablas precalculadas.
¿Es seguro que un sitio guarde mi contraseña cifrada?
No es lo recomendado. OWASP reserva el cifrado para casos puntuales en que la aplicación necesita la contraseña original, y para un login común pide hash lento con salt. Desde afuera no podés verificar qué hace cada sitio.
¿Qué es mejor para guardar contraseñas: Argon2id, bcrypt o scrypt?
Argon2id es la primera opción de OWASP para sistemas nuevos. scrypt va si Argon2id no está disponible, y bcrypt queda para sistemas legacy, con factor de trabajo 10 o más y límite de 72 bytes.
¿Por qué SHA-256 solo no alcanza para guardar contraseñas?
Porque es rápido, y esa velocidad le sirve al atacante: OWASP lo considera no apto, ya que deja probar una gran cantidad de combinaciones en poco tiempo. Hace falta un algoritmo lento y con salt, como Argon2id.
Conclusión
No cambió nada en las recomendaciones: el post del 9 de octubre de 2026 resume lo que OWASP ya documenta. Hash, no cifrado; salt único por usuario; algoritmo lento y con costo que se sube. Si mantenés un login, abrí tu código esta semana, mirá qué función hashea, con qué parámetros, y compará contra la tabla de arriba. Si sos usuario, un gestor de contraseñas y claves únicas es la defensa que sí está en tus manos.
Fuentes
- OWASP Password Storage Cheat Sheet – parámetros mínimos, salt, pepper y factor de trabajo
- RFC 9106 – especificación informativa de Argon2 y recomendación de salt
- NIST SP 800-63B – guía de autenticación, reemplazada por la SP 800-63-4
- dev.to (Autional) – post de origen con los casos RockYou, LinkedIn y Adobe
- Manual de PHP – función password_hash






