简述

GnuPG,简称GPG,是一个密码学软件,用于加密、签名通信内容及管理非对称密码学的密钥。GnuPG 是自由软件,遵循 IETF 订定的 OpenPGP 技术标准设计,并与 PGP 保持兼容。

功能 能力 说明
[C] Certificating 认证 / 给其它证书签名
[S] Signing 签名
[A] Authenticating 身份验证
[E] Encrypting 加密

GPG 密钥的能力中, [C]、[S]、[A] 均属于签名方案,只有 [E] 是加密方案。
一个主密钥,可以绑定若干个子密钥;这些子密钥有的具备加密功能,有的具备签名功能。
可以理解为,主私钥就是用来生成多个子密钥来使用,而子密钥丢失可以随时废弃,主密钥生成新的子密钥来使用。

安装

官方下载地址:https://www.gnupg.org/download/index.en.html

centOS

CentOS 默认已经安装了 gpg2

1
gpg --version

如果需要手动安装,在http://rpmfind.net/ 搜GPG下载:

1
2
wget http://rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/gnupg2-2.0.22-5.el7_5.x86_64.rpm
rpm -ivh gnupg2-2.0.22-5.el7_5.x86_64.rpm

macOS

macOS 下安装,可以选择图形界面和命令行两种形式:

1.GPGTools 包含图形界面,下载地址:https://gpgtools.org/

可以直接安装 GPGTools,就可以包含命令行工具,本例安装 GPGTools,但是使用它的命令行进行操作。

macOS

2.命令行工具安装:

1
brew install gpg

生成私钥

安装后使用命令:gpg进行后续的操作,生成私钥使用命令:

1
gpg --gen-key

只需输入姓名、邮件即可生成,输出如下,私钥文件生成目录:/Users/{user_name}/.gnupg/openpgp-revocs.d/
需要关注用户ID,在操作时很多地方需要用到用户ID,我这里生成的测试用户ID:9F4B9BCF408B96C68E0645805BDF50B192200806

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
gpg (GnuPG/MacGPG2) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

注意:使用 “gpg --full-generate-key” 以获得一个全功能的密钥生成对话框。

GnuPG 需要构建用户标识以辨认您的密钥。

真实姓名: liukaitest
电子邮件地址: liukaitest@163.com
您选定了此用户标识:
“liukaitest <liukaitest@163.com>”

更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)? o
我们需要生成大量的随机字节。在质数生成期间做些其他操作(敲打键盘
、移动鼠标、读写硬盘之类的)将会是一个不错的主意;这会让随机数
发生器有更好的机会获得足够的熵。
我们需要生成大量的随机字节。在质数生成期间做些其他操作(敲打键盘
、移动鼠标、读写硬盘之类的)将会是一个不错的主意;这会让随机数
发生器有更好的机会获得足够的熵。
gpg: 吊销证书已被存储为‘/Users/liukai/.gnupg/openpgp-revocs.d/9F4B9BCF408B96C68E0645805BDF50B192200806.rev’
公钥和私钥已经生成并被签名。

pub rsa3072 2023-01-03 [SC] [有效至:2025-01-02]
9F4B9BCF408B96C68E0645805BDF50B192200806
uid liukaitest <liukaitest@163.com>
sub rsa3072 2023-01-03 [E] [有效至:2025-01-02]

列出私链

1
gpg --list-secret-keys

输出公钥

项目应用中,需要将公钥输出给其它机器使用。公钥文件(.gnupg/pubring.gpg)以二进制形式储存。
执行命令,需要用到上面生成的用户ID

1
gpg --armor --output public-key.txt --export [用户ID]

参数说明

--armor:参数可以将其转换为ASCII码显示
--output:参数指定输出文件名(public-key.txt)
--export::指定哪个用户的公钥

导入、导出密钥

导出公钥

导出为公钥文件,--output 参数可以省略,默认文件名也是 public-key.txt

1
gpg --armor --output public-key.txt --export [用户ID]

导出私钥

导出需要输入密钥密码。

1
gpg -a -o private-file.key --export-secret-keys [用户ID]

导入公钥、私钥

有两种方式:

  1. 从远GPG公钥服务器导入
  2. 从公钥文件导入

从公钥文件导入,这种方式很简单,做开源项目,很多项目会在README中说明公钥HASH,就可以拿着HASH或uid从远程导入到本地。

1
gpg --recv-keys <keyid/uid>

通过文件导入

1
gpg --import [密钥文件]

签名

签名的数据内容有两种形式:

  1. 二进制
  2. ASCII

签名会生成签名文件或将签名和文件合并成一个文件。

1.签名数据、生成新文件:原文件和签名生成在同一个文件中

生成结果为二进制的签名文件:

1
gpg --sign demo.txt

生成新文件:demo.txt.gpg,内容为二进制。

生成 ASCII 内容的签名文件。文件名为xxxx.xxx.asc。签名信息添加在文件尾

1
gpg --clear-sign 123.txt.gpg

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

