Cualquier respuesta significativa deberá tener en cuenta algunos detalles, por ejemplo, qué función hash se utilizó para proteger las contraseñas.
Si creó un diccionario con todas las combinaciones posibles de contraseñas, comenzando con "111111" y terminando con "zzzzzz" (asumiendo solo letras mayúsculas, letras minúsculas y dígitos), y no ordene este diccionario por probabilidad de contraseña, pero manteniéndolo en orden lexicográfico, la pregunta sería cuál era más rápida: introducir estas cadenas de diccionario en su buscador de contraseñas o hacer que el que crea las combinaciones cree las combinaciones sobre la marcha.
Para responder a esa pregunta, debemos saber dónde almacenamos nuestro diccionario, que es lo suficientemente grande como para que probablemente no lo podamos guardar por completo en la memoria, por lo que tendremos que almacenarlo en un disco duro.
También es importante saber que los discos duros (la variante de disco giratorio y magnético) tienen tiempos de acceso en el rango de milisegundos. La RAM es mucho más rápida, pero sigue siendo lenta en comparación con la memoria caché L1, que a su vez es mucho más lenta que el acceso directo al registro en una CPU. Desafortunadamente, los registros de CPU de propósito general solo pueden almacenar aproximadamente 128 bytes, y el caché L1 solo almacena unos pocos kb en total.
Nuevamente, asumiendo que estaba trabajando con una computadora que tenía 8 GB de memoria reservada para su uso, podría mantener alrededor de mil millones de entradas de diccionario en la RAM al mismo tiempo. Eso es aproximadamente el 2% de todo el espacio clave.
Si cargó su diccionario desde el disco duro, tendría que cargar un total de 325 gigabytes de datos (en archivos basura de aproximadamente 4 GB cada uno, siempre cargaría 4 GB de contraseñas al intentar las contraseñas en el otros 4 GB). Incluso con los SSD, eso llevaría un tiempo.
Ahora, si estuviera tratando con una función hash como md4, hashcat agotaría fácilmente sus contraseñas candidatas antes de poder cargar el siguiente lote, porque en una GPU moderna puede literalmente probar miles de millones de contraseñas cada segundo. En la práctica, no puede cargar contraseñas candidatas tan rápido desde el disco duro. Por otro lado, si estuviera intentando atacar contraseñas cifradas con una función hash como bcrypt, la carga de contraseñas candidatas desde el disco duro ni siquiera haría mella en el tiempo necesario para atacar con éxito la contraseña, porque incluso las GPU modernas no pueden Bcrypt lo suficientemente rápido como para agotar 500 millones de candidatos antes de que los siguientes 500 millones puedan cargarse desde el disco duro.
Veamos si crear las contraseñas sobre la marcha, en lugar de cargarlas en RAM en grandes cantidades, sería más rápido:
Las CPU tienen algunas propiedades interesantes. Por ejemplo, utilizan la búsqueda previa de instrucciones, la predicción de bifurcación y la ejecución tentativa para ejecutar el código antes de que realmente se sepa si debe ejecutarse o no. Junto con la memoria caché de la CPU, esto significa que si ejecuta un fragmento de código muy pequeño y ajustado, como el código para enumerar todas las combinaciones posibles de una longitud de bit determinada, básicamente puede ejecutarse por completo en la CPU, sin tocar (lento) RAM . Las contraseñas pequeñas (6-8 bytes) caben fácilmente en un solo registro de CPU, las contraseñas de 16 bytes aún caben en dos registros. El código para generar la siguiente contraseña candidata a partir de la última es tan simple como usar una instrucción "agregar", que es una de las instrucciones de CPU más rápidas que existen. Así que estoy bastante seguro de que podría generar cada combinación de contraseña mucho más rápido de lo que podría cargar la lista completa desde una fuente externa.
Pero, nuevamente, el tiempo que una CPU (o GPU) necesitaría para calcular un hash bcrypt real para comparar con una contraseña con hash disminuiría el tiempo requerido para generar las contraseñas candidatas.
Por lo tanto, el método de generación de contraseña simplemente no es tan importante para las contraseñas bien protegidas. Solo importa cuando se trata de funciones hash débiles o muy rápidas como md4, md5, sha1 etc.
Conclusión
Si asume que todas las contraseñas son igualmente probables, generar todas las contraseñas una tras otra (forzados brutos) sobre la marcha tiene más sentido, ya que no necesitará tener grandes diccionarios en su disco duro. Puedes crearlos más rápido sobre la marcha. Esta es la razón por la que nadie guarda diccionarios de contraseñas sin clasificar en sus discos duros para forzar estúpidamente.
Por otro lado, si admite que algunas contraseñas (piense en "123456" y "contraseña" son más probables que otras (piense en "1qHGmR"), luego cree un diccionario de estas contraseñas y cargue ese diccionario en la RAM, y tal vez el uso de algunas reglas para crear derivados, como "sarah1997" y "sarah1998" de la entrada del diccionario base "sarah", es bastante más rápido.
Dicho esto, si en realidad estás lidiando con contraseñas de 6 letras y una función hash débil, no importará mucho, ya que hashcat y sus compatriotas pueden agotar un espacio de teclas de 6 caracteres por fuerza bruta en cuestión de minutos. Horas o días, según la función hash utilizada y la potencia de la plataforma GPU disponible.