Программа для защиты информации на языке питон на основе Tkinter GUI и библиотеки pyAesCrypt. Я не знаю для чего изобретать велосипед, но можно надежно шифровать свои данные (не ТераБайтные например) своими силами. Скорость шифрования устраивает но проблема скорости есть, над этим не работал пока. На директории до 5 - 10 ГБ уйдет от 3 до 7 минут в зависимости от системы (но это не точно). Но тут вопрос видимо в алгоритме шифрования и мультипроцессинге имхо. В общем, всегда есть над чем работать) На выходе должен быть работающий код (при наличии поставленных библиотек), который можно доработать или изменить например алгоритм шифрования. В общем используется документация, питон и иногда гуглнет (куда без него). Если будет кому то интересно или полезно, буду рад получить обратную связь. По информативности и написанию тоже, хотя в основном будет оптимизировано документационный код) Часть замечаний будет непосредственно в комментариях внутри кода, постарался сделать подробно (надеюсь не слишком) Короче, погнали. Подключаем библиотеки : import os import threading import pyperclip import pyAesCrypt from tkinter import * import tkinter as tk from tkinter import ttk from tkinter import scrolledtext Python import os import threading import pyperclip import pyAesCrypt from tkinter import * import tkinter as tk from tkinter import ttk from tkinter import scrolledtext Проверяем, устанавливаем через pip. Создаем главное окно : Далее создаем класс приложения и вызываем метод инит, инициализируем нужные переменные и виджеты. Виджеты расположены по осям х, у для геометрии окна 500х500 (вроде оптимально)) # инициализацию можно делать по разному, тут наследуемся от Frame.tk class MainWindow(tk.Frame): def __init__(self, root): super().__init__(root) self.init_main() # создаем нужные переменные и виджеты главного окна def init_main(self): self.img_cache = [] # храним изображения self.thread_count = 0 # счетчик потоков self.path_error = False # отловить ошибку # тут стандартные виджеты tkinter lb_dir = Label(text=u"Директория шифрования : ") lb_dir.pack() self.ent_value_dir = Entry(width=40) self.ent_value_dir.pack() lb_pass = Label(text=u"Пароль : ") lb_pass.pack() ent_value_pass = Entry(width=40) ent_value_pass.pack() #base_img = "iVBORw0KGgoAAAAN_youR_very_long_code" crypt_img = PhotoImage(file='1.png') self.img_cache.append(crypt_img) btn_crypt = ttk.Button(text=' CRYPT', image=self.img_cache[0], compound='left', command=lambda: self.crypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_crypt.place(x=5, y=20) decrypt_img = PhotoImage(file='2.png') self.img_cache.append(decrypt_img) btn_decrypt = ttk.Button(text=' DECRYPT', image=self.img_cache[1], compound='left', command=lambda: self.decrypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_decrypt.place(x=5, y=60) paste_img = PhotoImage(file='3.png') self.img_cache.append(paste_img) btn_stop = ttk.Button(text=' PASTE', image=self.img_cache[2], compound='left', command=lambda: self.paste_dir_to_entry()) btn_stop.place(x=390, y=20) stop_img = PhotoImage(file='4.png') self.img_cache.append(stop_img) btn_stop = ttk.Button(text=' STOP', image=self.img_cache[3], compound='left', command=lambda: self.close_crypter()) btn_stop.place(x=390, y=60) self.console = scrolledtext.ScrolledText(fg="red", bg="black", state='disable') self.console.pack(pady=20) Python # инициализацию можно делать по разному, тут наследуемся от Frame.tk class MainWindow(tk.Frame): def __init__(self, root): super().__init__(root) self.init_main() # создаем нужные переменные и виджеты главного окна def init_main(self): self.img_cache = [] # храним изображения self.thread_count = 0 # счетчик потоков self.path_error = False # отловить ошибку # тут стандартные виджеты tkinter lb_dir = Label(text=u"Директория шифрования : ") lb_dir.pack() self.ent_value_dir = Entry(width=40) self.ent_value_dir.pack() lb_pass = Label(text=u"Пароль : ") lb_pass.pack() ent_value_pass = Entry(width=40) ent_value_pass.pack() #base_img = "iVBORw0KGgoAAAAN_youR_very_long_code" crypt_img = PhotoImage(file='1.png') self.img_cache.append(crypt_img) btn_crypt = ttk.Button(text=' CRYPT', image=self.img_cache[0], compound='left', command=lambda: self.crypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_crypt.place(x=5, y=20) decrypt_img = PhotoImage(file='2.png') self.img_cache.append(decrypt_img) btn_decrypt = ttk.Button(text=' DECRYPT', image=self.img_cache[1], compound='left', command=lambda: self.decrypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_decrypt.place(x=5, y=60) paste_img = PhotoImage(file='3.png') self.img_cache.append(paste_img) btn_stop = ttk.Button(text=' PASTE', image=self.img_cache[2], compound='left', command=lambda: self.paste_dir_to_entry()) btn_stop.place(x=390, y=20) stop_img = PhotoImage(file='4.png') self.img_cache.append(stop_img) btn_stop = ttk.Button(text=' STOP', image=self.img_cache[3], compound='left', command=lambda: self.close_crypter()) btn_stop.place(x=390, y=60) self.console = scrolledtext.ScrolledText(fg="red", bg="black", state='disable') self.console.pack(pady=20) Для кнопок лучше вставлять изображения - закодированные в base64, или придется держать файлы изображений в рабочей директории, если заходите скомпилировать в один exe. файл - это неудобно. Основные функции :Расшифровка / дешифровка директории: def crypt_file(self, file, password): bufferSize = 512 * 1024 # размер буфера по умолчанию - больше не надо try: # шифруем с расширением .your_version& pyAesCrypt.encryptFile(str(file), str(file) + ".your_version&", password, bufferSize) # выводим в консоль tkinter self.insert_to_console('ENCRYPTED >>> ' + str(file) + ".your_version&" + '\n') os.remove(file) # удаляем файл except Exception as e: self.insert_to_console('Ошибка шифрования <Unknown_Error>') pass def crypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): # если это директория - продолжаем рекурсивно self.crypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): # если файл - шифруем try: self.crypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True # поймали ошибку return def decrypt_file(self, file, password): # расшифровка практически идентична, только меняем метод на decryptFile bufferSize = 512 * 1024 try: pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize) self.insert_to_console('DECRYPTED >>> ' + str(os.path.splitext(file)[0]) + '\n') os.remove(file) except Exception as e: print('Ошибка расшифровки, файлы не зашифрованы,' 'неверный пароль или файл поврежден') self.insert_to_console(e) pass def decrypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.decrypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.decrypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True pass Python def crypt_file(self, file, password): bufferSize = 512 * 1024 # размер буфера по умолчанию - больше не надо try: # шифруем с расширением .your_version& pyAesCrypt.encryptFile(str(file), str(file) + ".your_version&", password, bufferSize) # выводим в консоль tkinter self.insert_to_console('ENCRYPTED >>> ' + str(file) + ".your_version&" + '\n') os.remove(file) # удаляем файл except Exception as e: self.insert_to_console('Ошибка шифрования <Unknown_Error>') pass def crypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): # если это директория - продолжаем рекурсивно self.crypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): # если файл - шифруем try: self.crypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True # поймали ошибку return def decrypt_file(self, file, password): # расшифровка практически идентична, только меняем метод на decryptFile bufferSize = 512 * 1024 try: pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize) self.insert_to_console('DECRYPTED >>> ' + str(os.path.splitext(file)[0]) + '\n') os.remove(file) except Exception as e: print('Ошибка расшифровки, файлы не зашифрованы,' 'неверный пароль или файл поврежден') self.insert_to_console(e) pass def decrypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.decrypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.decrypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True pass Тут используется функция self.insert_to_console для вывода в tk виджет scrolledtext. Напишем ее : def insert_to_console(self, text): self.console.configure(state='normal') # включаем инсерт self.console.insert(END, text) # вставить текст self.console.yview(END) # автоскролл self.console.configure(state='disabled') Python def insert_to_console(self, text): self.console.configure(state='normal') # включаем инсерт self.console.insert(END, text) # вставить текст self.console.yview(END) # автоскролл self.console.configure(state='disabled') Основные криптографические функции есть, но нам необходимо использовать потоки, чтобы окно не зависало. Во время работы криптографические функции нам надо получать динамический вывод в консоль программы, но без использования многопоточности, поток главного окна проги будет перекрывать поток выполнения, окно попросту будет висеть пока программа не закончит работу. Чтобы при повторном нажатии кнопки у нас потоки не накладывались друг на друга, разрешим запускаться только одному потоку. Реализовал так: def crypting(self, dir, password): # проверяем нет ли ошибки пути или пустой пароль if self.path_error or password == '': self.path_error = False # сбрасываем ошибку self.thread_count = 0 # обнуляем счетчик процессов self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: # print(threading.enumerate()) self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.crypt_disk, args=(dir, password)) pycrypt.start() def decrypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.decrypt_disk, args=(dir, password)) pycrypt.start() Python def crypting(self, dir, password): # проверяем нет ли ошибки пути или пустой пароль if self.path_error or password == '': self.path_error = False # сбрасываем ошибку self.thread_count = 0 # обнуляем счетчик процессов self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: # print(threading.enumerate()) self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.crypt_disk, args=(dir, password)) pycrypt.start() def decrypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.decrypt_disk, args=(dir, password)) pycrypt.start() Эти функции запускаются по нажатии кнопок CRYPT / DECRYPT соответственно. Напишем функции для кнопки PASTE и STOP: def close_crypter(self): # закрыть окно quit() def paste_dir_to_entry(self): # вставить текст из буфера обмена в поле директория self.ent_value_dir.insert(tk.END, pyperclip.paste()) Python def close_crypter(self): # закрыть окно quit() def paste_dir_to_entry(self): # вставить текст из буфера обмена в поле директория self.ent_value_dir.insert(tk.END, pyperclip.paste()) И наконец инициализируем запуск: def run_app(): root = tk.Tk() root.resizable(width=False, height=False) # не изменять размер окна MainWindow(root) root.title("crypter") root.geometry("500x500") root.mainloop() if __name__ == '__main__': crypter = MainWindow crypter.run_app() Python def run_app(): root = tk.Tk() root.resizable(width=False, height=False) # не изменять размер окна MainWindow(root) root.title("crypter") root.geometry("500x500") root.mainloop() if __name__ == '__main__': crypter = MainWindow crypter.run_app() Чтобы скомпилировать в .exe поменяйте расширение на your_file.pyw и выполните: pyinstaller --onefile your_file.pyw или pyinstaller --onefile --icon=skeleton.ico zvepb_crypter.pyw для эстетики. Для компиляции необходима библиотека pyinstaller: pip install pyinstaller Исходный код: import os import threading import pyperclip import pyAesCrypt from tkinter import * import tkinter as tk from tkinter import ttk from tkinter import scrolledtext class MainWindow(tk.Frame): def __init__(self, root): super().__init__(root) self.init_main() def init_main(self): self.img_cache = [] self.thread_count = 0 self.path_error = False lb_dir = Label(text=u"Директория шифрования : ") lb_dir.pack() self.ent_value_dir = Entry(width=40) self.ent_value_dir.pack() lb_pass = Label(text=u"Пароль : ") lb_pass.pack() ent_value_pass = Entry(width=40) ent_value_pass.pack() crypt_img = PhotoImage(file='1.png') self.img_cache.append(crypt_img) btn_crypt = ttk.Button(text=' CRYPT', image=self.img_cache[0], compound='left', command=lambda: self.crypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_crypt.place(x=5, y=20) decrypt_img = PhotoImage(file='2.png') self.img_cache.append(decrypt_img) btn_decrypt = ttk.Button(text=' DECRYPT', image=self.img_cache[1], compound='left', command=lambda: self.decrypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_decrypt.place(x=5, y=60) paste_img = PhotoImage(file='3.png') self.img_cache.append(paste_img) btn_stop = ttk.Button(text=' PASTE', image=self.img_cache[2], compound='left', command=lambda: self.paste_dir_to_entry()) btn_stop.place(x=390, y=20) stop_img = PhotoImage(file='4.png') self.img_cache.append(stop_img) btn_stop = ttk.Button(text=' STOP', image=self.img_cache[3], compound='left', command=lambda: self.close_crypter()) btn_stop.place(x=390, y=60) self.console = scrolledtext.ScrolledText(fg="red", bg="black", state='disable') self.console.pack(pady=20) def close_crypter(self): quit() def insert_to_console(self, text): self.console.configure(state='normal') # enable insert self.console.insert(END, text) self.console.yview(END) # autoscroll self.console.configure(state='disabled') def paste_dir_to_entry(self): self.ent_value_dir.insert(tk.END, pyperclip.paste()) def crypt_file(self, file, password): bufferSize = 512 * 1024 try: pyAesCrypt.encryptFile(str(file), str(file) + ".zvp", password, bufferSize) self.insert_to_console('ENCRYPTED >>> ' + str(file) + ".zvp" + '\n') os.remove(file) except Exception as e: self.insert_to_console('Ошибка шифрования <Unknown_Error>') pass def crypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.crypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.crypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True return def decrypt_file(self, file, password): bufferSize = 512 * 1024 try: pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize) self.insert_to_console('DECRYPTED >>> ' + str(os.path.splitext(file)[0]) + '\n') os.remove(file) except Exception as e: print('Ошибка расшифровки, файлы не зашифрованы,' 'неверный пароль или файл поврежден') self.insert_to_console(e) pass def decrypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.decrypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.decrypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True pass # проблемы - ускорение процесса шифрования и создающиеся потоки при повторном нажатии кнопки # (исправлено с помощью path_error и thread_count def crypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: # print(threading.enumerate()) self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.crypt_disk, args=(dir, password)) pycrypt.start() def decrypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.decrypt_disk, args=(dir, password)) pycrypt.start() def run_app(): root = tk.Tk() root.resizable(width=False, height=False) MainWindow(root) root.title("zvepb_crypter") root.geometry("500x500") root.mainloop() if __name__ == '__main__': zv = MainWindow zv.run_app() Python import os import threading import pyperclip import pyAesCrypt from tkinter import * import tkinter as tk from tkinter import ttk from tkinter import scrolledtext class MainWindow(tk.Frame): def __init__(self, root): super().__init__(root) self.init_main() def init_main(self): self.img_cache = [] self.thread_count = 0 self.path_error = False lb_dir = Label(text=u"Директория шифрования : ") lb_dir.pack() self.ent_value_dir = Entry(width=40) self.ent_value_dir.pack() lb_pass = Label(text=u"Пароль : ") lb_pass.pack() ent_value_pass = Entry(width=40) ent_value_pass.pack() crypt_img = PhotoImage(file='1.png') self.img_cache.append(crypt_img) btn_crypt = ttk.Button(text=' CRYPT', image=self.img_cache[0], compound='left', command=lambda: self.crypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_crypt.place(x=5, y=20) decrypt_img = PhotoImage(file='2.png') self.img_cache.append(decrypt_img) btn_decrypt = ttk.Button(text=' DECRYPT', image=self.img_cache[1], compound='left', command=lambda: self.decrypting(self.ent_value_dir.get(), ent_value_pass.get())) btn_decrypt.place(x=5, y=60) paste_img = PhotoImage(file='3.png') self.img_cache.append(paste_img) btn_stop = ttk.Button(text=' PASTE', image=self.img_cache[2], compound='left', command=lambda: self.paste_dir_to_entry()) btn_stop.place(x=390, y=20) stop_img = PhotoImage(file='4.png') self.img_cache.append(stop_img) btn_stop = ttk.Button(text=' STOP', image=self.img_cache[3], compound='left', command=lambda: self.close_crypter()) btn_stop.place(x=390, y=60) self.console = scrolledtext.ScrolledText(fg="red", bg="black", state='disable') self.console.pack(pady=20) def close_crypter(self): quit() def insert_to_console(self, text): self.console.configure(state='normal') # enable insert self.console.insert(END, text) self.console.yview(END) # autoscroll self.console.configure(state='disabled') def paste_dir_to_entry(self): self.ent_value_dir.insert(tk.END, pyperclip.paste()) def crypt_file(self, file, password): bufferSize = 512 * 1024 try: pyAesCrypt.encryptFile(str(file), str(file) + ".zvp", password, bufferSize) self.insert_to_console('ENCRYPTED >>> ' + str(file) + ".zvp" + '\n') os.remove(file) except Exception as e: self.insert_to_console('Ошибка шифрования <Unknown_Error>') pass def crypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.crypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.crypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True return def decrypt_file(self, file, password): bufferSize = 512 * 1024 try: pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize) self.insert_to_console('DECRYPTED >>> ' + str(os.path.splitext(file)[0]) + '\n') os.remove(file) except Exception as e: print('Ошибка расшифровки, файлы не зашифрованы,' 'неверный пароль или файл поврежден') self.insert_to_console(e) pass def decrypt_disk(self, dir, password): try: for file in os.listdir(dir): if os.path.isdir(dir + '\\' + file): self.decrypt_disk(dir + '\\' + file, password) if os.path.isfile(dir + '\\' + file): try: self.decrypt_file(dir + '\\' + file, password) except Exception as ex: self.insert_to_console(ex) pass except OSError: self.path_error = True pass # проблемы - ускорение процесса шифрования и создающиеся потоки при повторном нажатии кнопки # (исправлено с помощью path_error и thread_count def crypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: # print(threading.enumerate()) self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.crypt_disk, args=(dir, password)) pycrypt.start() def decrypting(self, dir, password): if self.path_error or password == '': self.path_error = False self.thread_count = 0 self.insert_to_console('Ошибка : Неправильный путь или нет пароля !\n') return else: self.thread_count += 1 if self.thread_count > 1: self.insert_to_console('Ограничение потока, запущено : 1\n') return pycrypt = threading.Thread(target=self.decrypt_disk, args=(dir, password)) pycrypt.start() def run_app(): root = tk.Tk() root.resizable(width=False, height=False) MainWindow(root) root.title("zvepb_crypter") root.geometry("500x500") root.mainloop() if __name__ == '__main__': zv = MainWindow zv.run_app() Источник:codeby_sec/6606