¿Es más seguro usar una contraseña varias veces?

43

He leído algunas veces que al almacenar contraseñas, es una buena práctica 'doble hash' de las cadenas (por ejemplo, con md5 y luego sha1, ambas con sales, obviamente).

Supongo que la primera pregunta es, "¿es esto realmente correcto?" Si no es así, por favor, descarte el resto de esta pregunta :)

La razón por la que pregunto es que, a primera vista, diría que esto tiene sentido. Sin embargo, cuando lo pienso, cada vez que se vuelve a agregar un hash (posiblemente con algo agregado), todo lo que puedo ver es que hay una reducción en el límite superior de la 'singularidad' final ... ese límite está relacionado con La entrada inicial.

Permítanme decirlo de otra manera: tenemos x número de cadenas que, cuando se procesan, se reducen a y posibles cadenas. Es decir, hay colisiones en el primer set. Ahora, desde el segundo conjunto hasta el tercero, ¿no es posible que ocurra lo mismo (es decir, colisiones en el conjunto de todas las cadenas 'y' posibles que resultan en el mismo hash en el tercer conjunto)?

En mi cabeza, todo lo que veo es un 'embudo' para cada llamada de función hash, 'canalizando' un conjunto infinito de posibilidades en un conjunto finito y así sucesivamente, pero obviamente cada llamada está trabajando en el conjunto finito anterior, dándonos un establecer no más grande que la entrada.

¿Quizás un ejemplo explicará mis divagaciones? Tome 'hash_function_a' que le dará a 'a' y 'b' el hash '1', y le dará a 'c' y 'd' el hash '2'. Usando esta función para almacenar contraseñas, incluso si la contraseña es 'a', podría usar la contraseña 'b'.

Tome 'hash_function_b' que le dará a '1' y '2' el hash '3'. Si tuviera que utilizar que como un 'hash de secundaria' después 'hash_function_a' a continuación, incluso si la contraseña es 'a' que podría utilizar 'b', 'c' o 'd'.

Además de todo eso, entiendo que se deben usar sales, pero en realidad no cambian el hecho de que cada vez que estamos asignando entradas 'x' a salidas 'menores que x'. No pienso

¿Puede alguien explicarme qué es lo que me falta aquí?

¡Gracias!

EDITAR: por lo que vale, no hago esto yo mismo, uso bcrypt. Y no estoy realmente preocupado sobre si es útil o no para 'usar ciclos' para un 'hacker'. Realmente me pregunto si el proceso reduce o no la "seguridad" desde un punto de vista de colisión hash.

Narciso
fuente
2
@ S.Lott: Realmente no veo cómo eso responde la pregunta real, aunque ... todo lo que dice es "no lo hagas tú mismo, usa esto" o "¡es bueno tomarse el tiempo!". .. ninguna de las cuales responde "es realmente más seguro". De nuevo, a menos que me falte algo.
Narciso
@MetalMikester: Sí, ese fue el artículo de ayer: thedailywtf.com/Articles/Bulletproof-Encryption.aspx
FrustratedWithFormsDesigner
Esto no es sobre el tema de seguridad de TI, pero parece una buena combinación para la criptografía. De hecho, se ve extremadamente similar a esta pregunta allí .
Sé de una empresa que quería usar sin sal MD5(password). Dijimos que no es seguro, por lo que sugirieron usar en su MD5(MD5(password))lugar ...
configurador
¡La respuesta aceptada no es la respuesta correcta!
markus

Respuestas:

27

Esto es más adecuado en security.stackexchange pero ...

El problema con

hash1(hash2(hash3(...hashn(pass+salt)+salt)+salt)...)+salt)

es que esto es tan fuerte como la función hash más débil de la cadena. Por ejemplo, si el hashn (el hash más interno) produce una colisión, toda la cadena de hash generará una colisión ( independientemente de los otros hash de la cadena ).

Una cadena más fuerte sería

hash1(hash2(hash3(...hashn(pass + salt) + pass + salt) + pass + salt)...) + pass + salt)

Aquí evitamos el problema de colisión temprana y esencialmente generamos una sal que depende de la contraseña para el hash final.

Y si un paso en la cadena choca, no importa porque en el siguiente paso la contraseña se usa nuevamente y debería dar un resultado diferente para diferentes contraseñas.

