python encryption pbkdf2

python passlib: ¿cuál es el mejor valor para "rondas"



encryption pbkdf2 (1)

de la documentación de passlib

Para la mayoría de los servicios públicos, generalmente puede iniciar sesión para tomar más de 250ms - 400ms antes de que los usuarios comiencen a molestarse.

Entonces, ¿cuál es el mejor valor para las rounds en un inicio de sesión / registro si consideramos que hay una llamada para la base de datos para el intento de inicio de sesión y usa MongoDB con una llamada no bloqueante ? (utilizando Mongotor , y utilizando el correo electrónico como _id , por lo que está indexado por defecto, la consulta es rápida: 0.00299978256226 y, por supuesto, probado con una base de datos que tiene 3 registros ...)

import passlib.hash import time hashh = passlib.hash.pbkdf2_sha512 beg1 = time.time() password = hashh.encrypt("test", salt_size = 32, rounds = 12000) print time.time()- beg1 # returns 0.142999887466 beg2 = time.time() hashh.verify("test", password) # returns 0.143000125885 print time.time()- beg2

ahora si uso medio valor:

password = hashh.encrypt("test", salt_size = 32, rounds = 4000) # returns 0.0720000267029 hashh.verify("test", password) # returns 0.0709998607635

estoy usando Windows 7 64 bits en Dell XPS 15 i7 2.0 Ghz

NB: instaló bcrypt , y por supuesto, es un verdadero dolor usarlo directamente como sus valores predeterminados ( rounds = 12 ):

hashh = passlib.hash.bcrypt beg1 = time.time() password = hashh.encrypt("test", rounds = 12) # returns 0.406000137329 print time.time()- beg1 beg2 = time.time() hashh.verify("test", password) # returns 0.40499997139 print time.time()- beg2

medio valor:

password = hashh.encrypt("test", rounds = 12) # 0.00699996948242 wonderful? hashh.verify("test", password) # 0.00600004196167

¿Me puede sugerir un buen valor de rondas al usar pbkdf2_sha512 que será bueno para la producción?


(desarrollador de passlib aquí)

La cantidad de tiempo que toma pbkdf2_sha512 es linealmente proporcional a su parámetro de rondas ( elapsed_time = rounds * native_speed ). Usando los datos para su sistema, native_speed = 12000 / .143 = 83916 iterations/second , lo que significa que necesitará alrededor de 83916 * .350 = 29575 rounds para obtener ~ 350ms de retraso.

Las cosas son un poco complicadas para bcrypt, porque la cantidad de tiempo que toma es logarítmicamente proporcional a su parámetro de rondas ( elapsed_time = (2 ** rounds) * native_speed ). Usando los datos para su sistema, native_speed = (2 ** 12) / .405 = 10113 iterations/second , lo que significa que necesitará alrededor de log(10113 * .350, 2) = 11.79 rounds para obtener ~ 350 ms de retraso. Pero dado que BCrypt solo acepta los parámetros de las rondas enteras, entonces tendrá que elegir rounds=11 (~ 200ms) o rounds=12 (~ 400ms).

Todo esto es algo que espero solucionar en una versión futura de passlib. Como un trabajo en progreso, el repositorio mercurial de passlib actualmente contiene un pequeño script simple, choose_rounds.py , que se encarga de elegir el valor de rondas correcto para un tiempo objetivo dado. Puede descargarlo y ejecutarlo directamente de la siguiente manera (puede tardar unos 20 segundos en ejecutarse):

$ python choose_rounds.py -h usage: python choose_rounds.py <hash_name> [<target_in_milliseconds>] $ python choose_rounds.py pbkdf2_sha512 350 hash............: pbkdf2_sha512 speed...........: 83916 iterations/second target time.....: 350 ms target rounds...: 29575 $ python choose_rounds.py bcrypt 350 hash............: bcrypt speed...........: 10113 iterations/second target time.....: 350 ms target rounds...: 11 (200ms -- 150ms faster than requested) target rounds...: 12 (400ms -- 50ms slower than requested)

(editar: respuesta agregada con respecto a rondas mínimas seguras ...)

Descargo de responsabilidad: Determinar un mínimo seguro es una pregunta sorprendentemente difícil: hay una serie de parámetros difíciles de cuantificar, muy pocos datos del mundo real y alguna teoría rigurosamente inútil. Al carecer de una buena autoridad, he estado investigando el tema yo mismo; y para los cálculos fuera del manguito, he reducido los datos sin procesar a una fórmula corta (a continuación), que generalmente es lo que uso. Solo tenga en cuenta que detrás de él hay un par de páginas de suposiciones y estimaciones aproximadas, por lo que es más una estimación de Fermi que una respuesta exacta: |

Mi regla general (mediados de 2012) para atacar a PBKDF2-HMAC-SHA512 usando GPU es:

days * dollars = 2**(n-31) * rounds

  • days es la cantidad de días antes de que el atacante tenga una probabilidad del 50/50 de adivinar la contraseña.
  • dollars es el presupuesto de hardware de los atacantes (en $ USD).
  • n es la cantidad promedio de entropía en las contraseñas de usuario (en bits).

Para responder a la pregunta del script-kiddie: si una contraseña promedio tiene 32 bits de entropía y el atacante tiene un sistema de $ 2000 con una buena GPU, entonces en 30000 rondas necesitarán 30 días ( 2**(32-31)*30000/2000 ) para tener una probabilidad de 50/50 de descifrar un hash dado. Recomiendo jugar con los valores hasta que llegue a una compensación de rondas / días con la que se sienta cómodo.

Algunas cosas para tener en mente:

  • La tasa de éxito de un ataque de diccionario no es lineal, es más una situación de "cola larga", así que piense en la marca 50/50 como más de una vida media.

  • Ese 31 es el factor clave, ya que codifica una estimación del costo de atacar un algoritmo específico utilizando un nivel tecnológico específico. El valor real, 2**-31 , mide los "días-dólar por ronda" que le costará a un atacante. A modo de comparación, atacar PBKDF2-HMAC-SHA512 usando un ASIC tiene un factor más cercano a 46 - números más grandes significan más explosión para el dinero del atacante, y menos seguridad por ronda para ti, aunque los script kiddies generalmente no tendrán ese tipo de presupuesto :)