No respondiendo precisamente al tema, pero igualmente supongo que puede ser apreciado por aquellos a los que estos temas les resulta de interés...
La fuerza bruta sería aún más improductible, si el password fuera hasheado en el 'servidor' con dos algoritmos disitintos ... pués exige que un mismo password coincida con los hashes almacenados para sendos algoritmos, esto reduce notablemente dos posibilidades:
1 xxxxx: Hallar un hash para el password recibido que colisione con el hash generado para el password original. ...es demostrable que cuanto más pequeña sea la contraseña original, más fácil es que logre hallarse por una colisión.
Se eleva el costo de encontrar las soluciones por colisión a:
espacio de combinaciones: combinacionesAlgoritmo(A) * CombinacionesAlgoritmo(B)
- No debe confundirse que 'CombAlgA * CombAlgB' sea igual que 'combAlgA con password del doble de tamaño'. Éste último valor suele ofrecer muchas más combinaciones, pero complica enormemente al usuario al tener que exigirle el doble de caracteres para sus contraseñas.
Esto, curiosamente puede ser contraproducente, ya que ante tales exigencias (exigir un tamaño muy grande para las contraseñas) los usuarios suelen simplificar las contraseña en base a repetir caracteres y en general introducir secuencias más simples, lo que en definitiva en vez de aumentar la seguridad, la acaba reduciedo logrando el efecto contrario al deseado. Esto es tanto más cierto, cuanto más 'zoquete-negado' sea un usuario digital.
2 xxxxx: Explotar posibles vulnerabilidades halladas en uno o ambos algoritmos de hashing, para generar un password que colisione con el hash aún conociendo uno u ambos hashes. Nótese que el interés especial del diseño descrito estriba sobre todo en la fortaleza que se logra con esto...
- El producto de dos hashes, simplemente reduce las posibilidades de que un password distinto del original, colisione con el password original (sin necesidad de que para ello intervenga el propio usuario). Y aunque a priori no parezca muy importante porque las colisiones son difíciles, aumenta exponencialmente la fuerza de los algoritmos de hashes ante posible defectos en su diseño. Es decir complica enormemente explotar fallos y fugas en la fuerza del diseño del algoritmo. Por ello ambos algoritmos deben ser sutancialmente muy distintos, para así asumir que ambos no adolecen de exactamente los mismos errores.
Conociendo las vulnerabilidades de un algoritmo dado, y conocido un hash a ser generado, puede sortearse el algoritmo para encontrar algún password que colisione con el hash esperado. Sin embargo, ese password (que no es el original), y que ha sido generado al efecto aprovechando los defectos del diseño, acabará fallando para generar el hash con el segundo algoritmo, pués incluso aunque éste tenfa también sus defectos, no van a ser coincidentes con el previo.
Lo interesante del caso, es que con apenas unas líneas más de código (y un inapreciable tiempo de cálculo extra, que para el caso de la seguridad el tiempo de contrastar contraseñas favorece la seguridad, pués ralentiza los intentos de fuerza bruta), la seguridad aumenta notablemente.
Al caso, para no malograrlo, no deberían cometerse errores, como concatenar ambos hashes en uno, o hashear ambos hashes (con alguno u otro algoritmo), debe exigirse el test, con ambos hashes. Algo así:
bolueano = funcion Test(Password, Alias)
string hash1, hash2
hash1 = hashingAlgA(password)
hash2 = HaslingAlgB(password)
devolver (hash1 = Search(Alias, algA)) and (hash2 = Search(Alias, algB))
...donde las funciones 'HashingAlgA' y 'HashingAlgB' son dos funciones distintas de hashing y donde la función 'Search', localiza el hash correspondiente al 'Alias' y el tipo de algoritmo solicitado (algA y algB, serían valores enumerados o cualquier otro que identiifique claramente que hash debe entregarse).
Por supuesto nada impide que al almacenar ambos hashes en el servidor, si estén concatenados (por pura simplicidad) sabiendo que cada uno tiene un número de caracteres prefijado en el diseño y que la función 'Search', discrimina convenientemente.