Загрузка...

Шифрование на Python

Тема в разделе Безопасность создана пользователем maks28ru 25 сен 2022. (поднята 25 сен 2022) 692 просмотра

Загрузка...
  1. maks28ru
    maks28ru Автор темы 25 сен 2022 Кура это миха 27 11 янв 2022
    Программа для защиты информации на языке питон на основе Tkinter GUI и библиотеки pyAesCrypt. Я не знаю для чего изобретать велосипед, но можно надежно шифровать свои данные (не ТераБайтные например) своими силами. Скорость шифрования устраивает но проблема скорости есть, над этим не работал пока. На директории до 5 - 10 ГБ уйдет от 3 до 7 минут в зависимости от системы (но это не точно). Но тут вопрос видимо в алгоритме шифрования и мультипроцессинге имхо. В общем, всегда есть над чем работать)

    На выходе должен быть работающий код (при наличии поставленных библиотек), который можно доработать или изменить например алгоритм шифрования. В общем используется документация, питон и иногда гуглнет (куда без него). Если будет кому то интересно или полезно, буду рад получить обратную связь. По информативности и написанию тоже, хотя в основном будет оптимизировано документационный код)

    Часть замечаний будет непосредственно в комментариях внутри кода, постарался сделать подробно (надеюсь не слишком)

    Короче, погнали.


    Подключаем библиотеки :
    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 (вроде оптимально))
    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. файл - это неудобно.


    Основные функции :
    Расшифровка / дешифровка директории:

    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. Напишем ее :

    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')



    Основные криптографические функции есть, но нам необходимо использовать потоки, чтобы окно не зависало. Во время работы криптографические функции нам надо получать динамический вывод в консоль программы, но без использования многопоточности, поток главного окна проги будет перекрывать поток выполнения, окно попросту будет висеть пока программа не закончит работу. Чтобы при повторном нажатии кнопки у нас потоки не накладывались друг на друга, разрешим запускаться только одному потоку.

    Реализовал так:
    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:
    Python
      def close_crypter(self): # закрыть окно

    quit()

    def paste_dir_to_entry(self): # вставить текст из буфера обмена в поле директория
    self.ent_value_dir.insert(tk.END, pyperclip.paste())

    И наконец инициализируем запуск:
    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


    Исходный код:
    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
     
    25 сен 2022 Изменено
  2. RSPARKER
    RSPARKER 25 сен 2022 2238 19 фев 2018
    python и шифрование, мне кажется это мимо вообще
     
Top