2
\$\begingroup\$

I've been making a brute force program for fun. This program tries to guess a password using brute force. I've tried many things to help increase the efficiency. Here it is: (Sorry for the lack of comments)

from itertools import product
from time import time
def findamount(find):
 constValues = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
 dictValues = {constValues[n]:n+1 for n in range(62)}
 value = 0
 for n in range(len(str(find))):
 x = len(str(find)) - (n+1)
 value += dictValues[find[n]] * (62**x)
 return value
def fast(password):
 password = tuple(password)
 origtime = time()
 length = 1
 constValues = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
 for a in range(10000000): #More efficient than while True
 for n in product(constValues, repeat=length):
 if n == password:
 amount = findamount(''.join(list(n)))
 amountTime = time() - origtime
 if amountTime == 0:
 print(f"Length = {length}, Amounts = {amount}\nTime elapsed = 0 secs\nAttempts per sec = ? TIME TOO SHORT")
 else:
 print(f"Length = {length}, Amounts = {amount}\nTime elapsed = {amountTime} secs\n Attempts per sec (estimate) = {amount/amountTime}")
 print(f"DONE! PASSWORD: {password}")
 return
 length += 1
 if length > 3:
 amount = findamount(''.join(n))
 amountTime = time() - origtime
 print(f"Length = {length-1}, Amounts = {amount}, Password = {''.join(n)}\nTime elapsed = {amountTime} secs\nAttempts per sec = {amount/amountTime}\nEstimated Time: {findamount(''.join(password))/(amount/amountTime)} secs")
password = input(">>> ")
fast(password)

My current average is 6-16M per sec. However, I want to see how to increase it on my code. I tried using threading and this is the attempt:

from itertools import product
from time import time
from threading import Thread
from more_itertools import divide
def findamount(find):
 constValues = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
 dictValues = {constValues[n]:n+1 for n in range(62)}
 value = 0
 for n in range(len(str(find))):
 x = len(str(find)) - (n+1)
 value += dictValues[find[n]] * (62**x)
 return value
def fast(password, amountOfThreads, thread):
 password = tuple(password)
 origtime = time()
 length = 1
 constValues = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
 for a in range(10000000): #More efficient than while True (I think)
 for n in divide(amountOfThreads, product(constValues, repeat=length))[thread-1]:
 if n == password:
 amount = findamount(''.join(list(n)))
 amountTime = time() - origtime
 if amountTime == 0:
 print(f"Length = {length}, Amounts = {amount}\nTime elapsed = 0 secs\nAttempts per sec = ? TIME TOO SHORT")
 else:
 print(f"Length = {length}, Amounts = {amount}\nTime elapsed = {amountTime} secs\n Attempts per sec (estimate) = {amount/amountTime}")
 print(f"DONE! PASSWORD: {password}")
 raise SystemExit
 length += 1
 if length > 3:
 amount = findamount(''.join(n))
 amountTime = time() - origtime
 print(f"Length = {length-1}, Amounts = {amount}, Password = {''.join(n)}\nTime elapsed = {amountTime} secs\nAttempts per sec = {amount/amountTime}\nEstimated Time: {findamount(''.join(password))/(amount/amountTime)} secs")
password = input(">>> ")
if __name__ == "__main__":
 amountOfThreads = int(input("How much threads?"))
 for n in range(amountOfThreads):
 Thread(target=fast, args = (password, amountOfThreads, n+1)).start()

It gets much slower. If you input 1 thread it does 2-3M per sec and 2+ threads in total does about 200k per sec (totalling all threads). Is there any way to improve this code to allow threading to be useful, or any other efficient code I should add? Also, is threading the most efficient way to do this?

asked May 30, 2021 at 21:28
\$\endgroup\$
1
  • 1
    \$\begingroup\$ The constraint in the program is computation, not IO. Using threads, as you discovered, won't help (search for the Python GIL). Instead see the multiprocessing library. \$\endgroup\$ Commented Jun 1, 2021 at 6:50

1 Answer 1

1
\$\begingroup\$

I've found a few ways to improve my code:

  1. Instead of doing for a in range(10000000): and length += 1, you can just merge the two and do for length in range(1, 10000000):. This would help increase efficiency because in the previous case, a would be length-1, meaning if I use range(1, 10000000) (meaning a starts at 1 instead of 0), a would be equal to length.

  2. The second improvement is in this code:

if length > 3: 
 amount = findamount(''.join(n))
 amountTime = time() - origtime
 print(f"Length = {length}, Amounts = {amount}, Password = {''.join(n)}\nTime elapsed = {amountTime} secs\nAttempts per sec = {amount/amountTime}\nEstimated Time: {findamount(''.join(password))/(amount/amountTime)} secs")

''.join(n) is calculated twice, I could just do currentPassword = ''.join(n) so ''.join(n) would only be calculated once, and use currentPassword for the two times I used ''.join(n).

  1. This improvement is also on the code above. the print part can be improved. This isnt an efficiency improvement, but a readability improvement. Changing the print function to:
print(f"Length = {length}, Amounts = {amount}, Password = {currentAmount}\nTime elapsed = {amountTime} secs",
"\nAttempts per sec = {amount/amountTime}\nEstimated Time: {findamount(''.join(password))/(amount/amountTime)} secs")

I'll update this every time I find something new.

answered May 31, 2021 at 8:52
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.