Проверка кода и шифрование данных с помощью Python-GnuPG и Python 3

Пакет GnuPG предлагает комплексное средство для генерации и хранения криптографических ключей. Он также позволяет шифровать и подписывать данные и сообщения.

В этом мануале мы напишем серию сценариев, которые используют Python 3 с модулем python-gnupg. Эти сценарии позволяют подписывать и шифровать файлы, а также проверять целостность сценариев перед их запуском.

Требования

1: Извлечение информации о ключе

Согласно предварительным требованиям, сейчас у вас есть пара ключей, сохраненная в .gnupg в вашем домашнем каталоге. GnuPG хранит ключи с именем пользователя и электронной почтой, чтобы их было проще идентифицировать. В этом примере имя пользователя — 8host, а адрес электронной почты – 8host@example.com.

Запустите команду, чтобы получить список доступных ключей:

gpg --list-keys
/home/8host/.gnupg/pubring.gpg
-----------------------------
pub   2048R/4920B23F 2018-04-23
uid                  8host <8host@example.com>
sub   2048R/50C06279 2018-04-23

Запишите адрес электронной почты, отображаемый в строке uid в выводе команды. Он понадобится вам позже, чтобы идентифицировать ваши ключи.

2: Установка Python-GnuPG и подпись файлов

Установив ключи, вы можете установить модуль python-gnupg, который действует как оболочка для GnuPG и обеспечивает взаимодействие между GnuPG и Python 3. Используя этот модуль, вы сможете создавать сценарии Python, которые выполняют следующие действия:

  • Создавать отдельные подписи для файлов (это повысит безопасность процесса подписи, отделив подписи от файлов).
  • Шифровать файлы.
  • Расшифровывать файлы.
  • Проверять отдельные подписи и скрипты.

Сначала мы создадим сценарии и тестовые файлы, а затем перейдем к тестированию сценариев для этих файлов.

Для начала давайте установим модуль python-gnupg вместе с пакетом fs, который позволит вам открывать, читать и изменять тестовые файлы. Обновите индекс пакетов и установите новые пакеты с помощью pip:

sudo apt-get update
sudo pip3 install python-gnupg fs

Установив эти пакеты, вы можете создать необходимые скрипты и файлы.

Для хранения скриптов и тестовых файлов создайте в домашнем каталоге новый каталог python-test:

cd ~/
mkdir python-test

Перейдите в него:

cd python-test/

Создайте три тестовых файла:

echo "This is the first test file" > test1.txt
echo "print('This test file is a Python script')" > test2.py
echo "This is the last test file" > test3.txt

Чтобы создать отдельные подписи для этих тестовых файлов, создайте скрипт signdetach.py, который охватывает все файлы в каталоге, где он выполняется. Подпись действует как метка времени и удостоверяет подлинность документа.

Отдельные подписи будут храниться в новой папке signatures/, которая будет создана при запуске скрипта.

Откройте новый файл signdetach.py, используя nano или другой текстовый редактор:

nano signdetach.py

Сначала импортируйте все необходимые модули для скрипта. К ним относятся пакеты os и fs, которые включают навигацию по файлам, и gnupg:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg

Теперь определите каталог, где GnuPG сможет найти ключи шифрования. GnuPG по умолчанию хранит свои ключи в .gnupg, поэтому укажите здесь имя вашего пользователя (обязательно замените 8host именем вашего пользователя):

...
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")

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

...
home_fs = open_fs(".")

На данный момент скрипт выглядит так:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")

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

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

...
if os.path.exists("signatures/"):
print("Signatures directory already created")
else:
home_fs.makedir(u"signatures")
print("Created signatures directory")

Создайте пустой массив для хранения имен файлов, а затем просканируйте текущий каталог, добавляя все имена файлов в массив files_dir:

...
files_dir = []
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)

Следующее, что сделает скрипт, это создаст отдельные подписи для файлов. Прохождение массива files_dir создаст подпись для каждого файла, используя первый закрытый ключ в вашем наборе ключей. Чтобы получить доступ к закрытому ключу, нужно разблокировать его с помощью установленной вами парольной фразы. Замените «my passphrase» той фразой, которую вы использовали, когда генерировали пару ключей (по мануалу Шифрование и подпись сообщений с помощью GPG):

