3
\$\begingroup\$

I wrote a SHA256 password cracker. I initially used lists to store the information in list1.txt and list2.txt but I would end up getting memory overloads. So I now use files. I noticed that when I made this transition, the programme speed reduced hugely. Is there a way to optimise the speed of this programming without running into memory overload issues?

Thanks

import hashlib
import time
import os
def extract_password(fname):
 if fname == 0:
 filename = "list2.txt"
 else:
 filename = "list1.txt"
 for line in open(filename, "r"):
 yield line.strip()
def save_password(fname, password):
 if fname == 0:
 filename = "list1.txt"
 else:
 filename = "list2.txt"
 file = open(filename, "a")
 file.write(password)
 file.write("\n")
 file.close()
def next_password(lsta, item,next_char, secure_password):
 found = 0
 guess = item + chr(next_char)
 if hash_password(guess) == secure_password:
 print(guess)
 found = 1
 save_password(lsta, guess)
 return found
def hash_password(pwrd):
 #Generates hash of original password
 pwrd = pwrd.encode("UTF-8")
 password = hashlib.sha256()
 password.update(pwrd)
 return password.hexdigest()
def delete_file(ltsa):
 try:
 if ltsa == 1:
 os.remove("list2.txt")
 else:
 os.remove("list1.txt")
 except:
 pass
def reset_file_status():
 try:
 os.remove("list2.txt")
 os.remove("list1.txt")
 except:
 pass
def find_password(secure_password):
 #Brute force to find original password
 found = 0
 lsta = 1
 for length in range(1, 15):
 if found == 1: break
 lsta = lsta^1
 delete_file(lsta)
 for next_char in range(65, 123):
 if found == 1: break
 if length == 1:
 found = next_password(lsta, "", next_char, secure_password)
 if found == 1: break
 else:
 for item in extract_password(lsta):
 found = next_password(lsta, item, next_char, secure_password)
 if found == 1: break
if __name__ == "__main__":
 reset_file_status()
 start = time.time()
 secure_password = hash_password("AAAA")
 find_password(secure_password)
 print(f"{(time.time() - start)} seconds")
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Nov 15, 2020 at 21:11
\$\endgroup\$
2
  • \$\begingroup\$ This appears to be Python 3, is that correct? \$\endgroup\$ Commented Nov 16, 2020 at 2:49
  • \$\begingroup\$ Yes. This is python 3 \$\endgroup\$ Commented Nov 16, 2020 at 9:44

1 Answer 1

3
\$\begingroup\$

The optimization you are looking for is very simple:
Ask your self - what do I really need to keep?

The answer: only the password guess I am currently checking.

There is no need to store all the old guesses, so there is no need for files or huge lists.

All you really need is one string you will keep updating.

To visualize this, think of your string as a growing number, with each letter being a base 58 digit.

Now. all you really need is to do a +1 on the first digit, checking for carry and updating following digits if needed just like usual addition.

Unfortunately, Python strings don't allow assignment by index, but they do support slicing.

Here is a function that would generate sequential passwords running through all the letters and growing the length as needed (one password per call!):

def make_next_guess(guess):
 carry = 1
 next_guess = guess
 for i in range(len(guess)):
 cur_char = ord(guess[i]) + carry
 if cur_char > ord('z'):
 cur_char = ord('A')
 carry = 1
 else:
 carry = 0
 next_guess = next_guess[:i] + chr(cur_char) + guess[i + 1:]
 if carry == 0:
 break
 if carry = 1:
 next_guess += 'A'
 return next_guess

With this you can use one loop for all the possibilities up to the maximum length:

guess = 'A'
for _ in range(58 ** 14): #password maximum length 14 and there are 58 characters that can be used
 
 if hash_password(guess) == secure_password:
 print(guess)
 break
 guess = make_next_guess(guess)
answered Nov 15, 2020 at 23:40
\$\endgroup\$
2
  • \$\begingroup\$ Amazing. Thank you. Really appreciate it \$\endgroup\$ Commented Nov 16, 2020 at 10:05
  • \$\begingroup\$ You are welcome! If forgot to add that his exercise is also good for learning multiprocessing and working with threads. You can speed this up even more if you divide the work between multiple threads or processes that run concurrently. machinelearningplus.com/python/parallel-processing-python tutorialspoint.com/python/python_multithreading.htm Say your processor can run 8 threads - just split the range of passwords to 8 sections and check them all simultaneously. \$\endgroup\$ Commented Nov 16, 2020 at 10:10

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.