GnuPG 是 PGP 的开源实现软件(实际上是基于 RFC 4880),目的是取代 PGP,需要注意,GnuPG 自己不带算法, 使用 RSA、DSA 等算法,GnuPG 只是使用这些算法来进行加密、解密的工具而已。

由于 GnuPG 在生成私钥的时候进行大量的随机字符串, 我们需要安装一个用于生成随机数的工具

1
$ sudo apt-get install haveged

havged 的简单说明:

haveged - Generate random numbers and feed linux random device.

需要注意,haveged 为 daemon (你也可以从名字上看出来), 所以, docker 玩家请自行查找其他解决办法

生成私钥

1
$ gpg --gen-key

生成过程中会让你完善如下信息:

  • 加密方式:RSA、DSA、RSA(仅签名)、DSA(仅签名)
  • RSA/DSA key 长度(越长越安全, 当时相对来说运算也会慢)
  • RSA/DSA key 过期时间
  • Real Name 真实姓名
  • Email address 邮箱地址
  • Comment 一个简单的注释
  • passphrase 密码

如下,生成完成后会显示当前生成的相关信息,如下:

1
2
3
4
5
6
7
8
9
10
gpg: key ECA47B28 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub 2048D/ECA47B28 2016-07-25
Key fingerprint = F550 632A FF0F 2FDE 99AD 8761 BF7F 107C ECA4 7B28
uid Rui Ma <xjmarui@qq.com>
sub 2048g/00C364DD 2016-07-25

列表公钥、私钥

当我们生成了私钥后,即可列表自己的私钥

1
$ gpg --list-secret-keys

如下为结果:

1
2
3
sec   2048D/ECA47B28 2016-07-25
uid Rui Ma <xjmarui@qq.com>
ssb 2048g/00C364DD 2016-07-25

列表了自己的 PGP PUBLIC KEY, 用户信息等。


同样,我们可列表所有的公钥

1
$ gpg --list-keys

如下为结果:

1
2
3
4
5
6
7
8
9
pub   2048D/ECA47B28 2016-07-25
uid Rui Ma <xjmarui@qq.com>
sub 2048g/00C364DD 2016-07-25

pub 1024D/B2D7795E 2001-01-04
uid Philip R. Zimmermann <prz@mit.edu>
uid Philip R. Zimmermann <prz@acm.org>
uid [jpeg image of size 3457]
sub 3072g/A8E92834 2001-01-04

我们可列表所有的公钥。

发布、查找、接收公钥

非对称加密中,需要公开自己的公钥,便于别人进行加密和签名验证,同时,也可获取别人的公钥加密文件、文本给别人,或者验证别人的签名。

发布公钥

公钥的发布有如下两种方式

  • 发布到 KeyServer
  • 通过 export public key,然后通过其他介质传递给别人(例如,U 盘、网络等)

发布到 KeyServer

可以使用如下命令,发布 GPG PUBLIC KEY 到 KeyServer

1
$ gpg --send-keys <UID> --keyserver hkp://keyserver.ubuntu.com:80

其中 UID 为上述通过 ‘’gpg –gen-key’’ 命令生成的公钥的 UID,上述为 ECA47B28

导出后发送给别人

可以使用如下命令,直接导出公钥为纯文本 (或者标准输出)

1
$ gpg -a --export <UID>

其中 UID 为上述通过 gpg –gen-key 命令生成的公钥的 UID,上述为 ECA47B28

如上命令会直接标准输出 GPG 公钥,当然也可通过 --output FileName 或者 > 写入到文件中

查找公钥

公钥可通过全球同步的 KeyServer 来查询到(在一个地方通过 send-keys 命令上去的公钥,经过一段时间同步后,可在全球各个服务器查到,我们可使用如下命令查找公钥

1
$ gpg --keyserver hkp://keyserver.ubuntu.com:80 --search <Email Address>

如上通过 Email Address 来查找,或者如下,使用 UID 来查找:

1
$ gpg --keyserver hkp://keyserver.ubuntu.com:80 --search-key <UID>

查找到后,可通过列表 id,直接下载,完成接收公钥

接收公钥

使用如上 --search-key 查找公钥或者通过多上述 --export 导出的公钥,使用 --import 导入, 如下:

1
2
3
4
5
$ gpg --export -a <UID> > pub.key

# 如上为 a 服务器进行操作,如下为 b 服务器进行操作,而且 b 服务器已接收到来自 a 服务器的 pub.key

$ gpg --import pub.key

如上即可导入公钥

加密、解密

加密

我们使用别人的公钥,可对文本加密,加密后的文本,只有该公钥对应的私钥才能解开,如下为加密方式:

1
$ gpg -r <UID> -e -a FileName

如上,使用 UID 用户的公钥,对 FileName 进行加密. (-e 表示 --encrypt, -a 表示, 使用 ASCII 文本输出

如上操作后,会默认生成 FileName.gpg 的加密后的文件。

解密

当公钥对应的私钥的所有者拿到了加密后的文件,就可使用如下命令对文件进行解密

1
$ gpg -d FileName.gpg

执行完成后会提供输入私钥的 passphrase, 验证通过后,解密的文件内容会标准输出,也可通过 --output xxx 设定标准输出到某些路径或文件。

签名、验证

当我们发布一个文件后,如何让别人认为这个发布的文件是我发布的呢?(如何证明,我的文件是我的文件)

我们可以使用自己的私钥进行签名,让别人使用我公开的公钥进行验证即可。

签名

有三种不同的签名方式:

  • sign
  • clearsign
  • detach-sign

如下分别说明

sign

1
$ gpg -s FileName

如上,直接对 FileName 进行 sign, 会生成 Filename.gpg 文件, 该文件中包含了 FileName 的内容(不过已无法直接读取(非 ASCII))

clearsign

1
$ gpg --clearsign FileName

如上,直接对 FileName 进行 clearsign, 会生成 FileName.asc 文件,该文件中包含了 FileName 的内容,并且可直接读

detach-sign

1
$ gpg --detach-sign FileName

如上,直接对 FileName 进行 detach-sign,会生成 FileName.sig 文件,该文件不包含 FileName 的内容,只用于进行 verify

验证

针对使用 signclearsign 的文件,直接使用如下命令即可进行 verify

1
$ gpg --verify FileName.asc / FileName.gpg

如下为一次正常的验证结果:

1
2
gpg: Signature made Mon Jul 25 08:56:40 2016 EDT using RSA key ID DAB60F2E
gpg: Good signature from "Foker (Just A Foker) <foker@gmail.com>"

还可对 asc 文件和 gpg 文件进行处理,获取源文件,如下:

1
$ gpg --output FileName -d FileName.asc / FileName.gpg

如上,即可直接通过 sign 的文件获取源文件。


针对 detach-sign 的文件,需要有源文件和 sig 文件,一起进行验证,如下:

1
$ gpg --verify hello.txt.sig hello.txt

扩展阅读: