GPG 入门指南
加密与签名在传输信息时,会面临两个典型的问题:
[*]如何保证发出的消息,只能被预期的接收人获取?
[*]如何保证收到的消息,确实由预期的发送人发出?
这两个问题不难理解。例如发送的邮件可能会被监听,诈骗分子可以冒充你老板。不一定是在网络上,在任何非面对面交流的情况下,都可能存在这两个问题。例如打仗时,情报可能被敌方监听窃取,收到的命令可能是被敌人冒充的。
对于第一个问题,可以通过加密来解决。就像战争电影中,双方会加密自己的情报和破解对方的情报。
那么如何进行加密呢?最容易想到的方法就是双方约定一套规则(加密算法),发送方将原始信息(明文)按照这套规则转换(加密)成别人看不懂的信息(密文)。其他人不知道这套规则,就无法获取原始信息。而接收人按照约定好的规则,则可以还原(解密)出原始信息。最简单的规则可以是将字母后移三位,例如将 hi 转换成 kl。这种规则很容易被人猜到,而且人类的脑洞是有限的,或者说优秀密码学家设计出的加密算法是有限的,很可能就英雄所见略同了。而且如果加密算法被想到,就只能再换一种加密算法,估计密码学专家的头发也不太够用。所以一般常用的加密算法都是公开的,再提供一个额外的保密的信息(密钥),解密的时候必须使用相同的密钥才能成功。例如提供一本书,发送方将信息转换为书中的页码,接收方找到每页第一个字即可还原信息。这就是常说的对称加密的基本思路,对称的意思是加解密双方需要具备相同的密钥,解密的人同时也可以加密信息。常见的对称加密算法有:AES、Twofish 等。
对称加密解决了消息本身不能被其他人获取的问题,但带来了一个新问题:密钥又该如何传输呢?为了让后续的消息能被安全的加密,通信双方需要以安全的方式(例如面对面)交换一个密钥,然后就可以使用这个密钥进行安全的通信了。这就给通信带了困难,很多时候可能不方便这样面对面的交流。更致命的是,如果需要与多个人通信,与每个人都要重复一遍这个过程,而且交换的密钥都不能相同。这样交换密钥和管理密钥的成本都很高,甚至是不可行的。
有对称加密,自然就有非对称加密,可以用来解决密钥交换的问题。非对称加密的密钥不是一个,而是一对。其中一个可以发布给所有人,用来加密信息,这个叫公钥。另一个只能自己持有,用来解密信息,这个叫私钥。他们就像一对钥匙和锁头,和生活中的锁头不一样,这里钥匙(私钥)只有一把,而锁头(公钥)到处都是。这些锁头可以发布给所有人,发送方把信息用锁头锁上再发送,最终只有钥匙的持有者可以解开这条消息。常用的非对称加密算法有:RSA、椭圆曲线算法等。
非对称加密看起来没什么问题了,那是不是就不需要对称加密了?因为非对称加密算法的计算一般都很复杂,性能远远不如对称加密,所以这两个结合才是最佳的选择:用非对称加密算法去加密对称加密算法的密钥,然后再用这个密钥使用对称加密算法去加密原始信息。发送信息的过程变成了:
[*]接收方有一对公钥和私钥,并将公钥广而告之所有人,例如挂在自己的个人网站上
[*]发送方使用对称加密算法加密原始信息
[*]发送方使用接收方的公钥加密上一步使用的密钥
[*]发送方将这两个信息一起发送给接收方
接收方收到消息后:
[*]使用自己的私钥解密出对称加密用到的密钥
[*]使用解密出来的密钥解密原始信息
这样就彻底保证了发出的信息只能被预期的接收人获取。至于公钥如何广而告之的问题,我们在后面的 GPG 使用中讨论。
非对称加密也可以反过来,使用私钥加密,同样只有对应的公钥才能解密。这样做一般不是为了保密,因为公钥已经广而告之,所有人都能解开。但是有另一个意义:可以用来做数字签名。发送方使用自己的私钥将信息加密(签名),接收方收到信息后,使用公钥解密(验证)得到原始信息。这样其他人没有发送方的私钥,如果冒充或篡改原始信息,接收方使用公钥验证时将会失败。实际使用时一般不会对消息全文进行签名,因为效率太低,只需要对消息的摘要进行签名,如果消息被篡改,摘要也会变化,验证同样会失败。发送信息的过程如下:
[*]发送方有一对公钥和私钥,并将公钥广而告之所有人
[*]发送方计算原始信息的摘要
[*]发送方使用自己的私钥加密摘要
[*]发送方将原始信息和加密后的摘要一起发送给接收方
接收方收到信息后:
[*]计算原始信息的摘要
[*]使用发送方的公钥解密发送方加密后的摘要
[*]验证两个摘要是否相同
至此我们已经介绍了加密和签名的基本概念,有了这两个概念配合使用,就能解决本文开通提到的两个问题。下面将会介绍如何通过 GPG 工具来实现这些。
什么是 GPG
GPG 可以分成两部分来看:
第一部分:GPG 是一个加密、解密、签名、验证工具。前面介绍了加解密的基本概念、相关的算法。但这些概念和算法并不能直接使用,而 GPG 就是一个使用这些算法,对信息进行加密、解密、签名、验证的工具。具体介绍见如何使用部分。
第二部分:GPG 还是一个密钥管理工具,可以用于管理自己的私钥,其他人的公钥,以及提供了一套公钥信任体系。前面加解密概念中提到,公钥要广而告之,GPG 可以帮助我们更加安全高效的交换公钥。具体介绍见管理密钥部分。
另外在使用 GPG 时,可能还会看到 PGP、OpenPGP 等名词,他们是什么关系?PGP (Pretty Good Privacy) 是最早的于 1991 年发布的此类工具。PGP 很好用,但他是商业软件。于是 GNU 计划在 1999 年发布了开源版本的 GNU Privacy Guard (GnuPG 或 GPG)。而 OpenPGP 是于 1997 年制定的一套标准,GPG、PGP 等工具都实现了这套标准。
如何使用
已经做了很多铺垫,接下来先看一下 GPG 是如何使用的。
下面的每一条命令都涉及很多可选参数可以组合使用,这也是命令行工具的灵活之处。不过初次接触可能会觉得很不友好,没有关系,只要了解即可,需要时可以通过 man gpg 快速查询。
这里涉及到的一些概念,将在基本概念中介绍。
生成密钥
命令:
gpg --gen-key
将会交互式的要求输入真实姓名、邮箱的信息。输入完成后将会生成一对密钥。
查看已有密钥
命令:
gpg <-k|-K> [--with-fingerprint] [--with-subkey-fingerprints] [--with-sig-list] [--with-sig-check]
gpg --fingerprint
gpg --list-sigs
参数说明:
[*]-k/--list-public-keys:查看公钥。
[*]-K/--list-secret-keys:查看私钥。
[*]--with-xxx:根据字面意思,将会额外打印一些信息,具体信息可以通过 man gpg 查看。
[*]--fingerprint:打印密钥的指纹,等价于 gpg -k --with-fingerprint。
[*]--list-sigs:打印密钥的签名,等价于 gpg -k --with-sig-list。
[*]key-id:仅打印指定的密钥。可选,否则打印所有密钥。如何选择一个密钥请参考:选择密钥
打印出来信息的含义,将在基本概念中进一步说明。
示例:
gpg -k
gpg -K
gpg --fingerprint
加密
命令:
gpg -r <key-id> [-o <output-file>] [-a] -e
参数说明:
[*]-r/--recipient:指定接受者的公钥 ID,消息将会使用这个公钥进行加密,也就是只有拥有这个私钥的人才能解密信息。可以指定多个,则多个接受者都能解密信息。
[*]-o/--outfile:指定加密后的信息输出到哪个文件。可选,如果不指定将会输出到标准输出。
[*]-a/--armor:将加密后的信息转为可打印的 ASCII 字符。可选,如果不指定将会输出二进制信息。
[*]-e/--encrypt:加密。相应的还有解密、签名、验证等参数,将在后面介绍。
[*]file:要加密的文件。可选,如果不指定将会从标准输入读取。
注意:只有 -r 指定的私钥才能解密信息,如果没有指定自己,则自己也无法解密。也可以仅指定自己,用于加密隐私文件。可以通过配置,加密时默认将自己包含在内,后面将会介绍。
示例:
gpg -r someone -o myfile.gpg -e myfile
echo 'some message' | gpg -r someone -ae
解密
命令:
gpg [-o output-file] -d
参数说明:
[*]-o/--output:指定解密后的信息输出到哪个文件。可选,如果不指定将输出到标准输出。
[*]-d/--decrypt:解密。
[*]input-file:待解密的文件。可选,如果不指定将尝试从标准输入读入。
解密时没有指定私钥,因为一般加密信息中会包含使用的公钥 ID,GPG 将会自动在本地寻找对应的私钥,如果找不到将会解密失败。
示例:
gpg -o myfile -d myfile.gpg
echo 'some message' | gpg -r someone -e | gpg -d
签名
命令:
gpg -u <key-id> [-o output-file] [-a] <-s|-b|--clearsign>
参数说明:
[*]-u/--local-user:指定用来签名的密钥 ID,签名后,只有对应的公钥可以验证成功。
[*]-s/--sign:签名。
[*]--clearsign:签名并保持原始信息。-s 签名后,信息将会打包成 GPG 的格式。虽然没有加密,但仍需 GPG 命令才能解析查看。--clearsign 签名,会保持原始信息,额外附加一段签名信息,这样任何人都可以直接看到原始信息,需要验证的再使用 GPG 验证。
[*]-b/--detach-sign:分离签名。如果是文本信息不想修改原始信息,可以使用 --clearsign 保持原始信息。而对于二进制文件,则可以使用 -b 创建一个独立的签名文件。
这三种签名方式,实际动手操作一下就知道他们的差别了。
示例:
echo 'some message' | gpg -u myself --clearsign
gpg -b file.zip
验证
命令:
gpg <--verify |-d >
参数说明:
[*]--verify:验证签名是否正确。对于 -s 的签名,仅会验证签名是否正确,不会输出原始信息。
[*]-d/--detach-sign:验证签名是否正确。对于 -s 的签名,还会输出原始信息。
[*]file...:对于 -s/--clearsign 的签名,输入为签名文件。对于 -b 的签名,第一个参数为签名文件,第二个参数为被签名的数据,如果不指定第二个参数,将会自动尝试去掉后缀作为原始文件名。
验证签名同样不用指定公钥。GPG 将会在本地的公钥中寻找,如果无法找到,将会验证失败。
示例:
echo 'some message' | gpg -u myself -s | gpg -d
gpg --verify file.zip.sig
组合
为了更清楚的说明每个功能的用法,上面将每个参数分开介绍的,这些参数可以组合使用。例如实际使用时,可能同时需要签名和加密:
echo 'some message' | gpg -u myself -r someone -ase
基本概念
查看密钥列表时,会有类似如下输出,在介绍如何管理密钥前,先了解一下这些输出信息的含义。这个输出在每个版本有可能会不同。
$ gpg -k --with-fingerprint --with-subkey-fingerprint --with-sig-list
pub rsa4096 2021-11-22
B69B C896 53B7 D844 C67F137C 3684 CA4A 7AF9 0D04
uid Some One (Just an example.) <example@mail.com>
sig 3 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
sub rsa3072 2021-11-22
FED2 E682 2A8A E366 36944D72 51AE 0444 47EA C691
sig 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
sub rsa3072 2021-11-22
B471 1661 FE14 AE6A 3907DD65 3E40 85A7 CDAF 19EF
sig 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
$ gpg -K --with-fingerprint --with-subkey-fingerprint --with-sig-list
sec rsa4096 2021-11-22
B69B C896 53B7 D844 C67F137C 3684 CA4A 7AF9 0D04
uid Some One (Just an example.) <example@mail.com>
sig 3 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
ssb rsa3072 2021-11-22
FED2 E682 2A8A E366 36944D72 51AE 0444 47EA C691
sig 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
ssb rsa3072 2021-11-22
B471 1661 FE14 AE6A 3907DD65 3E40 85A7 CDAF 19EF
sig 3684CA4A7AF90D04 2021-11-22Some One (Just an example.) <example@mail.com>
密钥类型
每个密钥开头都会有这样几个字母:pub/sub/sec/ssb,表示这个密钥的类型。
在非对称加密算法中,密钥都是成对出现的。pub 和 sec 就分别表示这一对密钥的公钥和私钥,而 sub 和 ssb 则分别表示一对子密钥的公钥和私钥。
为什么会存在子密钥?理论上只需一对主密钥,就可以完成所有加密和签名的需要了。而 GPG 支持一对主密钥和若干对子密钥,主要是为了密钥本身的安全考虑。例如需要在多台设备上进行签名和加密操作,如果在每个机器上都使用主密钥,一旦丢失,则所有设备上的信息都将可以被解密。而且除了撤销整个主密钥之外,没有任何其他办法来止损。而如果将主密钥保存在安全的地方,仅在必要的时候使用,其余机器上都使用子密钥。那么如果一台机器上的子密钥丢失,只有这台机器上的信息可能被泄露。而且无需撤销整个主密钥,只需要使用主密钥撤销这个子密钥,然后重新创建一个子密钥即可。
另外每个子密钥也可以选择不同的加密算法,可以指定不同子密钥来选择不同的加密算法来进行加解密。
密钥用途
每个密钥旁边都会有方括号包围的一个或多个字母,可能取值有 E/S/C/A,表示这个密钥的用途。每个值的含义如下:
[*]Encryption:加密。
[*]Signing:签名。
[*]Certification:认证其他子密钥或 uid。
[*]Authentication:身份认证,例如用于 SSH 登录。
其中前三个较为常用。如果使用 gpg --gen-key 生成的密钥,默认就会生成一对主密钥 和一对子密钥 。这样将会使用主密钥进行签名,使用子密钥进行解密。
我们也可以自行添加其他子密钥或者修改已有子密钥用途,具体操作方式将在编辑密钥中介绍。
加密算法
pub 等标识后面紧跟着的是密钥的加密算法,例如 rsa3072 表示密钥长度为 3072 位的 RSA 算法。当前版本 (2.2.19) 使用 gpg --gen-key 生成的默认密钥使用的就是 3072 位的 RSA 算法。支持的其他算法可以输入 gpg --version 查看。注意这里指的是非对称加密的算法,对称加密使用的算法可以在每次加密时通过参数指定不同算法。
如果想要生成其他算法的主密钥,可以使用 gpg --full-gen-key 命令。这里也体现了使用子密钥的灵活性,例如我们可以使用 4096 位的主密钥,更加安全。然后使用 3072 位的子密钥用于加密和签名,更加高效。如果未来 3072 位密钥不够安全时,只需要重新生成 4096 位的子密钥,而不用重新生成主密钥。
指纹
每个密钥或子密钥下面都有一行由 10 组 4 个字符组成的信息。这是使用 SHA-1 算法对整个密钥计算出来的摘要,共 160 位,20 字节,一般表示为 40 个十六进制数,就是现在看到的。这个指纹可以用于唯一的标识一对密钥。
User ID
每个主密钥可以有一个或多个 uid,用于标识用户身份。格式为 Real Name (Comment) <Email>。
有效性
每个 uid 旁边的方括号内,标识了这个 uid 的有效性。
如果新导入了一个公钥,默认将会显示 。这是因为任何人都可以声称自己是任何人,所以在导入公钥时,需要想办法验证他的有效性。
第一种验证方式是直接当面交换公钥,绝对安全。但很多时候这不可能。
另一种方式是验证指纹,可以使用 gpg --fingerprint 命令将指纹打印出来,然后通过打电话或者其他可靠的方式确认指纹是否正确。因为指纹是通过安全散列算法对整个密钥信息计算的摘要,很难构造出(碰撞)两个摘要相同的密钥,所以一旦确认指纹没错,就可以认为整个密钥是有效的。
确认之后,需要将密钥标识为有效的,标识的方式就是使用自己的密钥对公钥进行签名,这样 GPG 就认为这是个有效的密钥了。
注意签名和有效性都是针对 uid 的。例如一个人声称了两个身份,第一个 uid 说他叫特朗普,第二个 uid 说他是前美国总统。你想尽一切办法最终只验证了他确实叫特朗普,但不知道是不是那个美国总统。那就可以仅对第一个 uid 签名。
如何对 uid 签名将会在编辑密钥具体介绍。
信任网络
事实上,几乎很难直接验证每个密钥的有效性,这时可以利用 GPG 的信任网络来间接验证密钥的有效性。
简单来说就是如果我确认了某个密钥的主人确实是美国总统,而我信任他不会乱认人(但愿吧)。那么如果这个密钥对某个叫做国务卿的密钥进行了签名,我就也认为这个国务卿确实是有效的,而不用亲自去认证。
信任分为几个不同的等级:
[*]ultimate:终极信任。一般只应该对自己的密钥进行终极信任,可以理解为所有信任链的根节点。
[*]full:完全信任。对于这个人签名的其他密钥,我也认可。
[*]marginal:信了,但没完全信。这个人签名过的密钥,我不一定认可,但如果三个这样的人都签了,那我就信了。
[*]never:不信任。这个人对其他密钥的签名,我一律视而不见。
需要注意信任和有效性不一定有关系。信任表示的是对这个密钥签名其他密钥的信任程度,而有效性是对这个密钥本身的验证。例如我知道某个密钥确实是特朗普的,他是有效的。但我觉得这个人满嘴跑火车,他签名的其他密钥我一概不认。
有了信任网络,一个密钥有效的条件就变成了:被一个 full 签名或三个 marginal 签名,同时这个签名传递的路径距离我(ultimate)的长度不超过 5。这些值都可以修改,具体可以参考 man gpg。更具体的说明可以参考 The GNU Privacy Handbook。
如何修改信任值将在编辑密钥具体介绍。
自签名和交叉签名
除了通过验证其他人对 uid 的签名外,所有 uid 和子密钥都还需要有自签名。否则攻击者就可以绕过公钥的主人插入一个自己的子密钥,来冒充别人。而如果要求所有的 uid 和子密钥都经过主密钥自签名,则冒名顶替的 uid 和子密钥因为没有主密钥的私钥,将无法蒙混过关。
对于子密钥,除了自签名外,还需要和主密钥进行交叉签名。否则攻击者将其他人的子密钥插入到自己密钥中,就可以声称某个签名是自己发出的。而如果要求子密钥和主密钥进行交叉签名,则攻击者因为无法获取子密钥的私钥对自己的主密钥进行签名,将无法蒙混过关。
撤销
GPG 在更新密钥的时候,对 uid 的签名、uid、子密钥等都会采用合并的方式处理。因此如果一个签名、uid 或者子密钥不再使用了,将其删除是没有意义的,因为导出给其他人或者密钥服务器,合并后原来的签名、uid 和子密钥还是存在的。所以如果不再使用,我们需要撤销它。
其实无论撤销什么,本质都是在撤销签名。撤销对 uid 的签名,将会生成一条撤销签名的信息,标记原来的签名无效。而如果撤销的是 uid 或子密钥,将会撤销对 uid 或子密钥的自签名,使原来的 uid 或子密钥失效。
撤销的密钥只是不能用于新的加密和签名。但依然可以解密和验证已有的信息,只是会提示已经被撤销。
当然也可以撤销整个主密钥,这些都将在编辑密钥中介绍。
有效期
如果有必要,可以分别对主密钥和每对子密钥设置有效期。有效期可以随时修改,过期前重新设置有效期即可,无需重新生成新密钥。
过期的密钥只是不能用于新的加密和签名。但依然可以解密和验证已有的信息,只是会提示过期。
设置有效期的安全性,并不在于定期更换密钥,实际上 GPG 官方文档也没有推荐更换密钥,而是建议在到期前续期。也不在于担心密钥泄露,因为如果密钥泄露,获取私钥的人也可以随时修改有效期。有效期的意义是在于让持有公钥的人,记得及时更新公钥信息。例如如果密钥已经泄露了,但没有设置有效期。其他人如果没有想到要主动更新公钥,可能永远也发现不了密钥已经泄露了。那么获取了私钥的人冒充你进行签名,依然会被其他人认可。
如何设置有效期将在编辑密钥介绍。
选择密钥
前面介绍的命令中,已经出现了很多次 key-id 的占位符。其实这里用 key-id 并不恰当,只是没有更好的名称来描述。实际使用中,可以有多种方式来选择一个密钥。常用的有:
[*]指纹:就是那 40 个十六进制数。这是 GPG 推荐的,最不容易重复的方式,缺点是太长。
[*]Key ID:有两种格式
[*]短 ID:指纹的后 8 位,这种已经不推荐了,因为有被碰撞的风险
[*]长 ID:指纹的后 16 位
[*]精确匹配的邮箱:<xxx@xxx>
[*]部分匹配的邮箱:@xxx
[*]部分匹配 uid:someone,不区分大小写
所有需要选择某个 key 的地方,都可以使用上面这些形式。注意除了指纹和 Key ID 外,其他都可能匹配到多个,将会选择第一个使用。
除了这些基本的匹配外,对于 Key ID 和指纹,还有个特殊的用法:!。
前面介绍过 GPG 支持一对主密钥和若干对子密钥。而如果主密钥支持 ,某个子密钥也支持 。那么签名时将会使用哪个呢?答案是使用子密钥。在选择密钥时,GPG 会自动选择一个支持对应能力的子密钥,如果存在多个,则选择较新的一个。那么如果就是要使用某个特定的主密钥或子密钥呢?这时就可以在 key ID 或指纹后面加上 !,强制使用这个密钥,而不要自动推算。
这种用法还可以用在导出密钥时,仅导出某个子密钥或主密钥。
管理密钥
导出密钥
命令:
gpg [-a] [-o output-file] [--export-options <option>[,option...]] <--export|--export-secret-keys|--export-secret-subkeys>
参数说明:
[*]--export:导出公钥。
[*]--export-secret-keys:导出私钥。
[*]--export-secret-subkeys:导出子密钥。
[*]--export-options:导出选项,逗号分割,常用的有:
[*]backup:导出用于备份。会将信任值、本地签名等一起导出。
[*]export-clean/export-minimize:参考:清理签名
[*]key-id:如果不指定将会导出所有公钥或私钥,如果指定仅会导出指定的密钥,使用 ! 可以仅导出主密钥或子密钥。
导入密钥
命令:
gpg --import [--import-options <option>[,option...]]
参数说明:
[*]--import:导入密钥。
[*]--import-options:导出选项,逗号分割,常用的有:
[*]restore:恢复,与导出选项的 backup 对应。
[*]import-show:回显导入的密钥信息。
示例:
gpg --import someone.gpg
删除密钥
命令:
gpg <--delete-keys|--delete-secret-keys|--delete-secret-and-public-keys> <key-ids...>
参数说明:
[*]--delete-keys:删除公钥。
[*]--delete-secret-keys:删除私钥。
[*]--delete-secret-and-public-keys:同时删除私钥和公钥。
示例:
gpg --delete-keys someone
gpg --delete-secret-and-public-keys someone
密钥服务器
通过手动的导入、导出密钥,当密钥比较多时会比较麻烦。更关键的是不方便密钥的更新。例如已经通过手动导出的方式将公钥发布给了很多人,一旦公钥发生变动(例如获得了一个新签名、撤销了一个子密钥等),就需要重新导出,然后找到每个持有公钥的人,要求他更新一下。而 GPG 可以通过密钥服务器帮助我们完成这些,使用起来和导入导出差不多,只不过导出到密钥服务器、从密钥服务器导入而已。
命令:
gpg [--keyserver <key-server>] [--keyserver-options <option>[,option...]] <--send-keys|--recv-keys|--refresh-keys|--search-keys>
参数说明:
[*]--send-keys:将密钥发送到密钥服务器。
[*]--recv-keys:从密钥服务器接收密钥。
[*]--refresh-keys:从密钥服务器更新本地密钥。
[*]--search-keys:从密钥服务器搜索密钥。
[*]--keyserver:指定一个密钥服务器,大部分密钥服务器之间都会同步密钥。
[*]--keyserver-options:导入或导出密钥时的一些选项,支持所有 --import-options 和 --export-options,另外还支持像 http-proxy 来指定代理等。
示例:
gpg --search-keys EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
gpg --recv-keys EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
gpg --send-keys B69BC89653B7D844C67F137C3684CA4A7AF90D04
编辑密钥
使用 gpg --edit-key <key-id> 命令,可以交互式的编辑一个密钥。输入 help 可以查看帮助,输入 save 可以保存并退出编辑,输入 quit 可以不保存退出编辑。
下面是一些常用操作的介绍。
对 uid 签名
使用 sign 或 lsign 可以对 uid 进行签名。两者的区别是,sign 的签名可以被导出和上传到密钥服务器,而 lsign 的签名仅可以在本地查看和生效。一般我们验证了一个人的身份,如果没有得到公钥主人的允许,应该优先使用 lsign 进行签名。
如果需要撤销一个签名,可以使用 revsig 命令。如果签名还没有发布(上传到密钥服务器或者导出给其他人),也可以使用 delsig 直接删除。
这里的签名将会使用默认的私钥,如果没有指定将会使用第一个可用的私钥。或者也可以在 --edit-key 时通过 -u 参数指定一个私钥。
如果不指定某个 uid,将会对所有 uid 签名。也可以先通过 uid 命令选择某个或某些 uid,再进行签名。uid 0 将取消选择所有 uid。
信任密钥
使用 trust 命令可以设置对密钥的信任值。关于信任值的解释和每个信任值的含义参考:信任网络。
信任值是一个很主观的事情,因此信任值仅会保存到本地的数据库中,不会被导出或上传到数据库中。除非使用 --export-options backup 选项导出。
uid
使用 adduid 命令可以创建一个新的 uid。并可以使用 uid 命令选择一个 uid 后,使用 primary 命令指定一个主 uid。
如果某个 uid 不再使用,可以先使用 uid 选中,再使用 revuid 命令撤销。如果 uid 还没有发布,也可以使用 deluid 直接删除。
子密钥
使用 addkey 命令可以创建一对子密钥。创建过程中可以交互式的选择使用的算法、用途等。
如果某个子密钥不再使用,可以先使用 key 选中,再使用 revkey 命令撤销。如果子密钥还没有发布也没有使用过,可以使用 delkey 直接删除。但要注意,如果删除,使用此子密钥加密过的信息将永远无法解密!
撤销密钥
密钥服务器为了防止被篡改,被设计为只增不删的形式。也就是说如果密钥一旦上传到服务器,将永远不能删除。那么如果主密钥丢失或者泄露了,我们只能撤销它。
不选择任何子密钥,执行 revkey 命令,将撤销整个密钥。撤销之后,重新将密钥发送到密钥服务器,密钥服务器上的密钥也会被撤销。其他人从密钥服务器更新之后,将会知道密钥已经被撤销,以后就不会再使用此密钥进行加密,也将不会信任此密钥的签名。
上面的操作必须在我们拥有私钥的情况下进行,而如果私钥丢失了,我们就永远无法更新密钥的状态了。所以为了避免出现这种情况,一般建议生成一个撤销证书,和私钥分开保存。撤销证书本质上就是一个撤销密钥的签名。如果私钥丢失,需要将撤销证书导入,并发送到密钥服务器,密钥服务器上的公钥也将被撤销。
[*]生成撤销证书:gpg [-a] [-o output-file] --gen-revoke <key-id>
[*]通过导入撤销证书撤销密钥:gpg --import
[*]发布撤销密钥:
[*]如果之前使用了密钥服务器,则发布到密钥服务器即可:gpg --send-keys <key-id>
[*]如果是手动导出的方式,则再次导出并发送给其他人导入即可:gpg --export-keys <key-id>
注意: 密钥一旦撤销将无法恢复。
其实在拥有私钥的情况下,无需撤销证书即可撤销整个密钥。撤销证书单独保存的意义在于,他可以保存在比私钥稍低一个安全等级的地方。因为一旦私钥泄露,以往的信息都将泄露。而如果安全证书泄露,只会使密钥失效,不会泄露任何信息。最多是需要重新生成一对密钥发布给其他人,比较麻烦而已。例如撤销证书可以放在信任的人那里备份,而私钥只能放在不会被任何人获取的地方备份。
过期时间
使用 expire 命令可以设置密钥的过期时间。默认会设置主密钥的,使用 key 选中子密钥后,将设置选中密钥的。
密码
使用 passwd 命令可以修改密钥的密码。
清理签名
如果 uid 上收集的很多签名无效了,例如撤销了的签名,不会删除原有的签名,而是在生成一条撤销的信息。可以使用 clean 命令,清除所有无效的签名。
如果更进一步,不需要所有其他人的签名,则可以使用 minimize 清除自签名外的所有签名。
配置文件
前面的介绍中可以看到,很多时候我们都需要通过 -u 参数指定使用哪个密钥进行签名。还有加密时如果不指定自己,以后将会无法解密自己发出的信息。我们希望将这些参数默认配置下来,不用每次都在命令行中输入。
GPG 命令中的所有长参数 (--开头的参数) 都可以配置在 ~/.gnupg/gpg.conf 中,这样每次执行 GPG 命令时,都会默认带上这些参数。
例如指定默认的用于签名的密钥,指定每次加密都默认也加密给自己等等。
示例:
default-key B69BC89653B7D844C67F137C3684CA4A7AF90D04
encrypt-to B69BC89653B7D844C67F137C3684CA4A7AF90D04
使用场景
GPG 主要用于信息传输过程中的加密。对于大多数人来说,既没有什么恐怖袭击计划需要讨论,也没有几百亿的生意要谈,所以可能用到的机会不多。不过 GPG 也可以用于给自己的文件进行加密,例如将敏感文件加密后再通过网盘备份等。
GPG 的签名功能在很多地方都会用到。例如大部分 Linux 发行版的包管理系统,都会使用 GPG 签名来保证包在分发的过程没有被篡改。所以各种 Linux 发行版一般都在世界各地存在大量的镜像源,我们可以放心的享受这些镜像源的便利,不是靠对镜像源的信任来保证的,而是靠 GPG 签名来保证的。此外还可以使用 GPG 对 Git 的提交和标签进行签名等。
https://my.oschina.net/u/4685149/blog/5322706
页:
[1]