如何使用 Python-GnuPG 和 Python 3 验证代码和加密数据

作者选择了 开放式互联网 / 自由言论基金作为 写给捐赠计划的一部分接受捐款。

介绍

GnuPG包提供了生成和存储加密密钥的完整解决方案,还允许您加密和签署数据和通信。

在本教程中,您将创建一系列使用Python 3的脚本与 python-gnupg模块. 这些脚本将允许您签署和加密多个文件,并在运行之前验证脚本的完整性。

前提条件

在继续使用本教程之前,请完成以下先决条件:

步骤 1 – 获取关键对信息

在前提条件中完成 GnuPG 教程后,您将在您的主目录中存储一个密钥对。GnuPG 将具有用户名和电子邮件的密钥存储,以帮助识别密钥对。

运行下面的命令,以获取可用的密钥列表:

1gpg --list-keys
1[secondary_label Output]
2/home/sammy/.gnupg/pubring.gpg
3-----------------------------
4pub 2048R/4920B23F 2018-04-23
5uid Sammy <[email protected]>
6sub 2048R/50C06279 2018-04-23

记下输出中的uid行中显示的电子邮件地址,您将需要它来识别您的密钥。

步骤 2 — 安装 Python-GnuPG 和签名文件

有了你的密钥,你可以安装python-gnupg模块,它作为一个围绕GnuPG的包裹,以允许GnuPG和Python之间的互动。

  • 创建文件的分离签名,通过从文件中分离签名来添加一个安全层的签名过程
  • 加密文件
  • 解密文件
  • 验证分离签名和脚本

您将首先创建脚本,以及一些测试文件,然后继续测试这些文件上的脚本。

要开始,让我们安装python-gnupg模块,以及fs包,这将允许您打开,阅读和写下测试文件。

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

有了这些包,我们可以继续创建脚本和测试文件。

要存储脚本和测试文件,请在您的主目录中创建一个名为python-test的文件夹:

1cd ~/
2mkdir python-test

转到此目录:

1cd python-test/

接下来,让我们创建三个测试文件:

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

为了为我们的测试文件创建单独的签名,让我们创建一个名为signdetach.py的脚本,该脚本将瞄准它所执行的目录中的所有文件。

分离的签名将存储在一个名为签名/的新文件夹中,该文件将在脚本运行时创建。

使用nano或您最喜欢的文本编辑器打开名为signdetach.py的新文件:

1nano signdetach.py

让我们先导入脚本所需的所有模块,这些包括osfs包,允许文件导航,以及gnupg:

1[label ~/python-test/signdetach.py]
2#!/usr/bin/env python3
3
4import os
5import fs
6from fs import open_fs
7import gnupg

