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).