monstruo de trinquete
fuente
Entonces, ahora veo que agregar "contraseña + sal" como sal a la próxima ronda de hashing podría estar aumentando la cantidad de 'cosas' que podrían ir al embudo, ahora solo tengo que entender por 'cuánto'. Gracias.
Narciso
En realidad, creo que lo entiendo ahora: al forzar la contraseña en cada capa del hash, ¿en realidad está reduciendo el número de posibles colisiones al requerir esencialmente 'la contraseña de colisión' y la contraseña real para tener hashes coincidentes en cada 'llamada'? , ¿Derecha? ¡Estoy pensando que me faltaba la parte de 'poner la contraseña en cada capa'! Gracias de nuevo.
Narciso
@Narcissus no tiene problemas y eso también tiene la ventaja de permitir hashes internos más débiles (siempre y cuando los hashes externos / finales sean fuertes) ya que los hashes internos solo están generando la sal para el próximo pase
monstruo de trinquete del
Hum, creo que el problema es un poco más grande (y más profundo) que eso. Con los ataques de arco iris, puede generar tablas teniendo en cuenta todos sus hashes, y el problema persiste.
woliveirajr
44
@Narcissus: en una respuesta muy corta: Sí, no es más seguro. Sí, probablemente sea aún menos seguro.
woliveirajr
54

Usar diferentes algoritmos de hashing es una mala idea: reducirá la entropía en lugar de aumentarla.

Sin embargo, suponiendo que tenga un algoritmo de hash criptográficamente fuerte y una buena solución, aplicar la misma función de hash varias veces hace que el proceso de hash sea computacionalmente más costoso. El beneficio de esto es que cuando fallan otros medios para descifrar el hash de contraseña (adivinanzas, ataques de diccionario, tablas de arco iris, etc.), y el atacante se ve obligado a utilizar técnicas de fuerza bruta, les toma más tiempo probar cada contraseña, simplemente porque tienen que aplicar la misma función hash con más frecuencia. Entonces, si una ronda de hashing requeriría un mes de fuerza bruta, aplicarlo doce veces aumentaría el tiempo estimado a un año.

Algoritmos hash recientes como bcrypt se basan en esta idea; contienen un parámetro para controlar la complejidad computacional del hash, para que pueda escalarlo a medida que avanza la velocidad del hardware: cuando el hardware se vuelve más rápido en un factor de dos, aumenta la complejidad para compensar, por lo que el tiempo requerido para forzar su los hash permanecen aproximadamente constantes.

tdammers
fuente
2
¡Esta es la respuesta correcta!
markus
@markus: según la discusión que leí, esto solo es correcto debido a la adición "y una buena sal" que se aborda en la respuesta aceptada, ¿no? ¿Por qué es correcta y la respuesta aceptada no?
Narciso
Es la respuesta correcta porque la única razón para aplicar la misma función de hash varias veces (parametrizada) es que puede usar esta iteración para ajustar el hardware más rápido. De lo contrario, no hay beneficio de hashing varias veces.
markus
@Narcissus La clave aquí es la entropía. Hay una diferencia entre el hash muchas veces usando el mismo método y el hash muchas veces usando diferentes métodos.
sakisk
3

No intente escribir su propio esquema de hash de contraseña a menos que esté dispuesto a tomar un curso en criptografía y / o ingeniería de seguridad.

Debe usar una implementación bien establecida de hashing de contraseña que a su vez debe usar una función de derivación de clave ( KDF ) como PBKDF2, bcrypt, scrypt o el Argon2 más nuevo.

Los buenos KDF incluyen un factor de trabajo, generalmente varias iteraciones, para aumentar el costo de los ataques fuera de línea. Se podría decir que estos KDF cambian la contraseña varias veces, utilizando el mismo algoritmo cada vez. No tiene sentido usar el algoritmo de resumen de mensajes múltiples, como lo señalan otros.

Erwan Legrand
fuente
1
el enlace https://crackstation.net/hashing-security.htm está bloqueado por el cortafuegos
mosquito
1
@gnat Por alguna razón, me había perdido tu comentario sobre la URL bloqueada. Lo he reemplazado con un enlace a wikipedia.
Erwan Legrand, el
2

En general, no necesita usar más de un algoritmo de hash.

Lo que debes hacer es:

Use salt: la sal no se usa solo para hacer que su contraseña sea más segura , sino que se usa para abordar el ataque de la mesa arcoiris. De esa manera, alguien tendrá un trabajo más duro tratando de calcular previamente el hash para las contraseñas que almacene en su sistema.

Use múltiples interacciones: en lugar de hacer solo SHA (contraseña + sal), haga SHA (SHA (SHA (SHA (SHA (... SHA (contraseña + sal))))))). O, para representar de otra manera:

hash = sha(password + salt)
for i=1 , i=5000, i++ {
    hash = sha(hash + salt);
}

Y, finalmente, elija una buena función de hashing. SHA, MD5, etc., no son buenos porque son demasiado rápidos . Como desea usar hash para protección, es mejor que use hash más lentos. Echar un vistazo a Bcrypt , PBKDF2 o Scrypt , por ejemplo.

editar : después de las observaciones, intentemos ver algunos puntos (perdón, explicación larga para llegar al final, porque podría ayudar a otros a buscar respuestas similares):

Si su sistema es seguro, como si nunca nadie tuviera acceso a la contraseña almacenada, no necesitaría hash. La contraseña sería secreta, nadie la obtendría.

Pero nadie puede asegurar que la base de datos con las contraseñas sea robada. Robar la base de datos, obtuve todas las contraseñas. Ok, su sistema y su empresa sufrirán todas las consecuencias del mismo. Por lo tanto, podríamos tratar de evitar esta filtración de contraseña.

AVISO de que no estamos preocupados por los ataques en línea en este punto. Para un ataque en línea, la mejor solución es reducir la velocidad después de contraseñas incorrectas, bloquear la cuenta después de algunos intentos, etc. Y para eso no importa de qué manera cifre, cifre, almacene, etc., su contraseña. El ataque en línea es una cuestión de ralentizar las entradas de contraseña .

Entonces, volviendo al don't let them take my plain passwordsproblema. La respuesta es simple: no los almacene como texto sin formato. Ok lo tengo.

¿Cómo evitar eso?

Cifre la contraseña (?). Pero, como sabe, si lo encripta, puede volver a desencriptarlo, si tiene la clave adecuada. Y terminará con el problema de "dónde esconder" la clave. Hum, no está bien, ya que obtuvieron tu base de datos, pueden obtener tu clave. Ok, no lo usemos.

Entonces, otro enfoque: transformemos la contraseña en otra cosa que no se pueda revertir y almacénela. Y para verificar si la contraseña provista es correcta, hacemos el mismo proceso nuevamente y verificamos si los dos valores transformados coinciden. Si coinciden = se proporcionó la buena contraseña.

Ok, hasta ahora todo bien. Usemos un hash MD5 en la contraseña. Pero ... si alguien tiene nuestro valor hash almacenado de contraseña, puede tener mucha potencia de computadora para calcular el hash MD5 de cada contraseña posible (fuerza bruta), para que pueda encontrar la contraseña original. O, lo que es peor, puede almacenar todos los MD5 de todas las combinaciones de caracteres y encontrar fácilmente la contraseña. Entonces, haz muchas iteraciones, lo que es HASH (HASH (HASH ())), para hacerlo más difícil, porque tomará más tiempo.

Pero incluso eso se puede evitar, la mesa arcoiris fue creada exactamente para acelerar contra este tipo de protección.

Entonces, usemos un poco de sal sobre él. De esta manera, en cada interacción, la sal se usa nuevamente. Quien intente atacar sus contraseñas tendrá que generar la tabla del arco iris teniendo en cuenta que la sal se agrega cada vez. Y cuando genera esa tabla de arcoíris, ya que se generó con una sal, tendrá que calcular nuevamente con la otra sal, por lo que tendrá que pasar un tiempo para cada contraseña (= cada sal). Salt no agregará "más complejidad" a la contraseña, solo hará que el atacante pierda tiempo generando la tabla del arco iris, si usa una sal para cada contraseña, la tabla de una sal es inútil para otra contraseña.

¿Y usar más de un hash habrá ayudado aquí? No. La persona que genera un ataque de arco iris específico podrá generarlo usando uno o más hashes, de todos modos.