...
for x in files_dir:
with open(x, "rb") as f:
stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig")
os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig")
print(x+" ", stream.status)

После выполнения скрипта все подписи будут помещены в папку signatures/. В результате скрипт будет выглядеть так:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
if os.path.exists("signatures/"):
print("Signatures directory already created")
else:
home_fs.makedir(u"signatures")
print("Created signatures directory")
files_dir = []
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)
for x in files_dir:
with open(x, "rb") as f:
stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig")
os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig")
print(x+" ", stream.status)

Теперь можно приступать к шифрования файлов.

3: Шифрование файлов

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

Откройте новый файл encryptfiles.py:

nano encryptfiles.py

Сначала импортируйте все необходимые модули, установите домашний каталог GnuPG и создайте переменную для текущего рабочего каталога:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")

Затем добавьте код, который проверит, есть ли в текущем каталоге папка encrypted/ и создаст ее, если ее нет:

...
if os.path.exists("encrypted/"):
print("Encrypt directory exists")
else:
home_fs.makedir(u"encrypted")
print("Created encrypted directory")

Прежде чем начать поиск файлов, которые нужно зашифровать, создайте пустой массив для хранения имен файлов:

...
files_dir = []

Затем создайте цикл для сканирования файлов в папке и добавления их в массив:

...
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)

Теперь осталось создать цикл для шифрования всех файлов в папке. После завершения скрипта все зашифрованные файлы будут перемещены в папку encrypted/. В этом примере 8host@example.com — это ID электронной почты для ключа, который будет использоваться во время шифрования. Обязательно замените его своим адресом электронной почты, который вы указали в разделе 1:

...
for x in files_dir:
with open(x, "rb") as f:
status = gpg.encrypt_file(f,recipients=["8host@example.com"],output= files_dir[files_dir.index(x)]+".gpg")
print("ok: ", status.ok)
print("status: ", status.status)
print("stderr: ", status.stderr)
os.rename(files_dir[files_dir.index(x)] + ".gpg", 'encrypted/' +files_dir[files_dir.index(x)] + ".gpg")

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

Ваш файл сценария encryptfiles.py должен выглядеть следующим образом:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
if os.path.exists("encrypted/"):
print("Encrypt directory exists")
else:
home_fs.makedir(u"encrypted")
print("Created encrypted directory")
files_dir = []
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)
for x in files_dir:
with open(x, "rb") as f:
status = gpg.encrypt_file(f,recipients=["8host@example.com"],output= files_dir[files_dir.index(x)]+".gpg")
print("ok: ", status.ok)
print("status: ", status.status)
print("stderr: ", status.stderr)
os.rename(files_dir[files_dir.index(x)] + ".gpg", "encrypted/" +files_dir[files_dir.index(x)] + ".gpg")

Теперь нужно написать скрипт для расшифровки и проверки нескольких файлов.

4: Расшифровка файлов

Сценарий дешифровки работает почти так же, как сценарий шифрования, за исключением того, что он должен запускаться в каталоге encrypted/. При запуске decryptfiles.py сначала идентифицирует используемый открытый ключ, а затем ищет соответствующий закрытый ключ в папке .gnupg для расшифровки файла. Расшифрованные файлы будут сохранены в новой папке decrypted/.

Откройте новый файл decryptfiles.py в nano или в другом редакторе:

nano decryptfiles.py

Сначала введите базовую конфигурацию:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")

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

...
files_dir = []
files_dir_clean = []

Сценарий должен поместить расшифрованные файлы в отдельную папку; в противном случае зашифрованные и расшифрованные файлы смешаются, что затруднит поиск определенного расшифрованного файла. Чтобы решить эту проблему, добавьте такой код, который просканирует текущую папку и проверит, существует ли папка decrypted/, а если нет, создаст ее:

...
if os.path.exists("decrypted/"):
print("Decrypted directory already exists")
else:
home_fs.makedir(u"decrypted/")
print("Created decrypted directory")

Следующий фрагмент сканирует все имена файлов в папке и добавляет их в массив files_dir:

...
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)

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

