The blog of Juan Pablo Scaletti
El guardar contraseñas esta lleno de términos propios con nombres de condimentos y conceptos oscuros. Este artículo te lo explica al detalle sin complicarse.

Guardando contraseñas

Sales, hashes, encriptación… ¿pimientas? Para ser tan comúnmente usado, las ideas para guardar contraseñas esta lleno de términos propios con nombres de condimentos y técnicas complicadas. Y todos los tutoriales que encuentras o no explican nada o se acercan demasiado a los detalles de implementación.

La idea de este tutorial es explicar justo lo del medio: todas los conceptos e ideas, pero sin irse a discutir la matemática de los algoritmos.


¿Por qué?

Si todo tu sistema, la computadora sobre la que corre, todo el resto del software y todos los equipos y programas que se usaran para conectarse a ella fueran perféctamente seguros, ni siquiera estarías leyendo esto, las contraseñas serían un campo más, como tu nombre o tu foto de perfil…

Pero nada es perfectamente seguro y hay muchas formas en que los datos que guardes puedan “filtrar” a donde no deben. Además las contraseñas no solo protegen tu sito: muchas personas suelen reusarla en otros sitios, como el que usan para leer su email, así que también son la llave de entrada a otros sistemas, por lo demás seguros.

Así que no son como cualquier otro dato. Y es tu deber protegerlas

Bienvenida al club de la contraseña

La primera regla del manejo de contraseñas es que nunca guardas las contraseñas.

En serio. Es un concepto extraño si es la primera vez que lo lees, pero es la idea más básica del manejo de contraseñas: no la guardas nunca.

La segunda regla del manejo de contraseñas es que nunca guardas las contraseñas.

Lo que en cambio guardas es una representación de la contraseña, un hash. Para verificar que la que te da un usuario es correcta, calculas el hash de esa y lo comparas con el que tienes guardado.

¿Un que?

Un hash es como una “huella digital” de un texto: una serie de letras y números únicos para ese contenido, si el contenido cambia, aunque sea en un espacio, el hash cambia también.

Es importante recordar que esto no es ‘“encriptar la contraseña”. Un hash es un identificador. Igual que no puedes obetner una personas a partir de su huella digital, es imposible extraer la contraseña original desde el hash.

# El hash (sha256) de todo el texto de “El Quijote”...
# O quizas es solo el de mi nombre.... nunca lo sabrás!
'1f2ebaa98be90f9f14a9e99def985d3cb50b3cff81c041c20651a2c99b659065'

Lo de “huella digital” no es la mejor metáfora: hay muchas funciones de hashing y cada uno de ellos generará un hash diferente para el mismo contenido.

Eligiendo una función de hashing

Como dije, hay muchos algoritmos de hashing. Es probable que hayas oido de los más populares, como MD5 o SHA1 y cada uno

La tercera regla del manejo de contraseñas es que no cualquier función de hashing sirve.

Colisiones

En primer lugar, las funciones de hashing no debe de generar el mismo hash para contraseñas diferentes (es decir que deben ser “resistentes a colisiones”), o alguien podría entrar a tu cuenta con una contraseña diferente a la tuya.

Algunas funciones de hashing, como Cheksum, fueron credas desde el prncipio sabiendo que podían tener colisiones en algunos casos. No importa, sirven para lo que fueron diseñadas.

Para otras, como MD5, (que hace años Wordpress usaba para hashear sus contraseñas) se le han ido descubriendo casos, según han pasado los años. De todos modos, para cuando a una función de hashing se le encuentra una colisión, hace tiempo que han saltado otros problemas

Velocidad

En segundo lugar, muchas de las funciones más populares, como MD5, SHA1, etc. son muy rápidas y eficientes; Lo cual es perfecto para lo que fueron inventadas, pero es lo último que quieres para hashear contraseñas.

Cuando un atacante ha conseguido una copia de tu base de datos –ya que no es posible obtener la contraseña original desde el hash– lo que le queda es probar uno por uno, los hash de todas las combinaciones de números, letras y símbolos. Es lo que se llama un ataque por fuerza bruta.

Suena como un proceso imposíblemente largo, pero cuando usas una función de hashing que puede generar miles de resultados por segundo, es cuestión de horas ¡O incluso minutos!

Una función de hash para contraseñas debe estar diseñada para ser lenta.

Costo

Tu teléfono es miles de veces más rápido que una supercomputadora de los 80‘s. A menos que tengas un teléfono muy malo. Pero la idea es que no importa lo computacionalmente intensiva que sea una algo de ahora , en cinco años no va a servir.

