Hashing vs. Cifrado: Cómo Se Almacena Tu Contraseña en el Servidor

Supongamos que configuras una cuenta en VerySecureWebsite.com. Escribes tu dirección de correo electrónico y contraseña y configuras tu cuenta. Un poco más tarde recibes un correo electrónico informándote de que, irónicamente, el sitio web ha sido hackeado, y los nombres de usuario y contraseñas de cada usuario, que se almacenaban en texto sin formato, ahora están a la venta en la dark web. Mientras comienzas a cambiar la contraseña en todas tus cuentas (solo usas una, monstruo), te preguntas: “ ¿No es eso una mala idea? ¿No debería mi contraseña estar en algún tipo de código secreto para que los hackers no puedan leerla? ”
Tienes razón. Cualquier aplicación web o servicio que utilice un sistema de inicio de sesión con nombre de usuario/contraseña debería almacenar las contraseñas de sus usuarios utilizando un hash con sal, posiblemente incluso un hash lento con sal, quizás con un adicional. Si esto te suena más a desayuno que a criptografía, no te preocupes: a diferencia de tu contraseña (esperemos), el almacenamiento seguro de contraseñas no es un tema demasiado complicado de entender.
También lee: Por Qué las Restricciones de Contraseña en el Sitio Web No Te Mantienen Seguro
Texto claro y cifrado básico

| Nombre de usuario | Contraseña ingresada | Forma almacenada |
|---|---|---|
| UsuarioInocente | ContraseñaDébil | ContraseñaDébil |
Almacenar contraseñas en texto claro en una base de datos conectada a Internet es una idea bastante mala: si la base de datos es hackeada, cualquiera que haya reutilizado una de esas contraseñas está ahora en riesgo. Sin embargo, un número perturbador de sitios web todavía lo hace, probablemente porque las mejoras en seguridad son más para el cliente que para la empresa. Si quieres probar si un sitio está haciendo esto, intenta seleccionar la opción “olvidé mi contraseña”. Si simplemente te envían tu contraseña en lugar de un enlace de restablecimiento, se está almacenando en texto claro.
| Nombre de usuario | Contraseña ingresada | Cifrado con clave AES-128: ClaveDébil |
|---|---|---|
| UsuarioInocente | ContraseñaDébil | 38MkoXVXoKe01uAOROBLpQ== |
El cifrado puede sonar como una forma sólida de almacenar contraseñas, pero en realidad es solo un paso por encima del texto claro. En general, una contraseña cifrada puede ser decodificada con una clave, y si los hackers pueden encontrarla o adivinarla, el cifrado es inútil.
Hashing > cifrado

| Nombre de usuario | Contraseña ingresada | Cadena a ser hashada | Hash con SHA-256 |
|---|
| UsuarioInocente | ContraseñaDébil | ContraseñaDébil | 252E2406732308F9A7
B378ED94E78467D14
077D19C8282443FCD
3D6190FCABFA |
Una función hash es básicamente un cifrado unidireccional: conviertes la contraseña en texto claro en un código secreto, pero no hay clave para revertirla, lo que significa que nunca podrás derivar la contraseña real a partir de la versión hashada.
Así es como la mayoría de los sitios web seguros gestionan sus contraseñas:
- El usuario crea una cuenta
- La contraseña del usuario se pasa a través de la función hash y se almacena en la base de datos
- Cada vez que el usuario inicia sesión, la base de datos hashea la contraseña que ingresaron y verifica si el hash ingresado coincide con el hash que tienen archivado.
- Si es así, el usuario puede iniciar sesión
Con un hash, la app/sitio nunca almacena tu contraseña real en ningún lugar, y un hacker que logre entrar solo obtendrá una lista de letras y números que no pueden ser decodificados. Dependiendo de la solidez del algoritmo, estos hashes pueden ser bastante difíciles de romper.
Sin embargo, los hashes no son a prueba de hackers. Todo lo que un atacante tiene que hacer es pasar un diccionario de posibles contraseñas a través de la función hash, luego comparar esos hashes con los hashes en la base de datos. Cuando dos hashes coinciden, el hacker puede simplemente ver qué contraseña generó ese hash.
Para ahorrar tiempo y potencia de cálculo, muchos atacantes solo utilizan una tabla de búsqueda (o una “tabla arcoíris”, una versión que ahorra espacio de las tablas de búsqueda), una tabla pre-generada llena de posibles contraseñas y sus hashes. De hecho, puedes intentar hashear una palabra en texto claro y luego usar una tabla de búsqueda sobre el hash tú mismo; no es tan difícil. Esencialmente, si tu contraseña es en absoluto común, el hash de esa contraseña probablemente ya esté en una tabla de búsqueda. Esta es una gran razón para no usar contraseñas comunes.
También lee: Crea una Contraseña Fuerte Usando Estos Consejos y Herramientas
Hashes con sal > hashes