Для этого выполните цикл по массиву files_dir и удалите расширение .gpg из имени каждого файла:

...
for x in files_dir:
length = len(x)
endLoc = length - 4
clean_file = x[0:endLoc]
files_dir_clean.append(clean_file)

После «чистки» мена файлов без этого расширения будут храниться в массиве file_dir_clean.

Теперь пройдите по файлам и расшифруйте их. Замените my passphrase вашей парольной фразой, чтобы получить доступ к закрытому ключу.

...
for x in files_dir:
with open(x, "rb") as f:
status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)])
print("ok: ", status.ok)
print("status: ", status.status)
print("stderr: ", status.stderr)
os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])

В итоге скрипт должен выглядеть так:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
files_dir = []
files_dir_clean = []
if os.path.exists("decrypted/"):
print("Decrypted directory already exists")
else:
home_fs.makedir(u"decrypted/")
print("Created decrypted directory")
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)
for x in files_dir:
length = len(x)
endLoc = length - 4
clean_file = x[0:endLoc]
files_dir_clean.append(clean_file)
for x in files_dir:
with open(x, "rb") as f:
status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)])
print("ok: ", status.ok)
print("status: ", status.status)
print("stderr: ", status.stderr)
os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])

Теперь можно проверить извлеченные подписи файлов.

5: Проверка подписей

Чтобы проверить полученные цифровые подписи нескольких файлов, давайте напишем сценарий verifydetach.py. Этот скрипт будет искать папку signatures/ в рабочем каталоге и проверять каждый файл.

Откройте новый файл verifydetach.py:

nano verifydetach.py

Импортируйте все необходимые библиотеки, настройте рабочий и домашний каталог, а затем создайте пустой массив files_dir, как и в предыдущих примерах.

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
files_dir = []

Далее нужно просканировать папку, содержащую файлы, которые мы хотим проверить. Имена файлов будут добавлены в пустой массив files_dir:

...
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)

Теперь давайте проверим каждый файл с помощью отделенных подписей, используя цикл, который перемещается по массиву files_dir и ищет отделенные подписи каждого файла в папке signatures/. Когда цикл находит отдельную подпись, он заверяет файл с ее помощью. Последняя строка выводит статус проверки каждого файла:

...
for i in files_dir:
with open("../../signatures/" + i + ".sig", "rb") as f:
verify = gpg.verify_file(f, i)
print(i + " ", verify.status)

Получится такой сценарий:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
files_dir = []
files = [f for f in os.listdir(".") if os.path.isfile(f)]
for f in files:
files_dir.append(f)
for i in files_dir:
with open("../../signatures/" + i + ".sig", "rb") as f:
verify = gpg.verify_file(f, i)
print(i + " ", verify.status)

Далее давайте рассмотрим, как проверить подпись файла перед его выполнением на сервере.

6: Проверка файлов

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

Создайте файл verifyfile.py:

nano verifyfile.py

Сначала импортируйте библиотеки и определите рабочие каталоги:

#!/usr/bin/env python3
import os
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")

Чтобы скрипт работал, необходимо сохранить имя файла, который нужно проверить и запустить. Для этого создайте новую переменную script_to_run:

...
script_to_run = str(sys.argv[1])

Эта переменная принимает первый аргумент и сохраняет его во вновь созданной переменной. Затем скрипт откроет файл отделенной подписи, сверит файл в script_to_run со своей подписью, а затем выполнит его, если тот пройдет проверку:

...
with open("../../signatures/" + script_to_run + ".sig", "rb") as f:
verify = gpg.verify_file(f, script_to_run)
print(script_to_run + " ", verify.status)
if verify.status == "signature valid":
print("Signature valid, launching script...")
exec(open(script_to_run).read())
else:
print("Signature invalid or missing, ")
print("aborting script execution")

В результате скрипт будет выглядеть так:

#!/usr/bin/env python3
import os
import sys
import fs
from fs import open_fs
import gnupg
gpg = gnupg.GPG(gnupghome="/home/8host/.gnupg")
home_fs = open_fs(".")
script_to_run = str(sys.argv[1])
with open("../../signatures/" + script_to_run + ".sig", "rb") as f:
verify = gpg.verify_file(f, script_to_run)
print(script_to_run + " ", verify.status)
if verify.status == "signature valid":
print("Signature valid, launching script...")
exec(open(script_to_run).read())
else:
print("Signature invalid or missing, ")
print("aborting script execution")

