Untitled

mail@pastecode.io avatar
unknown
python
3 years ago
3.4 kB
32
Indexable
import string
import time
import random

attempts = 0
pass_to_guess_len = 0
pass_dictionaries = []
curr_progress_percent = 0
max_attempts_num = 0


def print_progress():
    print("Current progress: {}%. Checked {:,} of {:,}".format(curr_progress_percent, attempts, max_attempts_num))


def shuffle(array):
    random.shuffle(array)
    return array


def init_pass_dictionaries(password):
    global pass_dictionaries

    special_chars = ["!", "@", "#", "$", "%", "&", "*", "-", "_", "^"]

    valid_chars = list(string.digits) + special_chars + list(string.ascii_lowercase) + list(string.ascii_uppercase)
    if not all([char in valid_chars for char in password]):
        print("Unsupported characters in password found. Only ASCII letters, digits and next special characters are supported: \n{}".format(special_chars))
        quit(1)

    for i in range(len(password)):
        curr_dict = []

        if i == 0:
            curr_dict = shuffle(list(string.ascii_uppercase)) + shuffle(list(string.ascii_lowercase) + list(string.digits) + special_chars)
        elif i == len(password) - 1:
            curr_dict = shuffle(list(string.digits) + special_chars) + shuffle(list(string.ascii_lowercase) + list(string.ascii_uppercase))
        else:
            curr_dict = shuffle(list(string.ascii_lowercase) + special_chars + list(string.digits) + list(string.ascii_uppercase))

        if not all([char in string.digits for char in password]):
            curr_dict = [x for x in curr_dict if x not in string.digits]
        if not all([char in special_chars for char in password]):
            curr_dict = [x for x in curr_dict if x not in special_chars]

        pass_dictionaries.append(curr_dict)


def calculate_max_attempt_num(pass_to_guess, alphabet_size):
    result = 0
    for i in range(0, len(pass_to_guess)):
        result = result + pow(alphabet_size, i + 1)

    return result


def find_pass_match(pass_to_guess, current_pass):
    global attempts
    global pass_to_guess_len
    global curr_progress_percent

    current_pass_len = len(current_pass)
    if current_pass_len == pass_to_guess_len:
        return False

    for char_to_try in pass_dictionaries[current_pass_len]:
        attempts += 1

        curr_progress = int(attempts / max_attempts_num * 100)
        if curr_progress != curr_progress_percent:
            curr_progress_percent = curr_progress
            print_progress()

        pass_to_try = current_pass + char_to_try

        if pass_to_try == pass_to_guess:
            return True
        else:
            pass_to_try_matches = find_pass_match(pass_to_guess, pass_to_try)
            if pass_to_try_matches:
                return True

    return False


password = input("Please enter your password: \n")
pass_to_guess_len = len(password)

init_pass_dictionaries(password)

max_attempts_num = calculate_max_attempt_num(password, len(pass_dictionaries[0]))
print("Max number of attempts: {:,}".format(max_attempts_num))

print_progress()
start_time = time.time()
match_found = find_pass_match(password, "")
end_time = time.time()

if match_found:
    time_took_sec = end_time - start_time
    attempts_per_sec = attempts / time_took_sec if time_took_sec != 0 else float('inf')
    print("Found match in {:,} attempts, took {:.2f} seconds ({:,.0f} attempts per second)".format(attempts, time_took_sec, attempts_per_sec))