| Nombre de usuario | Contraseña ingresada | Cadena a ser hashada | Hash con SHA-256,
sal = XcyKn42, prependido | | — | — | — | — | | UsuarioInocente | ContraseñaDébil | XcyKn42ContraseñaDébil | 13EB660FF7FBD29A728FC5
92297D78DF19AFF8797363
15FBF1F1C4B7123BD10C |
A diferencia de los caracoles, la sal hace que los hashes sean más fuertes. Dado que todo el hash cambia incluso si solo una letra de la palabra en texto claro cambia, todo lo que un sitio necesita hacer para frustrar las tablas de búsqueda es añadir algún texto adicional a la contraseña antes de ser hasheada. El atacante podrá leer la sal en texto claro ya que se almacena en la base de datos, pero los obliga a recalcular cada posible combinación de contraseñas y sales.
Por supuesto, los hashes con sal aún pueden ser vulnerables. Los hackers pueden simplemente añadir la sal a la contraseña que están adivinando, hashear la combinación y esperar a que aparezcan las coincidencias – un ataque estándar de diccionario. Dado que las GPUs modernas pueden hacer miles de millones de conjeturas por segundo, esto no es en absoluto inviable, pero sí hace que el proceso sea mucho más molesto. En caso contrario, los ataques de fuerza bruta son lentos pero muy efectivos.
Haciendo los hashes aún más fuertes: otras tácticas

| Nombre de usuario | Contraseña ingresada | Cadena a ser hashada | Hash con Bcrypt,
sal = XcyKn42, prependido,
12 rondas | | — | — | — | — | | UsuarioInocente | ContraseñaDébil | XcyKn42ContraseñaDébil | $2y$12$6OleutQBO2iPoNvg
pyDndOU26Lqt9Y34f6PLEOx
mCELP5GoswrJT. |
Los algoritmos de hash lentos, como PBKDF2 o bcrypt, utilizan una técnica conocida como “extensión de clave” para ralentizar los ataques de diccionario y de fuerza bruta. Esto implica esencialmente configurar la función hash para que itere un cierto número de veces (aunque es un poco más complejo que simplemente ejecutar lo mismo una y otra vez), de modo que para llegar al hash correcto tengas que usar mucha potencia de cálculo. Si un sitio está haciendo todo esto, su seguridad es bastante buena.
| Nombre de usuario | Contraseña ingresada | Cadena a ser hashada | Hash con Bcrypt,
sal = XcyKn42, prependido,
12 rondas,
pepper = |4|\/|@p3pp3r, appendido | | — | — | — | — | | UsuarioInocente | ContraseñaDébil | XcyKn42ContraseñaDébil|4|\/|@p3pp3r | $2y$12$njmWr5UMydCzdCE44ElW/
OIfYp2PH9sgonCATyVY.OVKSpmoSaZlu |
Para mayor seguridad, también puedes “agregar un extra” a tus hashes – que espero que ya estén salados. Un “extra”, como la sal, es un conjunto de valores adjuntos a la contraseña antes de ser hasheada. Sin embargo, a diferencia de una sal, solo hay un valor de “extra”, y se mantiene en secreto, separado de las sales y los hashes. Añade otra capa de seguridad al hash con sal, pero si el atacante logra encontrarlo, ya no es muy útil ya que el atacante puede usarlo para calcular nuevas tablas de búsqueda.
No hagas un lío con tu hash
La seguridad de contraseñas ha hecho grandes avances – y también lo ha hecho el arte de romper esa seguridad. Desafortunadamente, los humanos todavía son malos en la gestión de contraseñas, y las bases de datos no actualizan la seguridad tan a menudo como deberían. En general, asume que cada vez que creas una cuenta, la contraseña se está almacenando con seguridad relativamente débil. Si tu contraseña es común o una palabra del diccionario, entonces está en un alto riesgo de ser hackeada. Haz que tus contraseñas sean largas, mezclando letras, números y símbolos, y estarás ayudando a las funciones hash a hacer su mejor trabajo.
Créditos de imagen: Función hash