Para contrarestar esto, las funciones de hashing modernas, como bcrypt, sha_crypt y pbkdf2 no solo son calculadamente lentas, sino que además retrasan todo el proceso aun más calculando el hash final en muchas rondas, re-hasheando el hash del resultado anterior una y otra vez (quizás no exactamente así, pero es la idea general)

Estás repeticiones son el costo de la función. Por ejemplo, una función con costo 12 hará 2^12 = 4096 rondas. Lo interesante es que el costo es variable, es decir que puedes cambiar el número de rondas que se usan.

La idea es que conforme las computadoras se hacen más potentes, puedes aumentar el costo para hacer que siga relativamente igual de lenta. De hecho, lo recomendable ahora es usar un costo de 16 por lo menos .

Para los usuarios normales, esto significa una demora de apenas una fracción de segundo, pero para un atacante puede ser la diferencia entre horas y años.

¡No lo hagas!

¿Te sientes inspirad@ y con ganas de programas tu propia función super segura y super lenta de hashing? ¡No lo hagas!

Diseñar un algoritmo de hashing no es algo que cualquiera pueda/deba hacer. Por ejemplo, esos tres algoritmos que mencioné (bcrypt, sha_crypt y pbkdf2) han sido revisados y probados a profundidad por expertos de todo el mundo durante por lo menos diez años.

Sal

Ahora que sabes de los hash-es, entenderás el malvado plan de un supervillano (o supervillana, da igual) para pre-calcular la lista de hashes para tooodas las combinaciones de letras, números y símbolos hasta… no se… digamos 12 caracteres. (Nota: eso tiene el colorido nombre de “Tablas Arcoiris”)

Tomará tiempo, pero es posible. Una vez terminada, será muy rápido comparar los hashes de los usuarios con los de la tabla, encontrando todas las contraseñas de ese largo o menos en un instante. ¡El mundo será suyo!

O no, por que en los 70’s se les ocurrió una solución a ese problema: “salar” las contraseñas.

La ”sal” es un grupo de letras, números y símbolos al azar que agregas a la contraseña para hacerla mucho, mucho más larga, tanto que sea imposible haber prealculado una lista de contraseñas tan largas.

Salando un hash
Salando un hash

La sal se genera al azar y cambia para cada contraseña, así que también es a prueba de precalcular los hashes suponiendo una sal específica. Esto también tiene la ventaja agregada de que, aunque dos contraseñas sean iguales, sus dos hashes van a ser siempre diferentes, por que sus sales son diferentes.

Pero la sal no es un secreto, no tienes que preocuparte por guardarla por separado o ocultarla de ninguna forma. Su unica función es evitar las tablas precalculadas.

Además necesitas tenerla a la mano para verificar las contraseñas. Así que lo más común es guardarla como “texto plano” concatenada al hash final.

La Pimienta (o “sal global”)

Otro tipo de ataque, órdenes de magnitud más rápido que la fuerza bruta, es un ataque de diccionario. Es básicamente probar una lista de palabras —y variaciones y combinaciones de esas palabras— comúnmente usadas en contraseñas. “12345678”, “pizzapizza” o incluso otras que parecen seguras como “p4$$word” o “123456789j” son casos perdidos contra este ataque.

Como la sal, la “pimienta” es un texto que se agrega a la contraseña antes de hashearla antes que la sal.

A diferencia de la sal, este valor es (1) único para todos los hashes del sistema, (2) secreto, (3) definido por ti, y (4) no se guarda junto al hash original sino en tu mismo código fuente.

Aunque se tenga una copia de la base de datos, la teoría es que sin acceso al código fuente, un ataque por fuerza bruta se hace imposible.

¿Muy condimentado?

No todos están desacuerdo en que usar una pimienta sea buena idea: el argumento es que empezar a meterte con el hashing sin tener un doctorado en matemáticas puede tener efectos imprevistos y hacer el hash mucho menos seguro.

Pero para mi el principal problema de la pimienta es que no puedes cambiar su valor nunca sin hacer inválidas todas las contraseñas guardadas. Aunque se haya filtrado y ya no de ninguna seguridad, el valor original es el que se queda de por vida.

Bonus

Lee al co-fundador de StackOverflow intentar hackear su propia lista de contraseñas aquí https://blog.codinghorror.com/hacker-hack-thyself/.

…luego entra en pánico y cambia tus contraseñas por otras más largas!

¿Comentarios? ¿Dudas? ¡Escríbeme!