Para reforzar un hash de contraseña, debes hacer dos al proceso de hash:
- para hacerlo único;
- para hacerlo lento.
"Único" significa que cada contraseña debe estar con su propia función hash; que se utiliza la función hash puede ser alguna información pública (es decir, almacenada a lo largo del valor de hash), pero desea hacerla diferente para cada contraseña que hash. Esto es lo que hace una sal : la sal define el procedimiento de hash a utilizar, entre una familia amplia. La singularidad derrota a las tablas de arco iris: las tablas de arco iris, al igual que todos los otros tipos de tablas precomputadas, se basan en la idea de que vale la pena dedicar un poco de tiempo a procesar muchas contraseñas y almacenar los valores de hash (posiblemente de una manera inteligente que permita cierta compresión extrema) , como las tablas arco iris), porque la tabla resultante se puede usar para atacar contraseñas de varias , con un costo marginal por contraseña muy pequeño. Con las sales, cada contraseña tiene su propia función, por lo que la tabla sería válida para, como máximo, una sola contraseña, lo que destruye sus ventajas.
Hashing "1000 (o más) veces" la contraseña no incluye un salt y, como tal, es vulnerable a las tablas precomputadas. Por ejemplo, asumiendo SHA-256 como función hash, aquí está su contraseña hash:
f3f19029aa4ef4bde723f49b4e90a7ad51473c54a03589af6fef706bf50d7894
Ese es el hash SHA-256 de 1000 'a' caracteres. Podría calcular este valor porque una vez que haya dicho "1000", lo habrá dicho todo; Sin sal, por lo tanto, no es una sorpresa para el atacante.
Lentitud trata de hacer que cada contraseña sea lo más cara posible para el atacante. Incluso con un buen uso de sal, una contraseña con hash individual puede ser vulnerable a la fuerza bruta, también conocida como " dictionary attack " (probar contraseñas potenciales), porque los humanos no son tan imaginativos como las computadoras son poderosos. Una PC con una GPU puede calcular una función hash un billón de veces por segundo aproximadamente. Queremos un procedimiento de hash que tarde más tiempo en calcularlo, no demasiado, porque nuestro servidor honesto también también tendrá contraseñas de hash cuando un usuario inicia sesión, y tampoco tenemos una CPU infinita; pero solo necesitamos un hash, como máximo, una docena de contraseñas por segundo, para poder tolerar una función de hash sustancialmente lenta.
Por lo general, la lentitud se obtiene mediante el hashing anidado: hash la contraseña, luego hash el valor hash resultante, que hash nuevamente, y así sucesivamente. Hay algunos detalles difíciles sobre cómo y dónde se inserta la sal. Hashing la concatenación de 1000 veces (en realidad, con las cifras anteriores, 1 millón de veces sería mejor) la contraseña (o la concatenación de la contraseña y la sal) podría servir al mismo propósito, pero es un poco delicado en la práctica: de hecho, queremos configurar el número de repeticiones de la contraseña para que el procedimiento sea tolerablemente lento. Pero con tal sistema, el hashing de una contraseña de 40 caracteres toma 40 veces más tiempo que el hashing de una contraseña de 1 carácter; si el último debe ser lento, el primero será 40 veces más lento, lo que pronto se volverá intolerable. Con el hashing anidado, es más fácil obtener un tiempo de hashing constante, lo que facilita la configuración.
Y, por supuesto, lo casero es malo . Insertar una contraseña y un salt en una función hash, iterada y / o anidada, es sutil; hay escollos y, lo que es peor, no puedes saber si lo hiciste mal o no. La seguridad no puede ser probada de manera confiable. Por lo tanto, debe atenerse a los estándares publicados y ampliamente implementados de buena reputación, como bcrypt y PBKDF2 . Solo porque eso significa que cualquier percance no será culpa de su .