GPG 使用初步
1. PGP 软件的安装
  PGP 的版本有很多,但由于其商业软件的特性,不能自由使用,自由软件基金会决定开发一个 PGP 的替代品,取名为 GnuPG ,这就是 PGP 的由来
   GPG 是基于命令行的程序,主要面向 Linux 等操作系统,由于我们在 Windows 系统下进行实验,这里选择 GPG 的 Windows 版本 Gpg4win
登录官网下载 Gpg4win:http://www.gpg4win.org/
 校验安装包的完整性,可以参考官方的 check integrity 说明:https://www.gpg4win.org/package-integrity.html

图中左侧为官网给出的证书参考,右侧是下载到本地的安装包的证书
 完成完整性校验后进行安装,按默认选项安装即可

安装完成

打开 cmd 输入命令 gpg --version 查看gpg的版本和支持的加密算法

提示当前 gpg 的版本为 2.3.4
 输入命令 gpg --help 查看帮助
 帮助中列出来了 gpg 的各种命令详解
gpg的基本语法为:gpg [options] [files]
 可以进行 Sign, check, encrypt or decrypt ( 签名、校验、加解密 ) 操作
2. 奇怪的报错
在 cmd 中输入命令 gpg --full-generate-key 开始进行密钥生成,在流程结束后,准备等待输入 passphrase,却收到报错如下

具体提示为
gpg: can't connect to the gpg-agent: IPC connect call failed
gpg: agent_genkey failed: No agent running
Key generation failed: No agent running
复制错误信息,在网上搜索了一下相关的博客,寻找解决方案,中文互联网上对于这个报错的文章较少,最后在 StackExchange 上看到了相关的解释

This can happen when you’re using Git Bash (which ships with gpg) and you’re installing GnuPG4Win additionally. The latter ships with a more recent version.
这种情况(指相关报错)会出现是因为你在使用 Git Bash(Git Bash 已经装载了 gpg)时额外安装了 Gpg4win,Gpg4win 搭载了更新版本的 gpg
本人电脑上确实安装了 Git Bash,但使用帖子中提到的相关命令,在 cmd 中只能查看到 Gpg4win 的版本信息,但问题应该就与 Git Bash 有关,先将刚才安装的 Gpg4win 卸载掉,再在 cmd 中输入命令 gpg ,提示
'gpg' 不是内部或外部命令,也不是可运行的程序或批处理文件。
打开 Git Bash 输入命令 gpg --version

可以看到 Git Bash 确实装载了 2.2.29 版本的 gpg,之前 Gpg4win 的 gpg 版本为 2.3.4,可以断定,之前出现的错误就是因为 Git Bash 已经装载了 gpg,系统中有 gpg-agent 在运行,额外安装 Gpg4win 就会发生上述错误
3. 创建密钥对
打开 Git Bash 输入命令 gpg --full-generate-key 来完整地创建一个新的密钥对
gpg (GnuPG) 2.2.29-unknown; Copyright © 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(14) Existing key from card
Your selection? 1
第一段是版权声明,然后让用户自己选择加密算法。默认选择第一个选项,表示加密和签名都使用 RSA 算法。
然后,系统会询问密钥的长度。
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 2048
Requested keysize is 2048 bits
RSA 密钥长度在 1024~4096 之间,密钥长度决定了安全性,默认是 3072 位,这里我选择 2048 位。
接着,设定密钥的有效期。
Please specify how long the key should be valid. # 请确认密钥的有效期
0 = key does not expire # 密钥不会过期
<n> = key expires in n days # 密钥在 n 天后过期
<n>w = key expires in n weeks # 密钥在 n 周后过期
<n>m = key expires in n months # 密钥在 n 月后过期
<n>y = key expires in n years # 密钥在 n 年后过期
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
因为这个密钥仅为个人使用,并且可以有效保管私钥,选择第一个选项,永不过期。之后系统会进行确认,输入 y 进行确认
接下来输入你的真实姓名、邮件地址和注释来生成你的用户 ID 信息 这里注释一栏我选择为空
GnuPG needs to construct a user ID to identify your key.
Real name: Hxxxxx
Email address: xxxxxxxx@qq.com
Comment:
提示生成了用户 ID
You selected this USER-ID:
“Hxxxxx <xxxxxxxx@qq.com>”
之后还会进行一次确认
Change (N)ame, ©omment, (E)mail or (O)kay/(Q)uit? O
输入 N 修改名字,输入 C 修改注释,输入 E 修改邮件,输入 O 进行确认,输入 Q 则退出
 我们输入 O 进行确认
