# Imports import pyfiglet, os, base64 from cryptography.fernet import Fernet # Terminal Text Class class TerminalText(): # Options COLOR_MAIN = "\033[94m" COLOR_PROCESSING = "\033[93m" COLOR_SUCCESS = "\033[92m" COLOR_ERROR = "\033[91m" COLOR_END = "\033[0m" # Print Title def printTitle(): # Start Color print(TerminalText.COLOR_MAIN) # Text pyfiglet.print_figlet("The Locker") print(" by Tylan Tyson", end = "") # End Color print(TerminalText.COLOR_END) # Print Menu def printMenu(): # Color print(TerminalText.COLOR_MAIN) # Text print("--------------------------------------------------") print("| Option 1: Encrypt |") print("| Option 2: Decrypt |") print("| Option 3: Exit |") print("--------------------------------------------------") # Input option = input(" Option: ") # End Color print(TerminalText.COLOR_END) # Return return option # Generate Key def generateKey(): # Get Valid Password password = "" password_valid = False while not password_valid: password = input("| Choose Password: ") if len(password) >= 1 and len(password) <= 32: password_valid = True else: print(TerminalText.COLOR_ERROR, "ERROR - Password must be between 1 and 32 characters long.", TerminalText.COLOR_PROCESSING) print(TerminalText.COLOR_SUCCESS, "SUCCESS - Password accepted.", TerminalText.COLOR_PROCESSING) # Adjust Length counter = 0 while len(password) != 32: character = password[counter] password += character counter += 1 # Create Key password = bytes(password.encode()) key = base64.b64encode(password) return key # Check Path def checkPath(): # Get Valid Input path = None path_valid = False while not path_valid: path = input("| Choose Path: ") if os.path.exists(path): if os.path.isdir(path): path_valid = True else: print(TerminalText.COLOR_ERROR, "ERROR - Path is not a directory.", TerminalText.COLOR_PROCESSING) else: print(TerminalText.COLOR_ERROR, "ERROR - Path does not exist.", TerminalText.COLOR_PROCESSING) print(TerminalText.COLOR_SUCCESS, "SUCCESS - Path accepted.", TerminalText.COLOR_PROCESSING) # Return Path return path # Encrypt def encrypt(key, directory_path): # Fernet Object fernet = Fernet(key) # Loop Through Files counter = 0 for root, directories, files in os.walk(directory_path): for file in files: # Avoid Errors try: # File Information file_path = os.path.join(root, file) with open(file_path, "rb") as file: file_data = file.read() # File Path To Encrypt file_path_to_encrypt = file_path.split(os.sep) # Remove Empty Space for directory in file_path_to_encrypt: if directory == "": file_path_to_encrypt.remove(directory) # Find Root Index root_index = None for directory_index, directory in enumerate(file_path_to_encrypt): if directory == directory_path.split(os.sep)[-1]: root_index = directory_index if root_index != None: break # Remove Items Upto Root Index if root_index > 0: for i in range(root_index + 1): file_path_to_encrypt.pop(0) # Encrypt with open(os.path.join(directory_path, f"THELOCKERFILE_{counter}.txt"), "w") as file: file.write(f"{str(fernet.encrypt(str(file_path_to_encrypt).encode()))}\n{str(fernet.encrypt(file_data))}") # Remove Encrypted File os.remove(file_path) # Display print("Encrypting: ", file_path, TerminalText.COLOR_SUCCESS, "- SUCCESS", TerminalText.COLOR_PROCESSING) except: print("Encrypting: ", file_path, TerminalText.COLOR_ERROR, "- ERROR", TerminalText.COLOR_PROCESSING) # Counter counter += 1 # Remove Folders while [i.path for i in os.scandir(directory_path) if i.is_dir()] != []: for root, directories, files in os.walk(directory_path): for directory in directories: try: os.rmdir(os.path.join(root, directory)) except: pass # Title printTitle() # Decrypt def decrypt(key, directory_path): # Fernet Object fernet = Fernet(key) # Loop Through Files for root, directories, files in os.walk(directory_path): for file in files: # Avoid Errors try: # Filter Locker Files if "THELOCKERFILE" in file: # Read File with open (os.path.join(directory_path, file)) as file1: file_contents = file1.read() file_contents = file_contents.split("\n") # File Path file_path = file_contents[0] file_path = file_path[2:] file_path = file_path[:len(file_path) - 1] file_path = str(fernet.decrypt(bytes(file_path.encode()))) decrypted_path = file_path file_path = file_path[2:] file_path = file_path[:len(file_path) - 1] file_path = eval(file_path) # Get Required Folders required_folders = [] get_folders = file_path get_folders.pop(-1) for file3 in get_folders: required_folders.append(file3) # Create Required Folders current_folder = None for folder in required_folders: if current_folder != None: current_folder = os.path.join(current_folder, folder) else: current_folder = os.path.join(directory_path, folder) try: os.mkdir(current_folder) except: pass # Decrypt File Data file_data = file_contents[1] file_data = file_data[2:] file_data = file_data[:len(file_data) - 1] file_data = fernet.decrypt(bytes(file_data.encode())) # File Path To Write To decrypted_path = decrypted_path[2:] decrypted_path = decrypted_path[:len(decrypted_path) - 1] decrypted_path = eval(decrypted_path) write_path = None for i in decrypted_path: if write_path == None: write_path = i else: write_path = os.path.join(write_path, i) # Write File with open(os.path.join(directory_path, write_path), "wb") as writetofile: writetofile.write(file_data) # Remove LOCKERFILE os.remove(os.path.join(directory_path, file)) # Display print("DECRYPTING: ", write_path, TerminalText.COLOR_SUCCESS, "- SUCCESS", TerminalText.COLOR_PROCESSING) except: print("DECRYPTING: ", write_path, TerminalText.COLOR_ERROR, "- ERROR", TerminalText.COLOR_PROCESSING) # Title printTitle() # Print Title printTitle() print() # Program Loop while True: # Print Menu option = printMenu() # Options if option == "1": print(TerminalText.COLOR_PROCESSING) key = generateKey() print() path = checkPath() print() encrypt(key, path) print(TerminalText.COLOR_END) elif option == "2": print(TerminalText.COLOR_PROCESSING) key = generateKey() print() path = checkPath() print() decrypt(key, path) print(TerminalText.COLOR_END) elif option == "3": exit() # Invallid Option else: print(TerminalText.COLOR_ERROR) print(" Invallid Option") print(TerminalText.COLOR_END)