xref: /linux/Documentation/translations/zh_CN/process/maintainer-pgp-guide.rst (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1.. SPDX-License-Identifier: GPL-2.0
2.. include:: ../disclaimer-zh_CN.rst
3
4:Original: Documentation/process/maintainer-pgp-guide.rst
5
6:翻译:
7
8 司延腾 Yanteng Si <siyanteng@loongson.cn>
9
10:校译:
11
12
13===================
14内核维护者 PGP 指南
15===================
16
17:作者: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
18
19本文档面向 Linux 内核开发者,特别是子系统维护人员。文档中含有Linux 基金
20会发布的更通用的 `保护代码完整性`_ 指南中讨论的内容子集。阅读该文档,以更
21深入地讨论本指南中提到的一些主题。
22
23.. _`保护代码完整性`: https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md
24
25PGP 在 Linux 内核开发中的作用
26=============================
27
28PGP 有助于确保 Linux 内核开发社区产出代码的完整性,并在较小程度上,通过
29PGP 签名的电子邮件交换,在开发者之间建立可信的交流渠道。
30
31Linux 内核源代码主要有两种(维护)方式:
32
33- 分布式源仓库 (git)
34- 定期发布快照 (tarballs)
35
36git 仓库和 tarball 都带有创建官方内核版本的内核开发者的 PGP 签名。这
37些签名提供了加密保证,即保证 kernel.org 或任何其他镜像提供的可下载版本
38与这些开发者在其工作站上的版本相同。为此:
39
40- git 仓库在所有标签上提供 PGP 签名
41- tarball 为所有下载提供独立的 PGP 签名
42
43信任开发者,不要信基础设施
44--------------------------
45
46自从 2011 年 kernel.org 核心系统遭到入侵以来,内核存档项目的主要运行原
47则就是假定基础设施的任何部分都可能随时受到入侵。因此,管理员特意采取措施,
48强调必须始终信任开发者,不能信任代码托管基础设施,无论后者的安全实践有多好。
49
50上述指导原则正是需要本指南的原因。希望确保通过对开发者的信任,我们不会简
51单地将未来潜在安全事件的责任归咎于其他人。目的是提供一套指导开发者可以用
52来创建安全的工作环境并保护用于建立 Linux 内核本身完整性的 PGP 密钥。
53
54PGP 工具
55========
56
57使用 GnuPG 2.2 或更高版本
58-------------------------
59
60默认情况下,你的发行版应该已经安装了 GnuPG,你只需要验证你使用的是相当新的
61版本即可。要检查,请运行::
62
63    $ gpg --version | head -n1
64
65如果你有 2.2 或更高版本,那么你就可以开始了。如果你的版本早于 2.2,则本指
66南中的某些命令可能不起作用。
67
68配置 gpg-agent 选项
69~~~~~~~~~~~~~~~~~~~
70
71GnuPG agent是一个辅助工具,每当你使用该命令时,它都会自动启动gpg,并在
72后台运行,目的是缓存私钥密码。你应该知道两个选项,以便调整密码何时从缓存
73过期:
74
75- ``default-cache-ttl`` (秒): 如果在生命周期结束之前再次使用相同的
76  密钥,倒计时将重置为另一段时间。默认值为 600(10 分钟)。
77- ``max-cache-ttl`` (秒): 无论你自输入初始密码以来多久使用过密钥,
78  如果最大生存时间倒计时结束,你都必须再次输入密码。默认值为 30 分钟。
79
80如果你发现这些默认值太短(或太长),你可以编辑 ``~/.gnupg/gpg-agent.conf``
81文件以设置你自己的值::
82
83    # 常规ttl设置为30分钟,最大ttl设置为2小时
84    default-cache-ttl 1800
85    max-cache-ttl 7200
86
87.. note::
88
89    不需要在 shell 会话开始时手动启动 gpg-agent。你可能需要检查
90    rc 文件来删除旧版本 GnuPG 中的所有内容,因为它可能不再做正确
91    的事情。
92
93保护你的 PGP 密钥
94=================
95
96本指南假定你已经拥有用于 Linux 内核开发目的的 PGP 密钥。如果你还没
97有,请参阅前面提到的 "`保护代码完整性`_" 文档,以获取有关如何创建新
98密钥的指导。
99
100如果你当前的密钥低于 2048 位 (RSA),你还应该创建一个新密钥。
101
102了解 PGP 子密钥
103---------------
104
105PGP 密钥很少由单个密钥对组成 - 通常它是独立子密钥的集合,这些子密钥
106可根据其功能用于不同的目的,并在创建时分配。PGP 定义了密钥可以具有的
107四种功能:
108
109- **[S]** 密钥可用于签名
110- **[E]** 密钥可用于加密
111- **[A]** 密钥可用于身份验证
112- **[C]** 密钥可用于验证其他密钥
113
114具有 **[C]** 功能的密钥通常称为“主”密钥,但该术语具有误导性,因为
115它意味着可以使用Certify密钥来代替同一链上的任何其他子密钥(如物理
116“主密钥”可用于打开为其他钥匙制作的锁)。由于情况并非如此,本指南将
117其称为“认证密钥”以避免任何歧义。
118
119充分理解以下内容至关重要:
120
1211. 所有子项彼此完全独立。如果你丢失了私有子密钥,则无法从链上的任何
122   其他私钥恢复或重新创建它。
1232. 除 Certify 密钥外,可以有多个具有相同功能的子密钥(例如,你可
124   以有 2 个有效的加密子密钥、3 个有效的签名子密钥,但只有 1 个有
125   效的认证子密钥)。所有子密钥都是完全独立的——加密到一个 **[E]**
126   子密钥的信息(messages)无法使用你可能拥有的任何其他 **[E]**
127   子密钥解密。
1283. 单个子密钥可能具有多种功能(例如,你的 **[C]** 密钥也可以是你
129   的 **[S]** 密钥)。
130
131携带 **[C]** (证明)能力的密钥是唯一可以用来指示与其他密钥的关系
132的密钥。仅 **[C]** 密钥可用于:
133
134- 添加或撤销具有 S/E/A 功能的其他密钥(子密钥)
135- 添加、更改或撤销与密钥关联的身份 (uid)
136- 添加或更改其本身或任何子密钥的到期日期
137- 出于信任网络的目的签署其他人的密钥
138
139默认情况下,GnuPG 在生成新密钥时创建以下内容:
140
141- 一个子密钥同时具有认证和签名功能 (**[SC]**)
142- 具有加密功能的单独子密钥 (**[E]**)
143
144如果你在生成密钥时使用了默认参数,那么这就是你将得到的。你可以通过
145运行命令来验证,例如: ``gpg --list-secret-keys``
146
147::
148
149    sec   ed25519 2022-12-20 [SC] [expires: 2024-12-19]
150          000000000000000000000000AAAABBBBCCCCDDDD
151    uid           [ultimate] Alice Dev <adev@kernel.org>
152    ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
153
154在 ``sec`` 这行下面长长的一行就是你的密钥指纹-无论在下文任何地方
155看到 ``[fpr]`` 都指的是这40个字符。
156
157确保你的密码强度高
158------------------
159
160GnuPG 在将私钥存储到磁盘之前使用密码对其进行加密。这样,即使你的
161``.gnupg`` 目录全部泄露或被盗,攻击者在没有事先获取密码来解密的
162情况下也无法使用你的私钥。
163
164你的私钥受到强密码保护是绝对必要的。要设置或更改它,请使用::
165
166    $ gpg --change-passphrase [fpr]
167
168创建一个单独的签名子密钥
169------------------------
170
171我们的目的是通过将你的证书密钥移动到离线媒介来保护它,因此如果你只
172有组合的 **[SC]** 密钥,那么你应该创建一个单独的签名子密钥::
173
174    $ gpg --quick-addkey [fpr] ed25519 sign
175
176.. note:: GnuPG 中的 ECC 支持
177
178    请注意,如果你打算使用不支持 ED25519 ECC 密钥的硬件密钥,则
179    应选择“nistp256”或“ed25519”。请参阅下面有关推荐硬件设备的
180    部分。
181
182
183备份你的证书密钥以进行灾难恢复
184------------------------------
185
186你的 PGP 密钥上来自其他开发者的签名越多,出于灾难恢复的原因,你就越
187有理由创建一个位于数字媒体之外的备份版本。
188
189创建私钥的可打印硬拷贝的最佳方法是使用 ``paperkey`` 为此目的编写
190的软件。有关输出格式及其相对于其他解决方案的优势的更多详细信息,请参
191阅 ``paperkey`` 参考资料。大多数发行版都应该已经打包了 Paperkey。
192
193运行以下命令来创建私钥的硬拷贝备份::
194
195    $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt
196
197打印出该文件(或将输出直接传输到 lpr),然后用笔在纸的边缘写下你的密
198码。 **强烈建议这样做**,因为密钥打印输出仍然使用该密码进行加密,并且
199如果你更改了它,你将不记得创建备份时它曾经是什么 - *保证*。
200
201将生成的打印输出和手写密码放入信封中,并存放在安全且受到良好保护的地
202方,最好远离你的家,例如银行保险柜。
203
204.. note::
205
206    你的打印机可能不再是连接到并行端口的简单哑设备,但由于输出仍然使
207    用你的密码进行加密,因此即使“云端打印”的现代打印机也应该保持相
208    对安全的操作
209
210备份整个 GnuPG 目录
211-------------------
212
213.. warning::
214
215    **!!!不要跳过这个步骤!!!**
216
217如果你需要恢复 PGP 密钥,拥有一个随时可用的备份非常重要。这与我们
218所做的灾难级准备不同 ``paperkey`` 。每当你需要使用你的证书密钥时,
219例如在会议和峰会后更改你自己的密钥或签署其他人的密钥时,你还将依赖
220这些外部副本。
221
222首先获取一个小型 USB “拇指” 驱动器(最好是两个!),用于备份目的。
223你需要使用 LUKS 对其进行加密——请参阅你的发行版文档以了解如何完成
224此操作。
225
226对于加密密码,你可以使用与 PGP 密钥相同的密码。
227
228加密过程完成后,重新插入 USB 驱动器并确保其正确安装。将整个 ``.gnupg``
229目录复制到加密存储::
230
231    $ cp -a ~/.gnupg /media/disk/foo/gnupg-backup
232
233你现在应该测试一下,确保一切依然能正常工作::
234
235    $ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr]
236
237如果没有出现任何错误,那么就可以开始了。卸下 USB 驱动器,给它贴上
238明显的标签,这样下次需要使用随机 USB 驱动器时就不会把它吹走,然后
239放在安全的地方 - 但不要太远,因为你每次都需要使用它时不时地用于诸
240如编辑身份、添加或撤销子密钥或签署其他人的密钥之类的事情。
241
242从你的 homedir 中删除 Certify 密钥
243----------------------------------
244
245我们的主目录中的文件并没有我们想象的那么受到保护。它们可以通过多种
246不同的方式泄露或被盗:
247
248- 在制作快速主目录备份以设置新工作站时意外发生
249- 系统管理员的疏忽或恶意
250- 通过不安全的备份
251- 通过桌面应用程序(浏览器、pdf 查看器等)中的恶意软件
252- 跨越国界时通过胁迫
253
254使用良好的密码短语保护你的密钥极大地有助于降低上述任何风险,但密码
255短语可以通过键盘记录器、肩窥或任何其他方式发现。因此,建议的设置是
256从主目录中删除你的证书密钥并将其存储在离线存储中。
257
258.. warning::
259
260    请参阅上一节并确保你已完整备份 GnuPG 目录。如果你没有可用的
261    备份,我们要做的事情将使你的密钥毫无用处!
262
263首先,确定你的证书密钥的keygrip::
264
265    $ gpg --with-keygrip --list-key [fpr]
266
267输出将是这样的::
268
269    pub   ed25519 2022-12-20 [SC] [expires: 2022-12-19]
270          000000000000000000000000AAAABBBBCCCCDDDD
271          Keygrip = 1111000000000000000000000000000000000000
272    uid           [ultimate] Alice Dev <adev@kernel.org>
273    sub   cv25519 2022-12-20 [E] [expires: 2022-12-19]
274          Keygrip = 2222000000000000000000000000000000000000
275    sub   ed25519 2022-12-20 [S]
276          Keygrip = 3333000000000000000000000000000000000000
277
278找到该线 ``pub`` 下方的keygrip项 (位于“认证密钥指纹”的正下方)。
279这将直接对应于你``~/.gnupg`` 目录中的一个文件::
280
281    $ cd ~/.gnupg/private-keys-v1.d
282    $ ls
283    1111000000000000000000000000000000000000.key
284    2222000000000000000000000000000000000000.key
285    3333000000000000000000000000000000000000.key
286
287你所要做的只是删除与证书密钥 keygrip 对应的 .key 文件::
288
289    $ cd ~/.gnupg/private-keys-v1.d
290    $ rm 1111000000000000000000000000000000000000.key
291
292现在,如果你发出命令 ``--list-secret-keys`` ,它将显示证书密钥丢
293失( 表示 ``#`` 它不可用)::
294
295    $ gpg --list-secret-keys
296    sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
297          000000000000000000000000AAAABBBBCCCCDDDD
298    uid           [ultimate] Alice Dev <adev@kernel.org>
299    ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
300    ssb   ed25519 2022-12-20 [S]
301
302你还应该删除 ``~/.gnupg``目录中的所有 ``secring.gpg`` 文件 ,这些
303文件可能是以前版本的 GnuPG 留下的。
304
305如果你没有“private-keys-v1.d”目录
306~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307
308如果你没有 ``~/.gnupg/private-keys-v1.d`` 目录,那么你的密钥仍存
309储在 GnuPG v1 使用的旧文件 ``secring.gpg`` 中。对密钥进行任何更改
310(例如更改密码或添加子密钥)应该会自动转换旧 ``secring.gpg`` 格式以
311供使用 ``private-keys-v1.d`` 。
312
313完成此操作后,请确保删除过时的 ``secring.gpg`` 文件,其中仍然包含你
314的私钥。
315
316
317将子密钥移至专用加密设备
318========================
319
320尽管 Certify 密钥现在不会被泄露或被盗,但子密钥仍然位于你的主目录中。
321任何设法获得这些内容的人都将能够解密你的通信或伪造你的签名(如果他们知
322道密码)。此外,每次执行 GnuPG 操作时,密钥都会加载到系统内存中,并
323可能被足够高级的恶意软件(例如 Meltdown 和 Spectre)从那里窃取。
324
325完全保护密钥的最佳方法是将它们转移到能够进行智能卡操作的专用硬件设备上。
326
327智能卡的好处
328------------
329
330智能卡包含一个加密芯片,能够存储私钥并直接在卡本身上执行加密操作。由于
331密钥内容永远不会离开智能卡,因此插入硬件设备的计算机的操作系统无法自行
332检索私钥。这与我们之前用于备份目的的加密 USB 存储设备有很大不同——当
333USB 设备插入并安装时,操作系统能够访问私钥内容。
334
335使用外部加密 USB 介质并不能替代具有智能卡功能的设备。
336
337可用的智能卡设备
338----------------
339
340除非你的所有笔记本电脑和工作站都有智能卡读卡器,否则最简单的方法是获
341取实现智能卡功能的专用 USB 设备。有多种选择::
342
343- `Nitrokey Start`_: 开放硬件和免费软件,日本基于FSI的 `Gnuk` 。
344  少数支持 ED25519 ECC 密钥的商用设备之一,但提供的安全功能最少
345  (例如防篡改或某些旁路攻击)。
346- `Nitrokey Pro 2`_: 与 Nitrokey Start 类似,但更防篡改并提供
347  更多安全功能。Pro 2 支持 ECC 加密 (NISTP)。
348- `Yubikey 5`_: 专有硬件和软件,但比 Nitrokey Pro 便宜,并且以
349  USB-C 形式提供,对于较新的笔记本电脑更有用。提供额外的安全功能,
350  例如 FIDO U2F 等,现在终于支持 NISTP 和 ED25519 ECC 密钥。
351
352你的选择将取决于成本、你所在地理区域的货运便利性以及开放/专有硬件考虑
353因素。
354
355.. note::
356
357    如果你位列于 MAINTAINERS 中或在 kernel.org 上拥有帐户,则你有
358    资格获得Linux 基金会提供的_`qualify for a free Nitrokey Start` 。
359
360.. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
361.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nkpr2-nitrokey-pro-2-3
362.. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/
363.. _Gnuk: https://www.fsij.org/doc-gnuk/
364.. _`qualify for a free Nitrokey Start`: https://www.kernel.org/nitrokey-digital-tokens-for-kernel-developers.html
365
366配置你的智能卡设备
367------------------
368
369当你将智能卡设备插入任何现代 Linux 工作站时,它就应该可以正常工作
370(TM)。你可以通过运行来验证它::
371
372    $ gpg --card-status
373
374如果你看到完整的智能卡详细信息,那么你就可以开始了。不幸的是,对所有
375可能无法正常工作的原因进行故障排除超出了本指南的范围。如果你在使该卡
376与 GnuPG 配合使用时遇到问题,请通过常规支持渠道寻求帮助。
377
378要配置你的智能卡,你需要使用 GnuPG 菜单系统,因为没有方便的命令行开
379关::
380
381    $ gpg --card-edit
382    [...omitted...]
383    gpg/card> admin
384    Admin commands are allowed
385    gpg/card> passwd
386
387你应该设置用户 PIN (1)、管理员 PIN (3) 和重置代码 (4)。请确保将
388这些信息记录并存储在安全的地方,尤其是管理员 PIN 码和重置代码(它允
389许你完全擦除智能卡)。你很少需要使用管理员 PIN 码,如果你不记录它,
390你将不可避免地忘记它是什么。
391
392回到主卡菜单,你还可以设置其他值(例如姓名、性别、登录数据等),但这
393不是必需的,并且如果你丢失智能卡,还会泄露有关智能卡的信息。
394
395.. note::
396
397    尽管名称为“PIN”,但卡上的用户 PIN 和管理员 PIN 都不需要是数字。
398
399.. warning::
400
401    某些设备可能要求你将子密钥移至设备上,然后才能更改密码。请检查设
402    备制造商提供的文档。
403
404将子密钥移至你的智能卡
405----------------------
406
407退出卡菜单(使用“q”)并保存所有更改。接下来,让我们将子密钥移至智能卡
408上。对于大多数操作,你将需要 PGP 密钥密码和卡的管理员 PIN::
409
410    $ gpg --edit-key [fpr]
411
412    Secret subkeys are available.
413
414    pub  ed25519/AAAABBBBCCCCDDDD
415         created: 2022-12-20  expires: 2024-12-19  usage: SC
416         trust: ultimate      validity: ultimate
417    ssb  cv25519/1111222233334444
418         created: 2022-12-20  expires: never       usage: E
419    ssb  ed25519/5555666677778888
420         created: 2017-12-07  expires: never       usage: S
421    [ultimate] (1). Alice Dev <adev@kernel.org>
422
423    gpg>
424
425使用 ``--edit-key`` 使我们再次进入菜单模式,你会注意到按键列表有点
426不同。从现在开始,所有命令都在此菜单模式内完成,如 所示 ``gpg>``。
427
428首先,让我们选择要放入卡上的密钥 - 你可以通过键入 ``key 1`` (它是
429列表中的第一个, **[E]** 子密钥)来完成此操作:
430
431    gpg> key 1
432
433在输出中,你现在在 **[E]** 子密钥应该看到 ``ssb*`` 。意味着这个子
434密钥当前被选中。它用作切换键,这意味着如果你再次输入 ``key 1`` ,
435``*`` 将会消失并且该键将不再被选择。
436
437现在,让我们将该密钥移至智能卡上::
438
439    gpg> keytocard
440    Please select where to store the key:
441       (2) Encryption key
442    Your selection? 2
443
444由于它是我们的 **[E]** 密钥,因此将其放入加密槽中是有意义的。当你提
445交选择时,系统将首先提示你输入 PGP 密钥密码,然后输入管理员 PIN 码。
446如果命令返回且没有错误,则你的密钥已被移动。
447
448**重要提示**:现在再次键入 ``key 1`` 以取消选择第一个键,并 ``key 2``
449选择 **[S]** 密钥::
450
451    gpg> key 1
452    gpg> key 2
453    gpg> keytocard
454    Please select where to store the key:
455       (1) Signature key
456       (3) Authentication key
457    Your selection? 1
458
459你可以使用 **[S]** 密钥进行签名和身份验证,但我们希望确保它位于签名槽中,
460因此选择 (1)。跟之前一样,如果你的命令返回且没有错误,则操作成功::
461
462    gpg> q
463    Save changes? (y/N) y
464
465保存更改将删除你从主目录移动到卡上的密钥(但这没关系,因为我们还有备份,
466让我们需要替换智能卡时再次执行此操作)。
467
468验证密钥是否已移动
469~~~~~~~~~~~~~~~~~~
470
471如果你现在执行 ``--list-secret-keys`` ,你将看到输出中存在细微的差异::
472
473    $ gpg --list-secret-keys
474    sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
475          000000000000000000000000AAAABBBBCCCCDDDD
476    uid           [ultimate] Alice Dev <adev@kernel.org>
477    ssb>  cv25519 2022-12-20 [E] [expires: 2024-12-19]
478    ssb>  ed25519 2022-12-20 [S]
479
480在 ``ssb>``中的 ``>`` 输出意味着子密钥只能在智能卡上可用,如果你返回
481密钥目录并查看那里的内容,你会注意到 ``.key`` 那里的文件已被存根替换::
482
483    $ cd ~/.gnupg/private-keys-v1.d
484    $ strings *.key | grep 'private-key'
485
486输出应包含 ``shadowed-private-key`` 指示这些文件只是存根,实际内容
487位于智能卡上。
488
489验证智能卡是否正常工作
490~~~~~~~~~~~~~~~~~~~~~~
491
492要验证智能卡是否按预期工作,你可以创建签名::
493
494    $ echo "Hello world" | gpg --clearsign > /tmp/test.asc
495    $ gpg --verify /tmp/test.asc
496
497在你的第一条命令执行时,应该会询问你智能卡的PIN,然后在你运行
498``gpg --verify`` 后显示"Good signature"。
499
500恭喜,你已成功使窃取你的数字开发者身份变得极其困难!
501
502其他常见的 GnuPG 操作
503---------------------
504
505以下是你需要使用 PGP 密钥执行的一些常见操作的快速参考。
506
507安装你的安全离线存储
508~~~~~~~~~~~~~~~~~~~~
509
510你将需要你的证书密钥来执行以下任何操作,因此你首先需要安装备份离线存储
511并告诉 GnuPG 使用它::
512
513    $ export GNUPGHOME=/media/disk/foo/gnupg-backup
514    $ gpg --list-secret-keys
515
516你需要确保你看到 ``sec`` 而不是 ``sec#`` 在输出中( ``#`` 意味着
517密钥不可用并且你仍在使用常规主目录位置)。
518
519延长密钥有效期
520~~~~~~~~~~~~~~
521
522证书密钥的默认到期日期为自创建之日起 2 年。这样做既是出于安全原因,也
523是为了使过时的密钥最终从密钥服务器中消失。
524
525要将密钥的有效期从当前日期延长一年,只需运行::
526
527    $ gpg --quick-set-expire [fpr] 1y
528
529如果更容易记住,你也可以使用特定日期(例如你的生日、1 月 1 日或加拿大
530国庆日)::
531
532    $ gpg --quick-set-expire [fpr] 2025-07-01
533
534请记住将更新后的密钥发送回密钥服务器::
535
536    $ gpg --send-key [fpr]
537
538进行任何更改后更新你的工作目录
539~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540
541使用离线存储对密钥进行任何更改后,你需要将这些更改导入回常规工作目录
542中::
543
544    $ gpg --export | gpg --homedir ~/.gnupg --import
545    $ unset GNUPGHOME
546
547通过 ssh 使用 gpg-agent
548~~~~~~~~~~~~~~~~~~~~~~~
549
550如果你需要在远程系统上签署标签或提交,你可以通过 ssh 转发你的
551gpg-agent。
552
553请参考 GnuPG wiki 上提供的说明:
554
555- `Agent通过SSH转发`_
556
557如果你可以修改远程端的 sshd 服务器设置,则工作会更顺利。
558
559.. _`Agent通过SSH转发`: https://wiki.gnupg.org/AgentForwarding
560
561将 PGP 与 Git 结合使用
562======================
563
564Git 的核心功能之一是它的分散性——一旦将仓库克隆到你的系统,你就拥有该
565项目的完整历史记录,包括其所有标签、提交和分支。然而,随着数百个克隆仓
566库的出现,人们如何验证他们的 linux.git 副本没有被恶意第三方篡改?
567
568或者,如果在代码中发现后门,并且提交中的“Author”行表示它是由你完成的,
569而你非常确定 `自己与它无关`_ ,会发生什么?
570
571为了解决这两个问题,Git 引入了 PGP 集成。签名的标签通过确保其内容与创
572建标签的开发人员的工作站上的内容完全相同来证明仓库的完整性,而签名的提
573交使其他人几乎不可能在无法访问你的 PGP 密钥的情况下冒充你。
574
575.. _`自己与它无关`: https://github.com/jayphelps/git-blame-someone-else
576
577配置 git 使用你的 PGP 密钥
578--------------------------
579
580如果你的密钥环中只有一个密钥,那么你实际上不需要执行任何额外操作,因为
581它会成为你的默认密钥。但是,如果你碰巧有多个密钥,你可以告诉 git 应该
582使用哪个密钥(``[fpr]`` 是你密钥的指纹)::
583
584    $ git config --global user.signingKey [fpr]
585
586如何使用签名标签
587----------------
588
589要创建签名标签,只需将 ``-s`` 开关传递给 tag 命令::
590
591    $ git tag -s [tagname]
592
593我们的建议是始终签署 git 标签,因为这可以让其他开发人员确保他们从中提
594取的 git 仓库没有被恶意更改。
595
596如何验证签名标签
597~~~~~~~~~~~~~~~~
598
599要验证签名标签,只需使用以下 ``verify-tag`` 命令::
600
601    $ git verify-tag [tagname]
602
603如果你从项目仓库的另一个分支中拉取标签,git 应该自动验证你拉取的顶
604部的签名,并在合并操作期间向你显示结果::
605
606    $ git pull [url] tags/sometag
607
608合并消息将包含如下内容::
609
610    Merge tag 'sometag' of [url]
611
612    [Tag message]
613
614    # gpg: Signature made [...]
615    # gpg: Good signature from [...]
616
617如果你正在验证其他人的 git 标签,那么你将需要导入他们的 PGP 密钥。
618请参阅下面的":ref:`身份验证`"部分。
619
620配置 git 始终对带注释的标签(annotated tags)进行签名annotated tags
621~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
622
623如果你要创建带注释的标签,你很可能会想要对其进行签名。要强制 git 始终签
624署带注释的标签,你可以设置一个全局配置选项::
625
626    $ git config --global tag.forceSignAnnotated true
627
628如何使用签名的提交
629------------------
630
631创建签名提交很容易,但在 Linux 内核开发中使用它们要困难得多,因为它依赖
632于发送到邮件列表的补丁,并且此工作流程不保留 PGP 提交签名。此外,当重新
633调整仓库以匹配上游时,甚至你自己的 PGP 提交签名最终也会被丢弃。因此,大
634多数内核开发人员不会费心签署他们的提交,并且会忽略他们在工作中依赖的任何
635外部仓库中的签名提交。
636
637但是,如果你的工作 git 树在某些 git 托管服务(kernel.org638infradead.orgozlabs.org 或其他)上公开可用,那么建议你签署所有 git
639提交,即使上游开发人员不直接受益于这种做法。
640
641我们推荐这样做的原因如下:
642
6431. 如果需要执行代码取证或跟踪代码来源,即使是外部维护的带有 PGP 提交签名
644   的树对于此类问题也很有价值。
6452. 如果你需要重新克隆本地仓库(例如,在磁盘故障后),这可以让你在恢复工
646   作之前轻松验证仓库的完整性。
6473. 如果有人需要挑选你的提交,这可以让他们在应用之前快速验证其完整性。
648
649创建签名提交
650~~~~~~~~~~~~
651
652要创建签名提交,你只需将 ``-S`` 标志传递给 ``git commit`` 命令(由于
653与另一个标志冲突,所以它是大写的 ``-S`` )::
654
655    $ git commit -S
656
657配置 git 始终对提交进行签名
658~~~~~~~~~~~~~~~~~~~~~~~~~~~
659
660你可以告诉 git 总是签署提交::
661
662    git config --global commit.gpgSign true
663
664.. note::
665
666    确保 ``gpg-agent`` 在打开此功能之前进行配置。
667
668.. _身份验证:
669
670
671如何使用签名补丁
672----------------
673
674可以使用你的 PGP 密钥来签署发送到内核开发人员邮件列表的补丁。由于现有的
675电子邮件签名机制(PGP-Mime 或 PGP-inline)往往会导致常规代码审查任务
676出现问题,因此你应该使用为此创建的 kernel.org 工具,该工具将加密证明签
677名放入消息标头中(a-la DKIM):
678
679- `Patatt Patch Attestation`_
680
681.. _`Patatt Patch Attestation`: https://pypi.org/project/patatt/
682
683安装和配置 patatt
684~~~~~~~~~~~~~~~~~
685
686Patatt 已针对许多发行版进行了打包,因此请先检查那里。你还可以使用
687“ ``pip install patatt`` ”从 pypi 安装它。
688
689如果你已经使用 git 配置了 PGP 密钥(通过``user.signingKey`` 配置参数),
690则 patatt 不需要进一步配置。你可以通过在所需的仓库中安装 git-send-email
691钩子来开始签署补丁::
692
693    patatt install-hook
694
695现在,你使用 ``git send-email`` 发送的任何补丁都将自动使用你的加密签
696名进行签名
697
698检查 patatt 签名
699~~~~~~~~~~~~~~~~
700
701如果你用于 ``b4`` 检索和应用补丁,那么它将自动尝试验证它遇到的所有
702DKIM 和 patatt 签名,例如::
703
704    $ b4 am 20220720205013.890942-1-broonie@kernel.org
705    [...]
706    Checking attestation on all messages, may take a moment...
707    ---
708      ✓ [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
709      ✓ [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
710      ✓ [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
711      ---
712      ✓ Signed: openpgp/broonie@kernel.org
713      ✓ Signed: DKIM/kernel.org
714
715.. note::
716
717    Patatt 和 b4 仍在积极开发中,你应该检查这些项目的最新文档以了解任
718    何新功能或更新功能。
719
720如何验证内核开发者身份
721======================
722
723签署标签和提交很容易,但是如何验证用于签署某项内容的密钥是否属于实际的内
724核开发人员而不是恶意冒名顶替者?
725
726使用 WKD 和 DANE 配置auto-key-locate(自动密钥检索)
727----------------------------------------------------
728
729如果你还没有广泛收集其他开发人员的公钥,那么你可以依靠密钥自动发现和自动
730检索来快速启动你的密钥环。如果从头开始创建自己的信任 Web 的预期太令人畏
731惧, GnuPG 可以借助其他委托信任技术(即 DNSSEC 和 TLS)来帮助你继续前
732进。
733
734将以下内容添加到你的 ``~/.gnupg/gpg.conf``::
735
736    auto-key-locate wkd,dane,local
737    auto-key-retrieve
738
739基于 DNS 的命名实体身份验证(“DANE”)是一种在 DNS 中发布公钥并使用
740DNSSEC 签名区域保护它们的方法。Web 密钥目录(“WKD”)是使用 https
741查找来达到相同目的的替代方法。当使用 DANE 或 WKD 查找公钥时,GnuPG
742将分别验证 DNSSEC 或 TLS 证书,然后将自动检索的公钥添加到本地密钥环。
743
744Kernel.org 为所有拥有 kernel.org 帐户的开发人员发布 WKD。一旦你的
745``gpg.conf`` 中进行了上述更改,你就可以自动检索 Linus Torvalds 和
746Greg Kroah-Hartman 的密钥(如果你还没有它们)::
747
748    $ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org
749
750如果你有 kernel.org 帐户,那么你应该 `添加 kernel.org UID 到你的密钥中`_
751添加到你的密钥中,以使 WKD 对其他内核开发人员更有用。
752
753.. _`添加 kernel.org UID 到你的密钥中`: https://korg.wiki.kernel.org/userdoc/mail#adding_a_kernelorg_uid_to_your_pgp_key
754
755信任网 (WOT) 与首次使用信任 (TOFU)
756-----------------------------------
757
758PGP 结合了称为“信任网”的信任委托机制。从本质上讲,这是一次尝试取代
759HTTPS/TLS 世界对集中式证书颁发机构的需求。PGP 将这一责任留给每个
760用户,而不是由各种软件制造商规定谁应该是你值得信赖的认证实体。
761
762不幸的是,很少有人了解信任网是如何运作的。虽然它仍然是 OpenPGP 规
763范的一个重要方面,但最新版本的 GnuPG(2.2 及更高版本)已经实现了
764一种称为“首次使用信任”(TOFU) 的替代机制。你可以将 TOFU 视为“类似
765SSH 的信任方法”。使用 SSH,第一次连接到远程系统时,其密钥指纹会被
766记录并记住。如果将来密钥发生变化,SSH 客户端将向你发出警报并拒绝连
767接,迫使你决定是否选择信任更改后的密钥。同样,第一次导入某人的 PGP
768密钥时,它被认为是有效的。如果将来的任何时候 GnuPG 遇到具有相同标
769识的另一个密钥,则先前导入的密钥和新密钥都将被标记为无效,你将需要手
770动确定保留哪一个。
771
772我们建议你使用 TOFU+PGP 组合信任模型(这是 GnuPG v2 中新默认的)。
773若要设置它,在 ``~/.gnupg/gpg.conf`` 中添加(或修改)
774``trust-model`` 设置::
775
776    trust-model tofu+pgp
777
778使用 kernel.org 信任网仓库
779--------------------------
780
781Kernel.org 维护着一个包含开发人员公钥的 git 仓库,作为复制密钥服
782务器网络的替代品,而在过去几年中,该网络几乎已经陷入黑暗。有关如何将
783该仓库设置为公钥来源的完整文档可以在此处找到:
784
785- `内核开发者密钥环`_
786
787如果你是内核开发人员,请考虑提交你的密钥以将其包含到该密钥环中。
788
789.. _`内核开发者密钥环`: https://korg.docs.kernel.org/pgpkeys.html
790