Итак, все скрипты готовы. Но на данный момент их можно запускать только из текущей папки. Давайте изменим это.

7: Настройка доступа к скриптам

Для простоты работы давайте сделаем сценарии исполняемыми из любого каталога в системе и поместим их в $PATH. Используйте команду chmod, чтобы дать право на запуск владельцу файлов, вашему пользователю sudo:

chmod +x *.py

Теперь, чтобы найти настройки $PATH, выполните следующую команду:

echo $PATH
-bash: /home/8host/bin:/home/8host/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Файлы, хранящиеся в $PATH, будут доступны из любой папки вашей системы, если это позволяют привилегии каталога. Вы можете разместить свои скрипты в любом месте вашего $PATH, но сейчас давайте переместим скрипты из каталога python-test/ в /usr/local/bin/.

Обратите внимание, что расширение .py при копировании файлов нужно удалить. Если вы посмотрите на первую строку созданных скриптов, вы увидите:

#!usr/bin/env python3

Эта строка называется шебанг, она помогает операционной системе определить интерпретатор bash или среду, которую нужно использовать при выполнении кода. Когда вы выполните сценарий, операционная система заметит, что вы указали Python в качестве среды, и передаст код на выполнение интерпретатору Python. Это означает, что нам больше не нужны расширения файлов, чтобы идентифицировать среду, в которой нужно работать.

sudo mv encryptfiles.py /usr/local/bin/encryptfiles
sudo mv decryptfiles.py /usr/local/bin/decryptfiles
sudo mv signdetach.py /usr/local/bin/signdetach
sudo mv verifyfile.py /usr/local/bin/verifyfile
sudo mv verifydetach.py /usr/local/bin/verifydetach

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

8: Тестирование сценариев

Теперь, когда мы переместили сценарии в переменную $PATH, мы можем запустить их из любой папки на сервере.

Сначала убедитесь, что вы работаете в каталоге python-test, с помощью команды pwd:

pwd
/home/8host/python-test

Ранее в этом мануале вы создали три тестовых файла. Запустите команду ls -l, чтобы получить список файлов в папке:

ls -l

Вы должны увидеть три файла, которые хранятся в папке python-test:

-rw-rw-r-- 1 8host 8host 15 Apr 15 10:08 test1.txt
-rwxrwxr-x 1 8host 8host 15 Apr 15 10:08 test2.py
-rw-rw-r-- 1 8host 8host 15 Apr 15 10:08 test3.txt

На этих файлах можно проверить работу скриптов. Вы можете быстро отобразить содержимое файла перед шифрованием с помощью команды:

cat test1.txt
This is the first test file

Для начала создайте отделенные подписи для всех файлов:

signdetach
Created signatures directory
test2.py  signature created
test1.txt  signature created
test3.txt  signature created

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

Чтобы убедиться в этом, снова запустите ls –l:

ls -l
total 16
drwxrwxr-x 2 8host 8host 4096 Apr 21 14:11 signatures
-rw-rw-r-- 1 8host 8host 15 Apr 15 10:08 test1.txt
-rwxrwxr-x 1 8host 8host 15 Apr 15 10:08 test2.py
-rw-rw-r-- 1 8host 8host 15 Apr 15 10:08 test3.txt

В списке будет и новый каталог signatures. Запросите содержимое этого каталога.

ls -l signatures/
total 12
-rw-rw-r-- 1 8host 8host 473 Apr 21 14:11 test1.txt.sig
-rw-rw-r-- 1 8host 8host 473 Apr 21 14:11 test2.py.sig
-rw-rw-r-- 1 8host 8host 473 Apr 21 14:11 test3.txt.sig

Файлы отделенных подписей можно узнать по расширению .sig. Команда cat может вывести одну из подписей на экран. Давайте посмотрим на подпись test1.txt.sig:

