#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

import datetime
from hashlib import sha1
from time import sleep, time
from shutil import get_terminal_size
from threading import Thread

stop = False
global_progress = []

def stopping():
	global stop
	stop = True

def stopped():
	return stop

def progress(start_point, current_point, end_point):
	global global_progress
	for thread in global_progress:
		if thread[0] == start_point and thread[2] == end_point:
			thread[1] = current_point
	else:
		global_progress.append([start_point, current_point, end_point])

def guess(start_point, end_point, user_hash):
	constant = b"\x77\x21\x4d\x4b\x19\x6a\x87\xcd\x52\x00\x45\xfd\x20\xa5\x1d\x67"
	try:
		for i in range(start_point, end_point):
			for j in range(256):
				progress(start_point * 256, i * 256 + j, end_point * 256)
				for k in range(256):
					for l in range(256):
						tmp = sha1(constant + bytes([i,j,k,l])).digest()
						if sha1(tmp[:16] + sha1(constant + tmp + bytes([i,j,k,l])).digest()[:16]).digest() == user_hash:
							print("\r" + " " * (int(get_terminal_size().columns) - 1), end="")
							print("\r Result: " + str(bytes([i,j,k,l]).hex()))
							stopping()
							break
				if stopped():
					return
		progress(start_point, end_point, end_point)
	except KeyboardInterrupt:
		stopping()

def timeprinter(start_time):
	while not stopped():
		amount_finished = 0.0
		for thread in global_progress:
			amount_finished += (thread[1] - thread[0]) / (thread[2] - thread[0])
		amount_finished /= len(global_progress)
		print("\r" + " " * (int(get_terminal_size().columns) - 1), end="")
		if amount_finished > 0:
			print("\r " + str(int(amount_finished * 1000) / 10) + "% - less than " + str(datetime.timedelta(seconds=(time() - start_time) * (1 - amount_finished) / amount_finished)) + " left.", end="", flush=True)
		else:
			print("\r " + str(int(amount_finished * 1000) / 10) + "% - calculating remaining time...", end="", flush=True)
		sleep(1)

def main():
	start_time = time()
	user_hash = input("Enter hash: ")
	amount_threads = int(input("Enter amount of threads: "))
	threads = []
	for thread in range(amount_threads):
		threads.append(Thread(target = guess, args = (int(thread / amount_threads * 256), int((thread + 1) / amount_threads * 256), bytes.fromhex(user_hash))))
	threads.append(Thread(target = timeprinter, args = (start_time, )))
	for thread in threads:
		thread.start()
	for thread in threads:
		try:
			thread.join()
		except KeyboardInterrupt:
			stopping()
	for thread in threads:
		thread.join()

if __name__ == '__main__':
	main()