Автор статьи никого не призывает к правонарушениям и отказывается нести ответственность за ваши действия. Вся информация предоставлена исключительно в ознакомительных целях. Все действия происходят на виртуальных машинах и внутри локальной сети автора. Спасибо!
Сегодня мы не будем разбираться в алгоритмах шифрования, а выясним, как шифровать на практике. Начнем с симметричного шифрования, в котором для шифрования и дешифрования используется один и тот же ключ. После чего рассмотрим ассиметричное шифрование при помощи утилиты GPG. Далее очень поверхностно научимся использовать openSSL для генерации пары открытый/закрытый ключ, которые применим для шифрования/расшифрования текстового файла при помощи Python.
Симметричное шифрование при помощи GPG
Создайте любой текстовый файл и заполните любыми данными.
cat > answer
Теперь вы можете его зашифровать при помощи команды gpg. Для шифрования выполните следующую команду:
gpg -c answer
Будет создан файл с тем же именем и расширением .gpg
. Можете более подробно узнать о файле при помощи команды file answer.gpg
:
answer.gpg: GPG symmetrically encrypted data (AES256 cipher)
Чтобы расшифровать наш файл, используйте ключ -d
:
gpg -d answer.gpg
После чего у вас будет запрошен «фраза-пароль» и вы увидите содержимое файла. Для большего понимания запустите еще раз команду дешифрования. Файл расшифровался и gpg даже не запросила пароль?
По большому счету, gpg использует ключ по умолчанию на вашем компьютере в качестве ключа шифрования/дешифрования, а кодовая фраза предназначена для обеспечения работы дешифрования с другими машинами. По сути, он тайно создает и сохраняет реальный ключ шифрования, а затем шифрует его с помощью ключевой фразы и объединяет зашифрованный ключ и зашифрованный открытый текст в выходные данные. Когда сессия закончится, необходимо будет снова ввести фразу-пароль, чтобы получить доступ к хранилищу ключей. Про добавление и удаление ключей GPG написано немного на этой странице и очень подробно написано здесь.
Ассиметричное шифрование при помощи GPG
Чтобы создать ключ наберите следующую команду:
gpg --full-gen-key
Необходимо будет выбрать тип ключа, его размер, срок действия ключа (0
– бессрочно), реальное имя, email и комментарий, при необходимости. В конце подтвердить введенные данные и придумать фразу-пароль. В консоль будет выведен публичный ключ.
Доступные ключи можно увидеть с помощью команды gpg --list-keys
. Сами ключи хранятся в следующей директории:
/root/.gnupg
Приступим к шифрованию, необходимо будет указать идентификатор (имя, которое вы указывали при создании ключа) и сам файл, который шифруем:
gpg -e -r идентификатор_пользователя название_файла
Расшифровываем также, как в предыдущем случае.
gpg -d answer.gpg
Экспортировать открытый ключ можно следующей командой:
gpg --export -a "идентификатор_пользователя" > public.key
А закрытый, такой:
gpg --export-secret-keys -a "идентификатор_пользователя" > private.key
Теперь переходим к программированию. Разберемся как работают программы-вымогатели.
Криптографическая библиотека openSSL
К библиотеке openSSL мы еще вернемся, а пока давайте кратко разберемся, как создать новую пару ключей. Чтобы сгенерировать новый RSA-ключ длиной 4096
, введите следующую команду:
openssl genrsa -out my_key.key 4096
Чтобы вывести эти ключи, используйте следующую команду:
openssl rsa -text -in my_key.key
Теперь давайте извлечем только открытый ключ, который нам в дальнейшем пригодится.
openssl rsa -in my_key.key -pubout -out public_key.key
Перейдем к написанию программы для шифрования файлов на Python.
Программа для шифрования файлов на Python
Для написания программы будем использовать модуль cryptography. Реализуем программу с таким синтаксисом:
python3 script.py –e путь_до_открытого_ключа путь_до_файла
python3 script.py -d путь_до_закрытого_ключа путь_до_файла
В первом случае мы будем шифровать текстовый файл и сохранять результат в этом же файле. Во втором случае расшифруем его. Для начала импортируем все необходимое.
import sys
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
Напишем тело программы и перейдем к самому интересному, функциям encrypt()
и decrypt()
:
if __name__ == '__main__':
mode = sys.argv[1]
path_key = sys.argv[2]
path_file = sys.argv[3]
if mode == '-e':
encrypt(path_key, path_file)
elif mode == '-d':
decrypt(path_key, path_file)
Найдем в документации cryptography функцию для работы с открытым ключом. Воспользуемся функцией load_pem_public_key(), которая сама определяет тип ключа по заголовку -----BEGIN {FORMAT} -----
в один из поддерживаемых типов асимметричных открытых ключей.
def encrypt(path_public_key, path_file):
with open(path_public_key, 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read()
)
with open(path_file, 'rb') as file:
file_data = file.read()
Мы открываем открытый ключ при помощи функции load_pem_public_key()
и сохраняем в переменную public_key
. Далее открываем файл, который будем шифровать этим ключом. Если вас интересует, почему мы не указывали аргумент backend
, то вам сюда. Для начала разберемся, что сохранилось в переменную public_key
:
<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x7fb792c42ee0>
Найдем в документации класс RSAPublicKey и посмотрим его методы. Метод encrypt
– то что нужно. Первым параметром указывается текст, который нужно зашифровать, вторым – padding
.
Для шифрования будем использовать схему OAEP, которая зарекомендовала себя достаточно надежной. Найдем ее в документации.
…
encrypted_data = public_key.encrypt(
file_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Осталось только записать зашифрованный текст в тот же файл:
…
with open(path_file, 'wb') as file:
file.write(encrypted_data)
Функция для расшифровки аналогична, только используется закрытый ключ. Полный код:
import sys
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
def encrypt(path_public_key, path_file):
with open(path_public_key, 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read()
)
with open(path_file, 'rb') as file:
file_data = file.read()
encrypted_data = public_key.encrypt(
file_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
with open(path_file, 'wb') as file:
file.write(encrypted_data)
def decrypt(path_private_key, path_file):
with open(path_private_key, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None
)
with open(path_file, 'rb') as file:
file_data = file.read()
encrypted_data = private_key.decrypt(
file_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
with open(path_file, 'wb') as file:
file.write(encrypted_data)
if __name__ == '__main__':
mode = sys.argv[1]
path_key = sys.argv[2]
path_file = sys.argv[3]
if mode == '-e':
encrypt(path_key, path_file)
elif mode == '-d':
decrypt(path_key, path_file)
В этой статье мы научились использовать утилиту GPG для симметричного и асимметричного шифрования. Очень кратко рассмотрели openSSL и самостоятельно реализовали программу на Python с модулем cryptography
для шифрования/расшифрования текстового файла с использованием открытого/закрытого ключа.