cat signatures/test1.txt.sig
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAABAgAGBQJa20aGAAoJENVtx+Y8cX3mMhMH+gOZsLJX3aEgUPZzDlKRWYec
AyrXEGp5yIABj7eoLDKGUxftwGt+c4HZud1iEUy8AhtW/Ea6eRlMFPTso2hb9+cw
/MyffTrWGpa0AGjNvf4wbxdq7TNpAlw4nmcwKpeYqkUu2fP3c18oZ3G3R3+P781w
GWori9FK3eTyVPs9E0dVgdo7S8G1pF/ECo8Cl4Mrj80rERAitQAMbSaN/dF0wUKu
okRZPJPVjd6GwqRRkXoqwh0vm4c+p3nAhFV+v7uK2BOUIJKPFbbn58vmmn+LVaBS
MFWSb+X85KwwftIezqCV/hqsMKAuhkvfIi+YQFCDXElJMtjPBxxuvZFjQFjEHe8=
=4NB5
-----END PGP SIGNATURE-----

Так выглядит отделенная подпись файла test1.txt.

Получив подписи, можно зашифровать файлы. Для этого запустите скрипт encryptfiles:

encryptfiles
Created encrypted directory
ok:  True
status:  encryption ok
stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
[GNUPG:] END_ENCRYPTION
ok:  True
status:  encryption ok
stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
[GNUPG:] END_ENCRYPTION
ok:  True
status:  encryption ok
stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
[GNUPG:] END_ENCRYPTION

Обратите внимание, что в выводе скрипт сообщает, что он создал папку encrypted/. Также обратите внимание, что все файлы были успешно зашифрованы. Снова введите команду ls -l и обратите внимание на новую папку в каталоге:

ls -l
total 20
drwxrwxr-x 2 8host 8host 4096 Apr 21 14:42 encrypted
drwxrwxr-x 2 8host 8host 4096 Apr 21 14:11 signatures
-rw-rw-r-- 1 8host 8host   15 Apr 15 10:08 test1.txt
-rw-rw-r-- 1 8host 8host   15 Apr 15 10:08 test2.py
-rw-rw-r-- 1 8host 8host   15 Apr 15 10:08 test3.txt

Теперь давайте взглянем, как выглядит зашифрованное сообщение в файле test1.txt:

cat encrypted/test1.txt.gpg
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
hQEMA9Vtx+Y8cX3mAQf9FijeaCOKFRUWOrwOkUw7efvr5uQbSnxxbE/Dkv0y0w8S
Y2IxQPv4xS6VrjhZQC6K2R968ZQDvd+XkStKfy6NJLsfKZM+vMIWiZmqJmKxY2OT
8MG/b9bnNCORRI8Nm9etScSYcRu4eqN7AeUdWOXAFX+mo7K00IdEQH+0Ivyc+P1d
53WBgWstt8jHY2cn1sLdoHh4m70O7v1rnkHOvrQW3AAsBbKzvdzxOa0/5IKGCOYF
yC8lEYfOihyEetsasx0aDDXqrMZVviH3KZ8vEiH2n7hDgC5imgJTx5kpC17xJZ4z
LyEiNPu7foWgVZyPzD2jGPvjW8GVIeMgB+jXsAfvEdJJAQqX6qcHbf1SPSRPJ2jU
GX5M/KhdQmBcO9Sih9IQthHDXpSbSVw/UejheVfaw4i1OX4aaOhNJlnPSUDtlcl4
AUoBjuBpQMp4RQ==
=xJST
-----END PGP MESSAGE-----

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

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

Чтобы удалить оригиналы, введите:

rm *.txt *.py

Убедитесь, что файлы были удалены:

ls -l
total 8
drwxrwxr-x 2 8host 8host 4096 Apr 21 14:42 encrypted
drwxrwxr-x 2 8host 8host 4096 Apr 21 14:11 signatures

После удаления исходных файлов давайте расшифруем и проверим зашифрованные файлы. Перейдите в папку encrypted и запросите список файлов:

cd encrypted/ && ls -l
total 12
-rw-rw-r-- 1 8host 8host 551 Apr 21 14:42 test1.txt.gpg
-rw-rw-r-- 1 8host 8host 551 Apr 21 14:42 test2.py.gpg
-rw-rw-r-- 1 8host 8host 551 Apr 21 14:42 test3.txt.gpg

