que - ¿Por qué la función SlowEquals es importante para comparar contraseñas hash?
que es hash pdf (3)
El hecho de que el algoritmo compare todos los bytes de los dos hashes es simplemente el resultado de la implementación y no está relacionado con el uso de XOR (es decir, se podría escribir un algoritmo que compare todos los bytes sin romper la primera discrepancia incluso usando == ) El uso de XOR pretende evitar la introducción de instrucciones de bifurcación en el cuerpo del bucle, lo que podría revelar detalles sobre el número de bytes coincidentes como resultado de la predicción de bifurcación de la CPU (aunque si ese es un problema dependerá en cierta medida de la implementación particular y las instrucciones para las que está compilado).
El uso de un sueño aleatorio () para enmascarar el tiempo de un control hash que retorna en el primer desajuste en realidad no funciona, ya que aún es posible distinguir el emparejamiento del desajuste en un punto dado al tomar más muestras. En aras de la argumentación, si suponemos que dormimos durante un número aleatorio de milisegundos distribuidos uniformemente en el rango [0..100], y una coincidencia en una posición determinada tarda 2 ms y una falta de coincidencia en esa posición tarda solo 1 ms (como el algoritmo sale temprano). Con un muestreo suficiente podríamos distinguir los casos de coincidencia y desajuste, ya que observaríamos respuestas que van desde [1..101] ms en el caso de desajuste, pero [2..102] ms en el caso de coincidencia (suponiendo que podemos sincronizar las respuestas a la perfección) . Por supuesto, las observaciones en el mundo real sufrirían inestabilidad y otras fuentes de aleatoriedad, pero aún se observaría un sesgo.
Entonces, por supuesto, existe simplemente la consideración práctica: ¿por qué introducir duerme, randoms, etc. cuando modificaciones relativamente menores deberían dar como resultado que se ejecutara en un tiempo constante, y eliminando los ataques de temporización?
Recientemente leí un artículo sobre el hash y el salado de contraseñas donde se explicaba (en "¿Cómo funciona el código SlowEquals?") Que se debe usar una función SlowEquals para comparar el hash de la contraseña ingresada con el hash de la contraseña en la base de datos .
Según tengo entendido, se usa la función SlowEquals porque usa XOR en lugar de == y como resultado comprobará cada carácter en ambas cadenas en lugar de fallar en los primeros caracteres que no coinciden.
Hay dos cosas que no entiendo:
- ¿Por qué XOR continuará revisando la cadena después de que se alcanza una condición de falla?
- Si la idea principal es no dar al atacante ninguna información útil al intentar descifrar una contraseña, ¿no funcionaría una función sleep () con un tiempo generado aleatoriamente?
TL; DR: no es importante usar SlowEquals cuando se comparan los valores hash de contraseñas.
Si estabas tratando de verificar un secreto no hash, entonces usar "SlowEquals" sería valioso para frustrar un ataque de tiempo.
Sin embargo, si está utilizando un hash de contraseña adecuado que sea lo suficientemente computacionalmente intensivo (PBKDF2, 50k + iteraciones) simplemente no importa. ¿Por qué? Debido a que el hashing de contraseña "asume una violación". Incluso si el atacante roba / conoce el hash Y la sal, lleva demasiado tiempo encontrar una contraseña de texto simple que tenga ese valor y, por lo tanto, la contraseña aún esté protegida. Ese es el objetivo de los algoritmos hash criptográficos, son inutilizables incluso si son robados. Claro, alguien podría usar un ataque de tiempo para resolver el hash, pero no importa, porque aún no podrán descifrar la contraseña.
Junto con la funcionalidad de bloqueo, donde la cuenta se bloquea después de X intentos no válidos (3-10, elige), los ataques de tiempo en contraseñas hash pasa de inútiles a indudablemente sin valor.
Si no hay SlowEquals .
Consideremos que el cálculo compara dos chararters usando 2 segundos (más rápido en el cálculo real, pero una gran cantidad de pruebas podrían funcionar), y usamos 1234554321 como la contraseña. El atacante usa 0000000000 para intentarlo. Debido a que no usamos la función slowEquals, la comparación toma solo 2 segundos debido a 0! = 1, por lo que cuando el atacante conoce los "2 segundos", cambiará el "0" por otro hasta que use "1000000000" y luego el servidor toma 4 segundos