123123
1231231
12
3123
12
312323
123123123
12
3
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCAAdFiEEeahrV6DakT8NdrWs1m5Gkkp6RHUFAmOz+Y4ACgkQ1m5Gkkp6
RHXWNQv/fbhBLdmuvw41nrtqK6exJ6MxX0Kso5NXOp5PleKc5baParHgjEvXEey8
6/krmom2K0W9tQQ0cXQkagDqRIhpSNEr+QiG1OZb6tLRLbFPqYCEU9dugc426/xO
4s9/gaLscYo5X8aoOkvO2cdlP/cYNPmI3CUGXJqy9KGVqmfvl8iTbg2LCEmAYqQu
uQdS42XXH8qieEvjCaBj1aC06NVsLmydwlFu3Zah9HVGj2IQmBTXjboz+FrYJ4q+
iVMuOH4b02dg7Il0h8u636EeUwNVkX+4jJB3+DPenQ37FOxp1vv/miKM4ace7SjX
nmMi+oAJnB577dEaOrxnP6wOKcWEd6/GJMRvb1FcLElu46Bsz5UhoQwRmGyuCrNL
2M6j2j4MHzNv4XBLaFv7Lo59TjZVZrghwblL3Y82zcDsak4kBu/GwZCS9/WANjSs
sPFZSVpwe5bg6cFLN35GAcUB590UCbOtN2SMvdWLWeTw4bSeyqcA8wRi0GTU31Tc
yrVpIRH4
=oMT2
-----END PGP SIGNATURE-----

以上两个命令都是将签名添加到文件中。

2.签名数据、生成新文件:sig、asc

1.生成签名,基于二进制格式

如果想生成单独的签名文件,与文件内容分开存放,可以使用detach-sign参数。

1
gpg --detach-sign demo.txt

2.生成签名,基于 ASCII 格式

这个命令会在当前目录下生成 xxxx.xxx.sig 这是文件的签名。采用二进制储存。

1
gpg --detach-sign --armor demo.txt

这个命令会生成文件的ASCII签名: demo.txt.asc。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-----BEGIN PGP SIGNATURE-----

iQGzBAABCAAdFiEEeahrV6DakT8NdrWs1m5Gkkp6RHUFAmOz+vUACgkQ1m5Gkkp6
RHVfKQv8CptzZlVqHoxq7TpGeg0kuB7WAtnG5yaHqRCWmGAI6RdMa6o6MI/RchtZ
CvBZRZjm4U228cUmN1/pl/wwI91HL97tei/NZ65ke/KgcEnw+HrluY+5b8j7SLug
XambZRlfFkdjTuwGM1zgaIhcBpTG4tX+pURGtdGRp5jTzNyWP6vVq80oXte85o/N
aZV/GEa5UOgigPnEK09DP3yTsHxhw8y2Rc8kDS5P1AWeE37dxO3NU1NzkWOmct7P
a4g+1cTxL2o3hXCt+TYCejqduKLXJjZLJRlU+Kie+nanEH868GN+qGeCOQN2eN3K
5E/sZzR7A3XTNT9gLYrtr7uRlz7+iU4vYsL5SvyB18I84T7Fqa8qM5s9KMIh7wsL
GlHcoE7H7zOkES3U0RyZWTYHrzJ/h8bCm6ErGy4meqWZRzQTgGMpWlAUvx9rU6iS
ZgwWDgc2qLPIEi0PhD6rVl9Kx1Pr3Ai5XJCtbBn41VK5B5Y6tXqheKXoo6n6lEBj
EmTuKvec
=OduX
-----END PGP SIGNATURE-----

3.验证签名 gpg --verify

新版本不需要 --output 参数,但是原文件必须在当前目录下

1
2
3
gpg --verify demo.txt.gpg
gpg --verify demo.txt.asc
gpg --verify demo.txt.sig

结果:

1
2
3
4
gpg: 假定被签名的数据在‘demo.txt’
gpg: 签名建立于 二 1/ 3 17:52:53 2023 CST
gpg: 使用 RSA 密钥 79A86B57A0DA913F0D76B5ACD66E46924A7A4475
gpg: 完好的签名,来自于 “liukai <liukaitest@gmail.com>” [绝对]

4.签名+加密

命令:

1
gpg --local-user [发信者ID] --recipient [接收者ID] --armor --sign --encrypt demo.txt

参数说明:

--local-user:参数指定用发信者的私钥签名
--recipient:参数指定用接收者的公钥加密
--armor:参数表示采用ASCII码形式显示
--sign:参数表示需要签名
--encrypt:参数表示指定源文件

发信者ID、接收者ID形式:DF9B9C49EAA9298432589D76DA87E80D6294BE9B

5.验证签名

收到别人签名后的文件,需要用对方的公钥验证签名是否为真。verify参数用来验证。

1
gpg --verify demo.txt.sig demo.txt

结果

1
2
3
gpg: 签名建立于 二  1/ 3 16:32:41 2023 CST
gpg: 使用 RSA 密钥 79A86B57A0DA913F0D76B5ACD66E46924A7A4475
gpg: 完好的签名,来自于 “liukai <liukaitest.asho@gmail.com>” [绝对]

总结

主密钥拥有所有的功能,但是在使用上一般不直接使用主密钥,而是多个生成子密来使用。

参考文档

https://gnupg.org/