Чтобы расшифровать файлы, запустите сценарий decryptfiles из текущей папки:

decryptfiles
Created decrypted directory
ok:  True
status:  decryption ok
stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <8host@example.com>
[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
"Autogenerated Key <8host@example.com>"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] DECRYPTION_INFO 2 9
[GNUPG:] PLAINTEXT 62 1524321773
[GNUPG:] PLAINTEXT_LENGTH 15
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION
ok:  True
status:  decryption ok
stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <8host@example.com>
[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
"Autogenerated Key <8host@example.com>"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] DECRYPTION_INFO 2 9
[GNUPG:] PLAINTEXT 62 1524321773
[GNUPG:] PLAINTEXT_LENGTH 15
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION
ok:  True
status:  decryption ok
stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <8host@example.com>
[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
"Autogenerated Key <8host@example.com>"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] DECRYPTION_INFO 2 9
[GNUPG:] PLAINTEXT 62 1524321773
[GNUPG:] PLAINTEXT_LENGTH 15
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION

Сценарий вернул status: decryption ok для каждого файла, что означает, что каждый файл был успешно расшифрован.

Перейдите в новую папку decrypted и запросите содержимое test1.txt с помощью команды cat:

cd decrypted/ && cat test1.txt
This is the first test file

Мы восстановили сообщение из файла test1.txt, который мы удалили.

Теперь нужно убедиться, что это сообщение действительно является исходным сообщением, проверив его подпись с помощью сценария verifydetach.

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

Любое вмешательство в исходный файл, файл подписи или открытый ключ отправителя изменит значение хеш-функции, и проверка не будет пройдена.

Запустите скрипт из папки decrypted:

verifydetach
test2.py  signature valid
test1.txt  signature valid
test3.txt  signature valid

Из вывода видно, что подпись всех файлов действительна, это означает, что документы не были подделаны в ходе этого процесса.

Давайте посмотрим, что происходит, когда вы вносите изменения в документ после его подписания. Откройте файл test1.txt с помощью nano:

nano test1.txt

И добавьте такую строку:

This is the first test file
Let's add a sentence after signing the file

Сохраните и закройте файл.

Перезапустите скрипт verifydetach и обратите внимание на вывод:

verifydetach
test2.py  signature valid
test1.txt  signature bad
test3.txt  signature valid

Обратите внимание, что GnuPG вернул signature bad при проверке test1.txt. Это потому, что мы внесли изменения в файл после того, как он был подписан. Помните, что в процессе проверки gpg сравнивает значение хеша, хранящееся в файле подписи, со значением хеша, которое оно вычисляет из подписанного вами документа. Изменения, которые мы внесли в документ, привели к тому, что gpg вычислил другое значение хеша для test1.txt.

И последний тест: давайте воспользуемся файлом verifyfile, чтобы проверить скрипт перед его выполнением. Этот сценарий можно рассматривать как расширение сценария verifydetach, но с таким отличием: если сценарий проходит проверку, verifyfile его запустит.

Сценарий test2.py выводит строку в консоль при запуске. Давайте используем его, чтобы посмотреть, как работает скрипт verifyfile.

verifyfile test2.py
test2.py  signature valid
Signature valid, launching script...
The second test file is a Python script

Из вывода видно, что скрипт проверил подпись файла, вывел соответствующий результат на основе этой проверки, а затем запустил скрипт.

Давайте проверим сам процесс проверки, добавив в файл дополнительную строку кода. Откройте test2.py и вставьте следующую строку:

nano test2.py
print "The second test file is a Python script"
print "This line will cause the verification script to abort"

Теперь снова запустите verifyfile:

verifyfile test2.py
test2.py signature bad
Signature invalid,
aborting script execution

Файл не прошел проверку, а потому он не будет запущен.

Заключение

Модуль python-gnupg позволяет интегрировать широкий спектр криптографических инструментов в среду Python. Возможность быстрого шифрования или проверки целостности потоков данных имеет решающее значение в определенных ситуациях, таких как запрос или перемещение данных на удаленный сервер базы данных. Ключи GnuPG также можно использовать для создания резервных копий и аутентификации SSH или в настройке VPN.

Читайте также:

Tags: , , ,