之后会提示
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize thedisks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.
我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
接下来弹出一个窗口,用来输入用户口令 passphrase 来对你的私钥进行加密存储

可以看到 此时输入的 passphrase 仅有 5 位,且均为字母,点击 OK 后,有如下提示

重新输入合规的 passphrase 后,系统提示密钥已经生成了
gpg: key F4AE9D0C2B8A marked as ultimately trusted
gpg 密钥 F4AE9D0C2B8A 被标记为绝对信任
公钥和私钥已经生成并经签名。

这样,新的属于你的密钥对就生成了
3. 导出密钥对
导出公钥列表,命令 gpg --list-keys 用来查看当前的公钥环

第 4 行显示密钥环 pubring.kbx
 pub:公钥特征 : RSA 算法、2048 位、创建时间
 uid:用户 ID
 sub:显示私钥特征
导出私钥列表,命令 gpg --list-secret-keys 用来查看当前的私钥环

sec:公钥特征 : RSA 算法、2048 位、创建时间
 uid:用户 ID
 ssb:显示私钥特征
4. 上传公钥
公钥服务器是网络上专门储存用户公钥的服务器。send-keys参数可以将公钥上传到服务器。
gpg --send-keys [用户ID] --keyserver hkp://subkeys.pgp.net
使用上面的命令,你的公钥就被传到了服务器 subkeys.pgp.net,然后通过交换机制,所有的公钥服务器最终都会包含你的公钥。
由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性。通常,你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。fingerprint 参数生成公钥指纹。
gpg --fingerprint [用户 ID]
5. 文件签名和加密
下面进行签名同时加密的操作,准备一个文本文件,地址为 E:/test.txt 命名为 test.txt,内容如图

输入命令
gpg --sign --encrypt E:/test.txt # 签名并加密目录在 E:/ 的文件 test.txt

执行命令后,提示我们输入用户 ID ,想要结束则输入一个空行,输入我们的用户 ID ,即自己作为接收者,之后在弹出来的提示框中输入用户口令 passphrase

加密完成,打开文件目录可以看到,在源目录下生成了一个 .gpg 格式的文件。这就是我们的加密文件

我们将这个 .gpg 文件的后缀改为 .txt 格式,查看其内容,

发现文件的内容都是乱码,这就是加密后的文档
6. 文件解密和签名校验
我们使用上个步骤中加密的 test.txt.gpg 作为待解密文件,在 Git Bash 中输入命令
gpg --decrypt E:/test.txt.gpg
之后在弹出的对话框中输入用户口令 passphrase

由于该文件的接收人仍是我,公钥和私钥都存储在本地,想要得到我的私钥,就需要输入用户口令 passphrase,解密和签名校验完成,结果如图

gpg 解密后的文件内容会直接显示在标准输出,图中红框内为解密后的文件内容,之后紧跟的是该文件签名创建的时间,最后一行显示了签名的属性:这是一个来自"我"的可信签名
7. 总结和参考文献
  PGP 作为成熟的加密体制,其安全性毋庸置疑,在 Gpg 中还有其他很多的操作,包括对文件仅加密、仅签名、签名保存为 ASCII 文件等,这些操作可以在官方的使用手册上查到具体的使用方法,读者应该注重的是 PGP 的设计思想和相关的加密技术,对于软件的使用有一定的命令行基础即可
   对于那些正在使用 Git 进行版本管理的读者来说,不需要再额外安装 Gpg 服务,Git 中内置了较老版本的 Gpg,额外安装将带来不必要的麻烦
参考文档如下:
- 阮一峰 GPG入门教程-阮一峰
- Paul Heinlein, GPG Quick Start
- Ubuntu help,GnuPrivacyGuardHowto
- KNL, GnuPG Tutorial
- Alan Eliasen. GPG Tutorial
- GnuPG 袖珍 HOWTO (中文版)
- The GNU Privacy Handbook














