security - password - ¿Necesito una "sal aleatoria" una vez por contraseña o solo una vez por base de datos?
que es salt en criptografia (4)
Cambiar dinámicamente la sal es mucho más seguro que tener una sola sal estática.
También haga que las sales sean únicas por usuario y no una sal global. Cámbielos cada vez que un usuario inicie sesión, por ejemplo.
Concatenar la sal hasta el final de la contraseña y, a continuación, hash, está bien, pero es una fórmula fácil de adivinar. Lo mejor es crear el suyo propio, es decir, tejer la sal y la contraseña para crear una nueva cadena y luego hash, ya que md5 (contraseña + sal) es vulnerable al ataque de diccionario.
Además de mi pregunta anterior sobre las contraseñas saladas en PHP / MySQL , tengo otra pregunta con respecto a las sales.
Cuando alguien dice "use una sal al azar" para pre / agregar a una contraseña, ¿significa esto:
- Creando una cadena de caracteres estática, aleatoriamente generada 1 vez , o
- ¿Creando una cadena de caracteres que cambia al azar cada vez que se crea una contraseña ?
Si la sal es aleatoria para cada usuario y se almacena junto con la contraseña hash, ¿cómo se recupera la sal original para la verificación?
La sal debe almacenarse con el hash para que la verificación sea posible. La mejor práctica sería usar una sal diferente cada vez que se crea o modifica una contraseña.
La segunda alternativa es la correcta.
Tradicionalmente, la sal se almacena junto con la contraseña hash, pero no cifrada (generalmente preaplicada, por ejemplo, en contraseñas Unix )
Actualización: el método utilizado en el sistema Unix más nuevo es este .
Se debe generar aleatoriamente una nueva sal para cada usuario y cada vez que cambien su contraseña como mínimo. No confíe solo en la sal de un sitio amplio, por ejemplo, ya que eso no tiene sentido para usar una sal en primer lugar.
Usar una sal única para cada usuario es tal que si dos usuarios tienen la misma contraseña no obtendrán el mismo hash resultante. También significa que se debe montar un ataque de fuerza bruta contra cada usuario individualmente en lugar de precomputar una tabla de arcoíris para el sitio.
A continuación, almacena el resultado de hash la sal y la contraseña en el hash(salt + password)
la base de datos hash(salt + password)
, junto con la salt
para cada usuario. Puede almacenarlos en columnas separadas, o todo en una columna (separados por algún carácter no utilizado en los hash, por ejemplo,). Mientras puedas recuperar ambos, estarás bien.
Sin embargo, si su base de datos se ve comprometida, ya sea porque alguien obtiene acceso local o mediante ataques de inyección SQL, entonces estarán disponibles el hash final y sal, lo que significa que un ataque de fuerza bruta contra las contraseñas de los usuarios sería trivial. Para combatir esto, como sugiere The Rook , también puedes usar una clave secreta de todo el sitio almacenada en un archivo localmente como otra entrada de tu método hash para que un atacante también necesite saber esto para montar un ataque efectivo. Lo que significa que su base de datos debería estar en peligro Y que el atacante necesitaría acceder a los archivos locales. Entonces, usar hash(hash(salt + secret) + password)
, etc.
Mientras que en la mayoría de los algoritmos pretendes hacer las cosas lo más rápido posible, para el hash de contraseñas que deseas ralentizar, esto se denomina Fortalecimiento de claves (o, a veces, Estiramiento de claves). Si su función hash tarda 0.00001 segundos en volver, alguien puede intentar con fuerza bruta forzar 100.000 contraseñas por segundo hasta que encuentre una coincidencia. Si su función hash tarda 1 segundo en escupir el resultado, no es gran cosa para alguien que ingresa a su aplicación, pero para descifrar la contraseña es un problema mayor, ya que cada intento ahora tomará 1 segundo para obtener un resultado, lo que significa que tomaría 100,000 veces más tiempo probar cada contraseña bruta forzada de lo que usaría su función hash original.
Para hacer que su función hash sea más lenta, solo necesita ejecutarla varias veces. Por ejemplo, puede hacer new_hash = salt + password + previous_hash
100,000 veces. Es posible que necesite ajustar el número de iteraciones a un valor más alto si es demasiado rápido. Si desea poder cambiar el valor más tarde, asegúrese de almacenar el número de iteraciones con el registro del usuario para que no afecte ninguna contraseña previamente almacenada.
Su registro de usuario ahora debe tener un campo con formato algo así como " $<algorithm>$<iterations>$<salt>$<hash>
" (o como campos separados si lo desea).
Cuando el usuario ingresa su contraseña, puede recuperar la sal y el número de iteraciones de la base de datos y el secreto del sitio de un archivo local y validar que cuando ejecuta la misma cantidad de iteraciones con la sal y la contraseña, el hash resultante coincide con has almacenado
Si el usuario cambia su contraseña, entonces debe generar una nueva sal.
El método de hash que utiliza no importa (pero el algoritmo de hashing no *). Arriba sugerí hash(hash(salt + secret) + password)
pero igualmente podría ser hash(hash(salt) + hash(secret) + hash(password))
. El método que usa no cambia la efectividad de su almacenamiento de contraseñas, uno realmente no es más seguro que el otro. Confiar en el diseño de cómo hash la contraseña y la sal juntos para proporcionar seguridad se llama seguridad a través de la oscuridad y debe evitarse.
* No debe usar MD5 o SHA-1 ya que se consideran inseguros. Use la familia SHA-2 en su lugar (SHA256, SHA512, etc.). ( Ref )