¿Es posible aumentar el costo de BCrypt o PBKDF2 cuando ya está calculado y sin la contraseña original?

31

Solo quería saber si puede aumentar el costo (iteraciones) de estos dos algoritmos fuera de línea. Quiero aumentar el costo cada año de las contraseñas de mis usuarios.

Una solución es volver a calcularlos cuando el usuario inicia sesión, pero es posible que un usuario no haya iniciado sesión en ese período, y no quiero esperar hasta que inicie sesión.

Esto se podría hacer con la extensión de la contraseña (por ejemplo, iterar sobre un hash sha-256), pero no sé si esto es posible con BCrypt y / o PBKDF2. Gracias.

    
pregunta skantos 08.06.2012 - 22:48
fuente

5 respuestas

14

PBKDF2 y Bcrypt no admiten aumentar el costo, comenzando desde la salida en un recuento de iteraciones dado, sin el conocimiento de la contraseña. No hay una razón intrínseca para eso; un proceso de hashing de contraseña podría permitir dicho estiramiento fuera de línea mientras sigue siendo "bueno". Pero estos algoritmos pasan a no permitirlo.

Lo que se puede hacer es lo siguiente: una salida bcrypt o PBKDF2 normal incluye la sal s , el recuento de iteraciones i y la salida hash v . En las implementaciones de bcrypt, los tres valores a menudo se codifican en caracteres imprimibles (con una codificación similar a Base64); Consulte, por ejemplo, esta respuesta . Suponiendo que tenga s y v , puede almacenar lo siguiente:

  • la sal s ;
  • un recuento de iteraciones i ;
  • una cuenta de iteración extra j ;
  • el valor h (h (h (... h (h (v))))) que es el resultado del hashing v repetidamente, con una función hash segura h , realizada j veces.

Para la verificación de la contraseña, tiene que volver a calcular el bcrypt / PBKDF2 a partir de la contraseña dada (usando s y i ), y luego retoque el valor resultante j veces, para ver si coincide con el valor almacenado.

Esto es en su mayoría seguro, si usa una función hash fuerte para h , como SHA-256. Se puede mostrar que el hashing repetido reduce el espacio de valores posibles, pero debe alcanzar un "ciclo" interno de tamaño aproximadamente sqrt (N) si los valores de salida de hash están en un espacio de tamaño N ; además, si ese ciclo es lo suficientemente pequeño como para ser explorado exhaustivamente, entonces se puede calcular una colisión en la función hash h (consulte esta página para un buen diagrama). Por lo tanto, si h es resistente a colisiones (como SHA-256), entonces el esquema anterior es seguro.

El punto importante es que puede aumentar j más tarde, sin conexión. Sin embargo , tenga en cuenta que este tipo de estiramiento se basa en el costo de computación involucrado en la realización de muchos cálculos adicionales de función hash. Desafortunadamente, las funciones hash habituales como SHA-256 se asignan realmente bien a lo que puede hacer la GPU; por lo tanto, la ventaja obtenida de esa manera sobre el atacante podría no ser tan grande como se deseaba inicialmente. En otras palabras, el uso del estiramiento descrito anteriormente invalida cualquier ventaja de bcrypt sobre PBKDF2 (consulte esta respuesta para una discusión sobre este tema). Puede aplicarlo como una medida temporal, hasta que dicho usuario regrese, de modo que el paso bcrypt pueda realizarse nuevamente con un recuento de iteraciones más alto ( i ).

Además , el esquema que describo anteriormente es criptografía casera, y eso es malo. Puedo salirme con la suya porque soy totalmente increíble, pero esto no se puede promover de manera general.

    
respondido por el Thomas Pornin 28.10.2012 - 17:33
fuente
8

bcrypt depende del algoritmo de Eksblowfish que se define como:

Eksblowfish(cost, salt, key)
  state = InitState()
  state = ExpandKey(state, salt, key)
  repeat (2^cost)
    state = ExpandKey(state, 0, key)
    state = ExpandKey(state, 0, salt)
  return state

Este código muestra el número de iteraciones. Como el uso de bcrypt es: bcrypt(cost, salt, key) , la variable cost es log2 de iteraciones. Entonces, agregar uno a cost duplica el tiempo.

Cada ronda usa la contraseña inicial (clave), no puedes agregar rondas adicionales sin ella. Entonces, para Bcrypt, la respuesta es no.

    
respondido por el p____h 10.06.2012 - 00:14
fuente
7

Como lo menciona p

respondido por el Bradley Gottfried 12.06.2012 - 17:58
fuente
4

Tenía el mismo requisito y lo resolví de esta manera:

  • Hash la sal y la contraseña de la manera habitual con PBKDF2 y un factor de trabajo que actualmente es 16 (es decir, 2 ^ 16 iteraciones). Almacene la sal, el hash, el factor de trabajo, etc. como una fila en una tabla de base de datos.
  • Asincrónicamente (es decir, no afecta al usuario final), haga esto 3 veces más, aumentando el factor de trabajo en 1 cada vez. Así que ahora tengo 4 filas de bases de datos para ese usuario, con factores de trabajo de 16, 17, 18 y 19 respectivamente.
  • Siempre uso la fila con el factor de trabajo más bajo para verificar la contraseña, pero cada 2 años borro la fila con el factor de trabajo más bajo.
respondido por el RoadWarrior 08.04.2013 - 03:14
fuente
0

Imagine que era posible alargar el número de rondas de una clave sin la contraseña original. Si ese fuera el caso, sería posible construir una tabla de arco iris que se asigne desde la salida después de 1 iteración a la salida después de 1000 iteraciones. La tabla haría que sea rápido para revertir 1000 iteraciones.

Dada esa tabla, un cracker podría revertir 1000 iteraciones a 1 y luego simplemente intentar crackear el PBKDF con solo 1 iteraciones. Eso debilitaría el algoritmo.

    
respondido por el Eyal 31.08.2012 - 16:22
fuente

Lea otras preguntas en las etiquetas