现在让我们设置 GnuPG 会找到其加密密钥的目录。 GnuPG 默认地将其密钥存储在 `.gnupg 中,所以让我们用我们的用户名进行配置。

1[label ~/python-test/signdetach.py]
2...
3gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")

接下来,让我们创建一个home_fs变量来存储当前目录位置作为文件对象,这将使脚本能够在执行的目录中工作:

1[label ~/python-test/signdetach.py]
2...
3home_fs = open_fs(".")

到目前为止,你的脚本将是这样的:

 1[label ~/python-test/signdetach.py]
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")

此配置块是您将在您的脚本中使用的基本模板,当您通过本教程时。

接下来,添加代码来检查是否有名为签名/的文件夹,并创建它,如果它不存在:

1[label ~/python-test/signdetach.py]
2...
3if os.path.exists("signatures/"):
4        print("Signatures directory already created")
5else:
6        home_fs.makedir(u"signatures")
7        print("Created signatures directory")

创建一个空的数组以存储文件名,然后扫描当前目录,将所有文件名附加到files_dir数组:

1[label ~/python-test/signdetach.py]
2...
3files_dir = []
4
5files = [f for f in os.listdir(".") if os.path.isfile(f)]
6for f in files:
7    files_dir.append(f)

下一步,脚本会为文件生成单独的签名。通过files_dir数组,您将使用键盘上的第一个私钥创建每个文件的签名。 要访问私钥,您需要用您设置的密码语句解锁它。 用您在前提条件中生成密钥对时使用的密码语句代替我的密码语句:

1[label ~/python-test/signdetach.py]
2...
3for x in files_dir:
4    with open(x, "rb") as f:
5        stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig")
6        os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig")
7        print(x+" ", stream.status)

完成后,所有签名都将移动到签名文件夹中,完成的脚本将看起来像这样:

 1[label ~/python-test/signdetach.py] 
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")
11
12if os.path.exists("signatures/"):
13    print("Signatures directory already created")
14else:
15    home_fs.makedir(u"signatures")
16    print("Created signatures directory")
17
18files_dir = []
19
20files = [f for f in os.listdir(".") if os.path.isfile(f)]
21for f in files:
22    files_dir.append(f)
23
24for x in files_dir:
25    with open(x, "rb") as f:
26        stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig")
27        os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig")
28        print(x+" ", stream.status)

现在我们可以转到加密文件。

步骤 3 – 加密文件

在文件夹中运行加密脚本将导致该文件夹中的所有文件被复制和加密到名为加密/的新文件夹中。

打开一个名为encryptfiles.py的新文件:

1nano encryptfiles.py

首先,导入所有所需的模块,设置 GnuPG 主目录,并创建当前工作目录变量:

 1[label ~/python-test/encryptfiles.py]
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")

接下来,让我们添加代码来检查当前目录是否已经有名为加密的文件夹,并创建它,如果它不存在:

1[label ~/python-test/encryptfiles.py]
2...
3if os.path.exists("encrypted/"):
4        print("Encrypt directory exists")
5else:
6        home_fs.makedir(u"encrypted")
7        print("Created encrypted directory")

在搜索要加密的文件之前,让我们创建一个空的数组来存储文件名:

1[label ~/python-test/encryptfiles.py]
2...
3files_dir = []

接下来,创建一个循环来扫描文件的文件夹,并将其附加到阵列中:

1[label ~/python-test/encryptfiles.py]
2...
3files = [f for f in os.listdir(".") if os.path.isfile(f)]
4for f in files:
5    files_dir.append(f)

最后,让我们创建一个循环来加密文件中的所有文件。完成后,所有加密文件将被转移到加密文件夹中。在本示例中,[email protected]是用于加密过程中使用的密钥的电子邮件 ID。 请确保用您在步骤 1 中注明的电子邮件地址替换。

1[label ~/python-test/encryptfiles.py]
2...
3for x in files_dir:
4    with open(x, "rb") as f:
5        status = gpg.encrypt_file(f,recipients=["[email protected]"],output= files_dir[files_dir.index(x)]+".gpg")
6        print("ok: ", status.ok)
7        print("status: ", status.status)
8        print("stderr: ", status.stderr)
9        os.rename(files_dir[files_dir.index(x)] + ".gpg", 'encrypted/' +files_dir[files_dir.index(x)] + ".gpg")

如果您在.gnupg 文件夹中存储了多个密钥,并且想要使用特定公共密钥或多个公共密钥进行加密,则需要通过添加额外的接收者或更换当前的接收者来修改接收者数组。

你的cryptfiles.py脚本文件在你完成后会看起来像这样:

 1[label ~/python-test/encryptfiles.py] 
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")
11
12if os.path.exists("encrypted/"):
13    print("Encrypt directory exists")
14else:
15    home_fs.makedir(u"encrypted")
16    print("Created encrypted directory")
17
18files_dir = []
19
20files = [f for f in os.listdir(".") if os.path.isfile(f)]
21for f in files:
22    files_dir.append(f)
23
24for x in files_dir:
25    with open(x, "rb") as f:
26        status = gpg.encrypt_file(f,recipients=["[email protected]"],output= files_dir[files_dir.index(x)]+".gpg")
27        print("ok: ", status.ok)
28        print("status: ", status.status)
29        print("stderr: ", status.stderr)
30        os.rename(files_dir[files_dir.index(x)] + ".gpg", "encrypted/" +files_dir[files_dir.index(x)] + ".gpg")

现在让我们来看看这个过程的第二部分:一次解密和验证多个文件。

步骤 4 – 解密文件

解密脚本工作与加密脚本相同,但它是指在一个加密/目录内执行。当启动时,decryptfiles.py将首先识别使用的公共密钥,然后在.gnupg文件夹中搜索相应的私钥来解密文件。

打开一个名为decryptfiles.py的新文件,使用nano或您最喜欢的编辑器:

1nano decryptfiles.py

开始使用配置设置:

 1[label ~/python-test/decryptfiles.py]
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")

接下来,创建两个空数组以存储脚本执行期间的数据:

1[label ~/python-test/decryptfiles.py]
2...
3files_dir = []
4files_dir_clean = []

这里的目标是脚本将解密文件放到自己的文件夹中;否则,加密和解密文件会混合,难以找到一个特定的解密文件。

1[label ~/python-test/decryptfiles.py]
2...
3if os.path.exists("decrypted/"):
4    print("Decrypted directory already exists")
5else:
6    home_fs.makedir(u"decrypted/")
7    print("Created decrypted directory")

通过文件夹扫描并将所有文件名附加到 files_dir 阵列中:

1[label ~/python-test/decryptfiles.py]
2...
3files = [f for f in os.listdir(".") if os.path.isfile(f)]
4for f in files:
5    files_dir.append(f)

所有加密文件都添加了 .gpg 扩展到他们的文件名,表示它们是加密的. 但是,当解密它们时,我们想保存它们而没有这个扩展,因为它们不再加密。

要做到这一点,循环通过 files_dir 数组,并从每个文件名中删除 .gpg 扩展:

1[label ~/python-test/decryptfiles.py]
2...
3    for x in files_dir:
4            length = len(x)
5            endLoc = length - 4
6            clean_file = x[0:endLoc]
7            files_dir_clean.append(clean_file)

新的清理文件名存储在file_dir_clean数组中。

接下来,让我们循环通过文件并解密它们. 用您的密码代替我的密码以解锁私钥:

1[label ~/python-test/decryptfiles.py]
2...
3for x in files_dir:
4    with open(x, "rb") as f:
5       status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)])
6       print("ok: ", status.ok)
7       print("status: ", status.status)
8       print("stderr: ", status.stderr)
9       os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])

你的脚本文件将在你完成后看起来像这样:

 1[label ~/python-test/decryptfiles.py] 
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")
11
12files_dir = []
13files_dir_clean = []
14
15if os.path.exists("decrypted/"):
16    print("Decrypted directory already exists")
17else:
18    home_fs.makedir(u"decrypted/")
19    print("Created decrypted directory")
20
21files = [f for f in os.listdir(".") if os.path.isfile(f)]
22for f in files:
23    files_dir.append(f)
24
25for x in files_dir:
26    length = len(x)
27    endLoc = length - 4
28    clean_file = x[0:endLoc]
29    files_dir_clean.append(clean_file)
30
31for x in files_dir:
32    with open(x, "rb") as f:
33       status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)])
34       print("ok: ", status.ok)
35       print("status: ", status.status)
36       print("stderr: ", status.stderr)
37       os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])

有了我们的解密脚本,我们可以继续验证多个文件的分离签名。

步骤 5 – 验证分离签名

要验证多个文件的单独数字签名,让我们写一个verifydetach.py脚本. 此脚本将搜索工作目录中的一个签名文件夹,并用其签名验证每个文件。

打开一个名为verifydetach.py的新文件:

1nano verifydetach.py

导入所有必要的库,设置工作和家庭目录,并创建空的 files_dir 数组,如上面的示例:

 1[label ~/python-test/verifydetach.py]
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")
11
12files_dir = []

接下来,让我们扫描包含我们想要验证的文件的文件夹. 文件名将附加到空的 files_dir 数组:

1[label ~/python-test/verifydetach.py]
2...
3files = [f for f in os.listdir(".") if os.path.isfile(f)]
4for f in files:
5files_dir.append(f)

最后,让我们用单独的签名来验证每个文件,使用一个循环,通过files_dir数组来搜索每个文件的单独签名在签名/文件夹中。

1[label ~/python-test/verifydetach.py]
2...
3for i in files_dir:
4     with open("../../signatures/" + i + ".sig", "rb") as f:
5         verify = gpg.verify_file(f, i)
6         print(i + " ", verify.status)

当你完成后,你的脚本将看起来像这样:

 1[label ~/python-test/verifydetach.py] 
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")
11
12files_dir = []   
13
14files = [f for f in os.listdir(".") if os.path.isfile(f)]
15for f in files:
16    files_dir.append(f)
17
18for i in files_dir:
19    with open("../../signatures/" + i + ".sig", "rb") as f:
20        verify = gpg.verify_file(f, i)
21        print(i + " ", verify.status)

接下来,让我们来看看如何在您的服务器上执行文件之前验证文件的签名。

步骤 6 - 检查文件

最终的脚本在执行之前会验证脚本。在这种意义上,它类似于verifydetach,但它具有启动已验证的脚本的额外能力。它通过将脚本的名称作为一个论点,然后验证该文件的签名来工作。如果验证成功,脚本会向控制台发送消息并启动验证的脚本。如果验证过程失败,脚本会将错误发送到控制台并停止执行文件。

创建一个名为verifyfile.py的新文件:

1nano verifyfile.py

让我们先导入必要的库并设置工作目录:

 1[label ~/python-test/verifyfile.py]
 2#!/usr/bin/env python3
 3
 4import os
 5import fs
 6from fs import open_fs
 7import gnupg
 8
 9gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
10home_fs = open_fs(".")

要使脚本工作,需要存储文件的名称来验证和执行。 要做到这一点,让我们创建一个名为script_to_run的新变量:

1[label ~/python-test/verifyfile.py]
2...
3script_to_run = str(sys.argv[1])

此变量采用第一个参数并将其存储在新创建的变量中,然后,脚本将打开分离的签名文件,在script_to_run中验证该文件,然后执行如果它通过验证:

 1[label ~/python-test/verifyfile.py]
 2...
 3with open("../../signatures/" + script_to_run + ".sig", "rb") as f:
 4     verify = gpg.verify_file(f, script_to_run)
 5     print(script_to_run + " ", verify.status)
 6     if verify.status == "signature valid":
 7          print("Signature valid, launching script...")
 8          exec(open(script_to_run).read())
 9     else:
10           print("Signature invalid or missing, ")
11           print("aborting script execution")

完成的剧本将是这样的:

 1[label ~/python-test/verifyfile.py] 
 2#!/usr/bin/env python3
 3
 4import os
 5import sys
 6import fs
 7from fs import open_fs
 8import gnupg
 9
10gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
11home_fs = open_fs(".")
12
13script_to_run = str(sys.argv[1])
14
15with open("../../signatures/" + script_to_run + ".sig", "rb") as f:
16    verify = gpg.verify_file(f, script_to_run)
17    print(script_to_run + " ", verify.status)
18    if verify.status == "signature valid":
19        print("Signature valid, launching script...")
20        exec(open(script_to_run).read())
21    else:
22        print("Signature invalid or missing, ")
23        print("aborting script execution")

我们已经完成了脚本的创建,但目前它们只能从当前文件夹中启动,在下一步,我们将更改他们的权限,以使它们在全球范围内可访问。

步骤7 – 使脚本可用系统范围内

为了方便使用,让我们从系统上的任何目录或文件夹中执行脚本,并将它们放入我们的$PATH。使用chmod命令将可执行权限授予文件的所有者,您的非根用户:

1chmod +x *.py

现在要找到您的$PATH设置,请运行以下命令:

1echo $PATH
1[secondary_label Output]
2-bash: /home/sammy/bin:/home/sammy/.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/

如果你看我们创建的脚本的第一行,你会看到#!usr/bin/env python3这个行被称为shebang(https://en.wikipedia.org/wiki/Shebang_(Unix),它有助于操作系统识别执行代码时使用的bash解释器或环境。当我们执行脚本时,操作系统会注意到我们指定了Python作为我们的环境,并将代码传递给Python进行执行。

1sudo mv encryptfiles.py /usr/local/bin/encryptfiles
2sudo mv decryptfiles.py /usr/local/bin/decryptfiles
3sudo mv signdetach.py /usr/local/bin/signdetach
4sudo mv verifyfile.py /usr/local/bin/verifyfile
5sudo mv verifydetach.py /usr/local/bin/verifydetach

现在,脚本可以在系统中的任何地方执行,只需运行脚本名称以及脚本可能从命令行中提取的任何论点。

步骤8 - 测试脚本

现在我们已经将脚本移动到我们的$PATH,我们可以从服务器上的任何文件夹运行它们。

首先,检查您是否仍在使用pwd命令在python-test目录中工作:

1pwd

产量应该是:

1[secondary_label Output]
2/home/sammy/python-test

你在教程中早些时候创建了三个测试文件。运行ls -l命令来列出文件夹中的文件:

1ls -l

你应该看到存储在你的python-test文件夹中的三个文件:

1[secondary_label Output]
2-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt
3-rwxrwxr-x 1 sammy sammy 15 Apr 15 10:08 test2.py 
4-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt

我们将在这三个文件上测试脚本,您可以使用cat命令快速显示文件的内容,如下所示:

1cat test1.txt
1[secondary_label Output]
2This is the first test file

让我们开始为所有文件创建分离的签名,然后从当前文件夹中执行signdetach脚本:

1signdetach
1[secondary_label Output]
2Created signatures directory
3test2.py signature created
4test1.txt signature created
5test3.txt signature created

在输出中注意,脚本检测到签名/目录不存在,然后创建了文件签名。

我们可以通过再次运行ls -l命令来确认这一点:

1ls -l
1[secondary_label Output]
2total 16
3drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures
4-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt
5-rwxrwxr-x 1 sammy sammy 15 Apr 15 10:08 test2.py 
6-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt

在列表中的项目中注意新的签名目录,让我们列出这个文件夹的内容,并仔细看看其中一个签名。

要列出所有签名,键入:

1ls -l signatures/
1[secondary_label Output]
2total 12
3-rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test1.txt.sig
4-rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test2.py.sig
5-rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test3.txt.sig

单独的签名文件可以通过.sig扩展来识别。再次,cat命令可以显示这些签名中的一个内容。

1cat signatures/test1.txt.sig
 1[secondary_label Output]
 2-----BEGIN PGP SIGNATURE-----
 3Version: GnuPG v1
 4
 5iQEcBAABAgAGBQJa20aGAAoJENVtx+Y8cX3mMhMH+gOZsLJX3aEgUPZzDlKRWYec
 6AyrXEGp5yIABj7eoLDKGUxftwGt+c4HZud1iEUy8AhtW/Ea6eRlMFPTso2hb9+cw
 7/MyffTrWGpa0AGjNvf4wbxdq7TNpAlw4nmcwKpeYqkUu2fP3c18oZ3G3R3+P781w
 8GWori9FK3eTyVPs9E0dVgdo7S8G1pF/ECo8Cl4Mrj80rERAitQAMbSaN/dF0wUKu
 9okRZPJPVjd6GwqRRkXoqwh0vm4c+p3nAhFV+v7uK2BOUIJKPFbbn58vmmn+LVaBS
10MFWSb+X85KwwftIezqCV/hqsMKAuhkvfIi+YQFCDXElJMtjPBxxuvZFjQFjEHe8=
11=4NB5
12-----END PGP SIGNATURE-----

此输出是test1.txt的分离签名。

有了签名,可以继续加密我们的文件. 要做到这一点,执行cryptfiles脚本:

1encryptfiles
 1[secondary_label Output]
 2Created encrypted directory
 3ok:  True
 4status:  encryption ok
 5stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
 6[GNUPG:] END_ENCRYPTION
 7
 8ok:  True
 9status:  encryption ok
10stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
11[GNUPG:] END_ENCRYPTION
12
13ok:  True
14status:  encryption ok
15stderr:  [GNUPG:] BEGIN_ENCRYPTION 2 9
16[GNUPG:] END_ENCRYPTION

从输出中,注意到脚本创建了加密文件夹,也注意到所有文件都成功加密,再次运行ls -l命令,并注意到目录中的新文件夹:

1ls -l
1[secondary_label Output]
2total 20
3drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:42 encrypted
4drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures
5-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt
6-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test2.py
7-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt

讓我們來看看「test1.txt」中的訊息現在已經被加密了後,會怎麼樣:

1cat encrypted/test1.txt.gpg
 1[secondary_label Output]
 2-----BEGIN PGP MESSAGE-----
 3Version: GnuPG v1
 4
 5hQEMA9Vtx+Y8cX3mAQf9FijeaCOKFRUWOrwOkUw7efvr5uQbSnxxbE/Dkv0y0w8S
 6Y2IxQPv4xS6VrjhZQC6K2R968ZQDvd+XkStKfy6NJLsfKZM+vMIWiZmqJmKxY2OT
 78MG/b9bnNCORRI8Nm9etScSYcRu4eqN7AeUdWOXAFX+mo7K00IdEQH+0Ivyc+P1d
 853WBgWstt8jHY2cn1sLdoHh4m70O7v1rnkHOvrQW3AAsBbKzvdzxOa0/5IKGCOYF
 9yC8lEYfOihyEetsasx0aDDXqrMZVviH3KZ8vEiH2n7hDgC5imgJTx5kpC17xJZ4z
10LyEiNPu7foWgVZyPzD2jGPvjW8GVIeMgB+jXsAfvEdJJAQqX6qcHbf1SPSRPJ2jU
11GX5M/KhdQmBcO9Sih9IQthHDXpSbSVw/UejheVfaw4i1OX4aaOhNJlnPSUDtlcl4
12AUoBjuBpQMp4RQ==
13=xJST
14-----END PGP MESSAGE-----

原始文件中存储的句子已被转化为复杂的字符和数字序列,这是加密过程的结果。

现在文件已签名和加密,可以删除原始文件并从加密文件中恢复原始消息。

要删除原始内容,键入:

1rm *.txt *.py

再次运行ls -l命令,以确保所有原始文件已被删除:

1ls -l
1[secondary_label Output]
2total 8
3drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:42 encrypted
4drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures

有了原始文件,让我们解密并验证加密文件. 更改到加密文件夹并列出所有文件:

1cd encrypted/ && ls -l
1[secondary_label Output]
2total 12
3-rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test1.txt.gpg
4-rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test2.py.gpg
5-rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test3.txt.gpg

要解密文件,请从当前文件夹中运行decryptfiles脚本:

1decryptfiles
 1[secondary_label Output]
 2Created decrypted directory
 3ok:  True
 4status:  decryption ok
 5stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
 6[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <[email protected]>
 7[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
 8[GNUPG:] GOOD_PASSPHRASE
 9gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
10      "Autogenerated Key <[email protected]>"
11[GNUPG:] BEGIN_DECRYPTION
12[GNUPG:] DECRYPTION_INFO 2 9
13[GNUPG:] PLAINTEXT 62 1524321773
14[GNUPG:] PLAINTEXT_LENGTH 15
15[GNUPG:] DECRYPTION_OKAY
16[GNUPG:] GOODMDC
17[GNUPG:] END_DECRYPTION
18
19ok:  True
20status:  decryption ok
21stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
22[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <[email protected]>
23[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
24[GNUPG:] GOOD_PASSPHRASE
25gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
26      "Autogenerated Key <[email protected]>"
27[GNUPG:] BEGIN_DECRYPTION
28[GNUPG:] DECRYPTION_INFO 2 9
29[GNUPG:] PLAINTEXT 62 1524321773
30[GNUPG:] PLAINTEXT_LENGTH 15
31[GNUPG:] DECRYPTION_OKAY
32[GNUPG:] GOODMDC
33[GNUPG:] END_DECRYPTION
34
35ok:  True
36status:  decryption ok
37stderr:  [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0
38[GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key <[email protected]>
39[GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0
40[GNUPG:] GOOD_PASSPHRASE
41gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15
42      "Autogenerated Key <[email protected]>"
43[GNUPG:] BEGIN_DECRYPTION
44[GNUPG:] DECRYPTION_INFO 2 9
45[GNUPG:] PLAINTEXT 62 1524321773
46[GNUPG:] PLAINTEXT_LENGTH 15
47[GNUPG:] DECRYPTION_OKAY
48[GNUPG:] GOODMDC
49[GNUPG:] END_DECRYPTION

该脚本为每个文件返回状态:解密OK,这意味着每个文件都被成功解密。

更改到新的解密/文件夹并使用cat命令显示test1.txt的内容:

1cd decrypted/ && cat test1.txt
1[secondary_label Output]
2This is the first test file

我们已经恢复了我们删除的test1.txt文件中存储的消息。

接下来,让我们通过用verifydetach脚本验证其签名来确认这个消息确实是原来的消息。

签名文件包含签名者的身份以及使用签名文档数据计算的哈希值。在验证过程中,gpg 将使用发件人的公共密钥并与哈希算法一起计算数据的哈希值。

任何对发件人的原始文件、签名文件或公共密钥的篡改都会导致哈希值发生变化,而验证过程会失败。

解密文件夹中运行脚本:

1verifydetach
1[secondary_label Output]
2test2.py signature valid
3test1.txt signature valid
4test3.txt signature valid

您可以从输出中看到所有文件都有有效的签名,这意味着文档在这个过程中没有被篡改。

现在让我们看看在您签署文档后对文档进行更改时会发生什么。

1nano test1.txt

现在将下面的句子添加到文件中:

1[label ~/python-test/encrypted/decrypted/test1.txt]
2This is the first test file
3Let's add a sentence after signing the file

保存并关闭文件。

现在重新运行verifydetach脚本,并注意输出如何改变:

1verifydetach
1[secondary_label Output]
2test2.py signature valid
3test1.txt signature bad
4test3.txt signature valid

请注意,GnuPG在验证test1.txt时返回了签名差。这是因为我们在签名后对该文件进行了更改。请记住,在验证过程中,gpg 将签名文件中存储的哈希值与它从您签名的文档计算的哈希值进行比较。

对于我们最后的测试,让我们使用verifyfile来验证脚本,然后在它被执行之前。这个脚本可以被视为verifydetach脚本的扩展,但有以下区别:如果一个脚本通过验证过程,那么verifyfile将继续启动它。

test2.py脚本在启动时会打印一个字符串到控制台上,让我们用它来展示verifyfile脚本是如何工作的。

运行test2.py脚本与verifyfile:

1verifyfile test2.py
1[secondary_label Output]
2test2.py signature valid
3Signature valid, launching script...
4The second test file is a Python script

从输出中可以看到,脚本验证了文件的签名,根据该验证打印了适当的结果,然后启动了脚本。

让我们通过添加一个额外的代码行来测试验证过程,打开‘test2.py’并插入以下代码行:

1nano test2.py
1[label ~/python-test/encrypted/decrypted/test2.py]
2print "The second test file is a Python script"
3print "This line will cause the verification script to abort"

现在重新运行verify脚本:

1verifyfile test2.py
1[secondary_label Output]
2test2.py signature bad
3Signature invalid, 
4aborting script execution

脚本验证失败,导致脚本启动被中断。

结论

python-gnupg模块允许广泛的加密工具和Python之间的集成,快速加密或验证数据流的完整性在某些情况下至关重要,例如查询或存储数据到远程数据库服务器。

要了解更多关于「python-gnupg」模块的信息,您可以访问 python-gnupg 项目页面

Published At
Categories with 技术
comments powered by Disqus