Y usar más de un hash puede llevarlo a un problema: es tan seguro como el hash más débil que usa. Si alguien encuentra colisiones en un algoritmo hash, es ese hash el que se explotará, en cualquier punto del proceso de iteración, para romper la contraseña. Entonces, no ganas nada usando más algoritmos hash, es mejor elegir solo un buen algoritmo. y úsalo. Y si alguna vez escucha que se ha roto, piense cómo lo cambiará en su aplicación.

Y por qué usar bcrypt o algo así (usted dice que lo usa): porque el atacante tendrá que pasar más tiempo generando las tablas. Es por eso que usar MD5 + wait (3 segundos) no ayuda: el ataque estará fuera de línea, de todos modos, por lo que el atacante puede generar las tablas sin el (retraso de 3 segundos).

woliveirajr
fuente
2
¡Uy! Lo siento, mi comentario (sobre deliberadamente hacer que el hash sea más lento a través del parámetro de tiempo de espera) no debía ser tomado en serio ... Creo que he estado leyendo demasiado Dilbert últimamente.
FrustratedWithFormsDesigner
2
sha (sha (sha (...))) no es más seguro que sha. Si la entropía de la función sha no es máxima, en realidad es menos segura.
deadalnix
1
@deadalnix: es importante mencionar que no facilita la recuperación de la contraseña original, pero sí facilita la generación de una contraseña en conflicto, que es todo lo que se requiere.
Bryan Boettcher
1
@deadalnix, leí ese comentario en la voz de Dale Gribble .
Jiggy
1
@deadalnix: el objetivo de sha (sha (sha ())) no es, y nunca fue, agregar más entropía. La entropía solo la realiza el usuario inicial que elige su contraseña, todo lo demás (hash, sal, etc.) es solo para ralentizar un ataque de fuerza bruta. Si alguien es capaz de obtener su base de datos que contiene las contraseñas, que probablemente va a obtener el código utilizado para hash de la contraseña, así que cualquier sal no modificable es también conocido
woliveirajr
-1

Tengo entendido que usar múltiples algoritmos de hashing es derrotar a las tablas de arcoiris . Usar una buena sal también funciona, pero supongo que es un segundo nivel de protección.

jiggy
fuente
44
Bueno, esto no cambia mucho. La función «hash múltiple» puede verse como una y tratarse como tal.
deadalnix
2
El uso de múltiples técnicas de hash o iteraciones no hace nada para derrotar a las tablas de arcoiris. Si un atacante tiene su base de datos y tiene el método utilizado para generar los hashes, el atacante puede generar una tabla de arco iris para atacar todas las contraseñas en la base de datos. SALTS previene los ataques de la tabla del arco iris, ya que evitan que el atacante genere un solo diccionario de búsqueda para atacar, por ejemplo, todas las contraseñas de 8 caracteres o menos.
Erik
-1

Esto no es más seguro. Sin embargo, tiene un protocolo de identificación basado en hash varias veces con la misma función.

Esto va de esa manera. El valor almacenado es hash ^ n (pass) en la computadora A. A pide a B que se autentique y le da a B el número entero n. B hace el cálculo hash ^ (n-1) (pasar) y lo envía de vuelta a A.

Una comprobación de hash (hash ^ (n-1) (pass)) == hash ^ n (pass). Si es cierto, entonces se realiza la autenticación. Pero entonces, A store hash ^ (n-1) (pass) y la próxima autenticación, dará B n-1 en lugar de n.

Esto garantiza que la contraseña nunca se intercambie de forma clara, que A nunca sepa cuál es la contraseña y que la autenticación esté protegida por la reproducción. Sin embargo, esto tiene el inconveniente de requerir una contraseña con una vida útil limitada. Cuando n alcanza el valor 2, se debe elegir una nueva contraseña después de la autenticación.

Otro uso de hash múltiple es la herramienta HMAC, para garantizar la autenticación e integridad de una solicitud. Para obtener más información sobre HMAC, consulte http://en.wikipedia.org/wiki/HMAC .

La mayoría del uso de hash múltiple en el mundo real son excesivos. En su caso, parece ser. Tenga en cuenta que si utiliza varias funciones hash, no todas tendrán la misma entropía, por lo que esto reduce la fuerza del hash. Por ejemplo, md5 tiene menos entropía que sha1, por lo que usar sha1 en un md5 no mejorará la fuerza del hash. La fuerza generalmente será igual a la fuerza de la función hash más débil.

deadalnix
fuente