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

39

He leído varias veces que al almacenar contraseñas, es una buena práctica 'hacer 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, entonces 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 pienso en ello, cada vez que se vuelve a romper un hash (posiblemente con algo agregado), lo único 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ítame ponerlo de otra manera: tenemos x número de cadenas que, cuando se han modificado, se reducen a y cadenas posibles. Es decir, hay colisiones en el primer set. Ahora que viene del segundo conjunto al tercero, ¿no es posible que ocurra lo mismo (es decir, colisiones en el conjunto de todas las cadenas 'y' posibles que dan como resultado 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 que tiene ante sí, dándonos un conjunto no mayor que la entrada.

¿Quizás un ejemplo explique mis divagaciones? Toma 'hash_function_a' que dará 'a' y 'b' el hash '1', y dará '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'.

Toma 'hash_function_b' que dará a '1' y '2' el hash '3'. Si tuviera que usar it como un 'hash secundario' después de 'hash_function_a', entonces incluso si la contraseña es 'a' podría usar 'b', 'c' o 'd'.

Además de todo eso, obtengo que se deben usar sales, pero realmente no cambian el hecho de que cada vez que asignamos entradas 'x' a 'menos que x' salidas. No creo.

¿Puede alguien explicarme por favor qué es lo que me estoy perdiendo aquí?

¡Gracias!

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

    
pregunta Narcissus 20.10.2011 - 19:52

6 respuestas

25

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 hashn (el hash más interno) produce una colisión, toda la cadena de hash dará una colisión ( independientemente de qué otros hashes estén en 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 un salt que depende de la contraseña para el hash final.

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

    
respondido por el ratchet freak 20.10.2011 - 20:18
51

Usar diferentes algoritmos de hash es una mala idea, ya que reducirá la entropía en lugar de aumentarla.

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

Los algoritmos de hashing recientes como bcrypt se basan en esta idea; contienen un parámetro para controlar la complejidad computacional del hash, para que pueda escalar 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 la fuerza bruta hashes permanece aproximadamente constante.

    
respondido por el tdammers 20.10.2011 - 22:08
3

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

Debería usar una implementación bien establecida del hashing de contraseñas que a su vez debería usar una función de derivación de claves ( KDF ), tal como como PBKDF2, bcrypt, scrypt o el Argon2 más reciente.

Los KDF buenos incluyen un factor de trabajo, generalmente una serie de iteraciones, para aumentar el costo de los ataques sin conexión. Se podría decir que estos KDF tienen 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.

    
respondido por el Erwan Legrand 15.10.2013 - 11:58
2

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

Lo que debes hacer es:

Usa sal: la sal no se usa solo para hacer que tu contraseña sea más segura , se usa para evitar el ataque a la tabla del arco iris. De esa manera, alguien tendrá un trabajo más duro tratando de calcular previamente el hash para las contraseñas que almacena 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 + salt)))))). O, para representar de otra manera:

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

Y, finalmente, elige una buena función de hash. SHA, MD5, etc., no son buenos porque son rápidos . Ya que quiere usar hash para protección, es mejor que use hashes más lentos. Eche un vistazo a Bcrypt , PBKDF2 o Scrypt , por ejemplo.

editar : después de las observaciones, tratemos de ver algunos puntos (lo siento, una larga explicación para llegar al final, ya que podría ayudar a otros a buscar respuestas similares):

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

Pero nadie puede asegurar que la base de datos con las contraseñas será robada. Robar la base de datos, tiene todas las contraseñas. Ok, su sistema y su empresa sufrirán todas las consecuencias de ello. Por lo tanto, podríamos intentar evitar esta pérdida 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 las contraseñas incorrectas, bloquear la cuenta después de algunos intentos, etc. Y para eso no importa de qué manera cifre, haga hash, almacene, etc., su contraseña. El ataque en línea es una cuestión de ralentizar las entradas de contraseña .

Entonces, volvamos al problema don't let them take my plain passwords . La respuesta es simple: no los almacene como texto plano. Ok, lo tengo.

¿Cómo evitar eso?

Cifrar la contraseña (?). Pero, como sabe, si lo cifra, puede descifrarlo si tiene la clave adecuada. Y terminarás con el problema de "dónde ocultar la clave". Hum, no está bien, ya que tienen tu base de datos, pueden obtener tu llave. Ok, no lo usemos.

Por lo tanto, otro enfoque: transformemos la contraseña en otra cosa que no pueda revertirse y almacenémosla. Y para verificar si la contraseña proporcionada es correcta, hacemos el mismo proceso nuevamente y verificamos si los dos valores modificados coinciden. Si coinciden = se proporcionó la contraseña correcta.

Ok, hasta ahora todo bien. Vamos a usar un hash MD5 en la contraseña. Pero ... si alguien tiene nuestro valor hash de contraseña almacenado, puede tener una gran cantidad de 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 todo el MD5 de todas las combinaciones de caracteres y encontrar fácilmente la contraseña. Por lo tanto, haga muchas interacciones, lo HASH (HASH (HASH (HASH ())), para hacerlo más difícil, ya que tomará más tiempo.

Pero incluso eso puede ser evitado, la tabla del arco iris fue creada exactamente para acelerar contra este tipo de protección.

Por lo tanto, vamos a usar un poco de sal sobre él. De esta manera, en cada interacción, la sal se utiliza de nuevo. Uno que 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 del arco iris, ya que se generó con una sal, tendrá que volver a calcular con la otra sal, por lo que tendrá que dedicar algo de tiempo a 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 un salt para cada contraseña, la tabla de un salt no sirve para otra contraseña.

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

Y el uso de 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 que se explotará, en cualquier punto del proceso de iteración, para romper la contraseña. Entonces, no ganas nada usando más algoritmos de hashes, es mejor elegir solo algo bueno. y usarlo. Y si alguna vez escuchas que se ha roto, piensa cómo lo cambiarás en tu aplicación.

Y por qué usar bcrypt o algo así (dices que lo usas): porque el atacante tendrá que dedicar más tiempo a generar las tablas. Es por eso que usar MD5 + esperar (3 segundos) no ayuda: el ataque estará fuera de línea, de todos modos, para que el atacante pueda generar las tablas sin el (retraso de 3 segundos).

    
respondido por el woliveirajr 20.10.2011 - 20:10
-1

Entiendo que el uso de múltiples algoritmos de hash es derrotar a tablas de arco iris . El uso de una buena sal también funciona, pero creo que es un segundo nivel de protección.

    
respondido por el jiggy 20.10.2011 - 20:36
-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 (pase) en la computadora A. A le pide a B que autentifique y le da a B el número entero n. B hace el cálculo hash ^ (n-1) (pase) y lo envía de vuelta a A.

Un cheque que hash (hash ^ (n-1) (pass)) == hash ^ n (pass). Si es verdad, entonces la autenticación está hecha. Pero entonces, un hash de la tienda ^ (n-1) (pase) y la siguiente 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 del hash múltiple es la herramienta HMAC, para garantizar la autentificación y la integridad de una solicitud. Para obtener más información sobre HMAC, consulte enlace .

La mayoría del uso de hash múltiple en el mundo real es excesivo. En tu caso, parece serlo. Tenga en cuenta que si utiliza varias funciones hash, no todas tendrán la misma entropía, por lo que se reducirá 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.

    
respondido por el deadalnix 20.10.2011 - 21:29

Lea otras preguntas en las etiquetas