内核维护者 PGP 指南

作者:

Konstantin Ryabitsev <konstantin@linuxfoundation.org>

本文档面向 Linux 内核开发者,特别是子系统维护者。它包含了一部分 Linux 基金会发布的更通用的《保护代码完整性》指南中的信息。请阅读该文档以获取本指南中提及的一些主题的更深入讨论。

PGP 在 Linux 内核开发中的作用

PGP 有助于确保 Linux 内核开发社区所生成代码的完整性,并在较小程度上,通过 PGP 签名的电子邮件交换在开发者之间建立受信任的通信渠道。

Linux 内核源代码以两种主要格式提供

  • 分布式源代码仓库(git)

  • 定期发布快照(tarball)

Git 仓库和 tarball 都带有创建官方内核版本的内核开发者的 PGP 签名。这些签名提供加密保证,确保通过 kernel.org 或任何其他镜像提供的可下载版本与这些开发者工作站上的内容完全相同。为此

  • git 仓库在所有标签上提供 PGP 签名

  • tarball 在所有下载中提供分离的 PGP 签名

信任开发者,而非基础设施

自 2011 年核心 kernel.org 系统受到入侵以来,内核档案项目的主要操作原则是假设基础设施的任何部分都可能随时被入侵。因此,管理员已采取深思熟虑的措施,强调信任必须始终寄托于开发者,而绝不能寄托于代码托管基础设施,无论后者具有多么良好的安全实践。

上述指导原则是需要本指南的原因。我们希望确保通过信任开发者,我们不会仅仅将未来潜在安全事件的责任推卸给他人。目标是提供一套指导方针,开发者可以使用这些方针来创建安全的开发环境并保护用于建立 Linux 内核自身完整性的 PGP 密钥。

PGP 工具

使用 GnuPG 2.2 或更高版本

您的发行版默认应该已经安装了 GnuPG,您只需要验证您正在使用的是一个相对较新的版本。要检查,请运行

$ gpg --version | head -n1

如果您有 2.2 或更高版本,那么您就可以开始使用了。如果您的版本低于 2.2,那么本指南中的某些命令可能无法工作。

配置 gpg-agent 选项

GnuPG 代理是一个辅助工具,它在您使用 gpg 命令时会自动启动,并在后台运行,其目的是缓存私钥密码。您应该了解两个选项来调整密码何时从缓存中过期

  • default-cache-ttl(秒):如果您在生存时间过期之前再次使用同一密钥,倒计时将重新开始一个新周期。默认值为 600(10 分钟)。

  • max-cache-ttl(秒):无论您自首次输入密码以来使用密钥的时间有多近,如果最大生存时间倒计时过期,您都必须再次输入密码。默认值为 30 分钟。

如果您觉得这些默认值太短(或太长),您可以编辑 ~/.gnupg/gpg-agent.conf 文件来设置您自己的值

# set to 30 minutes for regular ttl, and 2 hours for max ttl
default-cache-ttl 1800
max-cache-ttl 7200

注意

在 shell 会话开始时不再需要手动启动 gpg-agent。您可能需要检查您的 rc 文件,以删除为旧版本 GnuPG 设置的任何内容,因为它们可能不再正确。

保护您的 PGP 密钥

本指南假设您已经拥有用于 Linux 内核开发目的的 PGP 密钥。如果您还没有,请参阅前面提到的《保护代码完整性》文档,以获取创建新密钥的指导。

如果您的当前密钥强度低于 2048 位 (RSA),您也应该创建一个新密钥。

理解 PGP 子密钥

PGP 密钥很少由单个密钥对组成——通常它是一个独立的子密钥集合,根据它们在创建时分配的能力,可用于不同的目的。PGP 定义了密钥可以拥有的四种能力

  • [S] 密钥可用于签名

  • [E] 密钥可用于加密

  • [A] 密钥可用于身份验证

  • [C] 密钥可用于认证其他密钥

具有 [C] 能力的密钥常被称为“主”密钥,但这种术语具有误导性,因为它暗示认证密钥可以替代同一链上的任何其他子密钥(就像物理“主密钥”可以打开为其他密钥制作的锁一样)。由于情况并非如此,本指南将将其称为“认证密钥”以避免任何歧义。

充分理解以下几点至关重要

  1. 所有子密钥彼此完全独立。如果您丢失了一个私有子密钥,它无法从您链上的任何其他私钥中恢复或重新创建。

  2. 除了认证密钥外,可以有多个具有相同功能的子密钥(例如,您可以拥有 2 个有效的加密子密钥,3 个有效的签名子密钥,但只有一个有效的认证子密钥)。所有子密钥都是完全独立的——加密到一个 [E] 子密钥的消息无法用您可能拥有的任何其他 [E] 子密钥解密。

  3. 单个子密钥可能具有多种功能(例如,您的 [C] 密钥也可以是您的 [S] 密钥)。

带有 [C] (认证) 功能的密钥是唯一可以用于指示与其他密钥关系的密钥。只有 [C] 密钥可以用于

  • 添加或撤销具有 S/E/A 功能的其他密钥(子密钥)

  • 添加、更改或撤销与密钥关联的身份(uids)

  • 添加或更改自身或任何子密钥的过期日期

  • 为信任网目的签署其他人的密钥

默认情况下,GnuPG 在生成新密钥时会创建以下内容

  • 一个同时具有认证和签名功能的子密钥([SC]

  • 一个单独的具有加密功能的子密钥([E]

如果您在生成密钥时使用了默认参数,那么您将拥有这些。您可以通过运行 gpg --list-secret-keys 进行验证,例如

sec   ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]

sec 条目下的长行是您的密钥指纹——每当您在下面的示例中看到 [fpr] 时,它指的就是那个 40 个字符的字符串。

确保您的密码足够强

GnuPG 使用密码短语在将私钥存储到磁盘之前对其进行加密。这样,即使您的 .gnupg 目录被完整泄露或盗窃,攻击者也无法在未首先获取密码短语以解密它们的情况下使用您的私钥。

私钥必须由一个强密码短语保护,这一点绝对至关重要。要设置或更改它,请使用

$ gpg --change-passphrase [fpr]

创建单独的签名子密钥

我们的目标是通过将您的认证密钥移动到离线存储介质来保护它,因此如果您只有一个组合的 [SC] 密钥,那么您应该创建一个单独的签名子密钥

$ gpg --quick-addkey [fpr] ed25519 sign

注意

GnuPG 中的 ECC 支持

请注意,如果您打算使用不支持 ED25519 ECC 密钥的硬件令牌,则应选择“nistp256”而不是“ed25519”。请参阅下面关于推荐硬件设备的部分。

备份您的认证密钥以备灾难恢复

您的 PGP 密钥从其他开发者那里获得的签名越多,您就越有理由创建一个不在数字媒体上存在的备份版本,以备灾难恢复。

创建私钥可打印硬拷贝的最佳方法是使用专门为此目的编写的 paperkey 软件。有关输出格式及其相对于其他解决方案的优势的更多详细信息,请参阅 man paperkey。Paperkey 应该已经为大多数发行版打包好了。

运行以下命令创建私钥的硬拷贝备份

$ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt

打印出该文件(或将输出直接通过管道传输到 lpr),然后用笔在纸边写下您的密码短语。强烈建议这样做,因为密钥打印件仍然用该密码短语加密,如果您将来更改了它,您将不记得创建备份时它是什么——保证

将打印出来的文件和手写的密码装入信封,并存放在安全且受保护的地方,最好远离您的家,例如您的银行保险库。

注意

您的打印机可能不再是连接到并行端口的简单哑设备,但由于输出仍然用您的密码短语加密,即使打印到“云集成”的现代打印机也应该仍然是相对安全的操作。

备份您的整个 GnuPG 目录

警告

!!!不要跳过此步骤!!!

拥有 PGP 密钥的现成备份非常重要,以防您需要恢复它们。这与我们使用 paperkey 进行的灾难级别准备不同。每当您需要使用您的认证密钥时——例如更改您自己的密钥或在会议和峰会后签署其他人的密钥时,您也将依赖这些外部副本。

首先,准备一个小型的 USB“拇指”驱动器(最好是两个!),您将用它来备份。您需要使用 LUKS 对它们进行加密——请参阅您的发行版文档以了解如何完成此操作。

对于加密密码,您可以使用与 PGP 密钥相同的密码。

加密过程完成后,重新插入 USB 驱动器并确保它正确挂载。将您的整个 .gnupg 目录复制到加密存储中

$ cp -a ~/.gnupg /media/disk/foo/gnupg-backup

您现在应该测试以确保一切正常

$ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr]

如果没有出现任何错误,那么您就可以开始了。卸载 USB 驱动器,清楚地标记它,这样您下次需要使用随机 USB 驱动器时就不会把它搞混,然后把它放在一个安全的地方——但不要太远,因为您会时不时地需要它,用于编辑身份、添加或撤销子密钥,或签署其他人的密钥。

从您的主目录中移除认证密钥

我们主目录中的文件并不像我们想象的那么安全。它们可能通过多种不同方式泄露或被盗

  • 在设置新工作站时,意外地快速复制主目录

  • 系统管理员的疏忽或恶意行为

  • 通过安全性差的备份

  • 通过桌面应用程序(浏览器、PDF 查看器等)中的恶意软件

  • 在穿越国际边境时受到胁迫

使用一个好的密码来保护您的密钥大大有助于降低上述任何风险,但密码可以通过键盘记录器、肩窥或任何其他方式被发现。因此,推荐的设置是将您的认证密钥从您的主目录中移除并存储在离线存储中。

警告

请参阅上一节,并确保您已完整备份您的 GnuPG 目录。我们即将进行的操作将使您的密钥失效,如果您没有可用的备份!

首先,识别您的认证密钥的 keygrip

$ gpg --with-keygrip --list-key [fpr]

输出将是这样的

pub   ed25519 2022-12-20 [SC] [expires: 2022-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
      Keygrip = 1111000000000000000000000000000000000000
uid           [ultimate] Alice Dev <adev@kernel.org>
sub   cv25519 2022-12-20 [E] [expires: 2022-12-19]
      Keygrip = 2222000000000000000000000000000000000000
sub   ed25519 2022-12-20 [S]
      Keygrip = 3333000000000000000000000000000000000000

找到 pub 行下面的 keygrip 条目(就在认证密钥指纹的下方)。这将直接对应您 ~/.gnupg 目录中的一个文件

$ cd ~/.gnupg/private-keys-v1.d
$ ls
1111000000000000000000000000000000000000.key
2222000000000000000000000000000000000000.key
3333000000000000000000000000000000000000.key

您所要做的就是简单地删除与认证密钥 keygrip 对应的 .key 文件

$ cd ~/.gnupg/private-keys-v1.d
$ rm 1111000000000000000000000000000000000000.key

现在,如果您执行 --list-secret-keys 命令,它将显示认证密钥丢失(# 表示它不可用)

$ gpg --list-secret-keys
sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
ssb   ed25519 2022-12-20 [S]

您还应删除 ~/.gnupg 目录中任何可能由旧版本 GnuPG 遗留的 secring.gpg 文件。

如果您没有“private-keys-v1.d”目录

如果您没有 ~/.gnupg/private-keys-v1.d 目录,那么您的私钥仍然存储在 GnuPG v1 使用的旧版 secring.gpg 文件中。对您的密钥进行任何更改,例如更改密码或添加子密钥,都应该自动将旧的 secring.gpg 格式转换为使用 private-keys-v1.d

完成此操作后,请务必删除过时的 secring.gpg 文件,该文件仍包含您的私钥。

将子密钥移动到专用加密设备

尽管认证密钥现在已安全,免于泄露或被盗,但子密钥仍在您的主目录中。任何设法获取这些密钥的人都能够解密您的通信或伪造您的签名(如果他们知道密码)。此外,每次执行 GnuPG 操作时,密钥都会加载到系统内存中,并可能被足够高级的恶意软件(想想熔断和幽灵)从那里窃取。

完全保护您的密钥的最佳方法是将其移动到能够进行智能卡操作的专用硬件设备。

智能卡的好处

智能卡包含一个加密芯片,能够存储私钥并在卡本身上直接执行加密操作。由于密钥内容从未离开智能卡,因此您插入硬件设备的计算机操作系统无法检索私钥本身。这与我们之前用于备份的加密 USB 存储设备非常不同——当 USB 设备插入并挂载时,操作系统能够访问私钥内容。

使用外部加密 USB 介质并不能替代拥有智能卡功能的设备。

可用智能卡设备

除非您所有的笔记本电脑和工作站都配备智能卡读卡器,否则最简单的方法是购买一个实现智能卡功能的专用 USB 设备。有几种选择可供选择

  • Nitrokey Start:开源硬件和自由软件,基于 FSI Japan 的 Gnuk。少数支持 ED25519 ECC 密钥的商用设备之一,但提供的安全功能最少(例如抗篡改或某些侧信道攻击)。

  • Nitrokey Pro 2:类似于 Nitrokey Start,但更防篡改,并提供更多安全功能。Pro 2 支持 ECC 加密(NISTP)。

  • Yubikey 5:专有硬件和软件,但比 Nitrokey Pro 便宜,并提供 USB-C 形式,对新型笔记本电脑更有用。提供 FIDO U2F 等附加安全功能,现在最终支持 NISTP 和 ED25519 ECC 密钥。

您的选择将取决于成本、您所在地区的运输可用性以及开放/专有硬件的考量。

注意

如果您在 MAINTAINERS 中列出或拥有 kernel.org 账户,您有资格免费获得由 Linux 基金会提供的 Nitrokey Start

配置您的智能卡设备

您的智能卡设备在插入任何现代 Linux 工作站时应该“开箱即用”(TM)。您可以通过运行以下命令进行验证

$ gpg --card-status

如果您看到完整的智能卡详细信息,那么您就可以开始使用了。不幸的是,排除所有可能导致您无法正常工作的原因超出了本指南的范围。如果您在使用 GnuPG 时遇到智能卡问题,请通过常规支持渠道寻求帮助。

要配置智能卡,您需要使用 GnuPG 菜单系统,因为没有方便的命令行开关

$ gpg --card-edit
[...omitted...]
gpg/card> admin
Admin commands are allowed
gpg/card> passwd

您应该设置用户 PIN (1)、管理 PIN (3) 和重置码 (4)。请务必记录并安全地保存这些信息——特别是管理 PIN 和重置码(它允许您完全擦除智能卡)。您很少需要使用管理 PIN,因此如果您不记录它,您将不可避免地忘记它是什么。

回到主卡菜单,您还可以设置其他值(如姓名、性别、登录数据等),但这并非必要,并且还会泄露您智能卡的信息,以防您丢失它。

注意

尽管名称为“PIN”,但卡上的用户 PIN 和管理 PIN 都不需要是数字。

警告

某些设备可能要求您在更改密码之前将子密钥移动到设备上。请查阅设备制造商提供的文档。

将子密钥移至您的智能卡

退出卡片菜单(使用“q”)并保存所有更改。接下来,让我们将子密钥移动到智能卡上。对于大多数操作,您需要您的 PGP 密钥密码和卡片的管理 PIN

$ gpg --edit-key [fpr]

Secret subkeys are available.

pub  ed25519/AAAABBBBCCCCDDDD
     created: 2022-12-20  expires: 2024-12-19  usage: SC
     trust: ultimate      validity: ultimate
ssb  cv25519/1111222233334444
     created: 2022-12-20  expires: never       usage: E
ssb  ed25519/5555666677778888
     created: 2017-12-07  expires: never       usage: S
[ultimate] (1). Alice Dev <adev@kernel.org>

gpg>

使用 --edit-key 会再次将我们带入菜单模式,您会注意到密钥列表略有不同。从这里开始,所有命令都在此菜单模式内执行,如 gpg> 所示。

首先,让我们选择要放入卡中的密钥——您可以通过键入 key 1 来完成(它是列表中的第一个,即 [E] 子密钥)

gpg> key 1

在输出中,您现在应该在 [E] 密钥上看到 ssb*。星号 * 表示当前“选中”的密钥。它作为切换开关工作,这意味着如果您再次输入 key 1,星号 * 将消失,并且该密钥将不再被选中。

现在,让我们把那个密钥移到智能卡上

gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2

由于它是我们的 [E] 密钥,将其放入加密槽是合理的。当您提交选择时,系统将首先提示您输入 PGP 密钥密码,然后输入管理 PIN。如果命令返回时没有错误,则您的密钥已成功移动。

重要:现在再次输入 key 1 以取消选择第一个密钥,然后输入 key 2 以选择 [S] 密钥

gpg> key 1
gpg> key 2
gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

您可以使用 [S] 密钥进行签名和认证,但我们想确保它在签名槽中,所以选择(1)。再次,如果您的命令返回时没有错误,则操作成功

gpg> q
Save changes? (y/N) y

保存更改将删除您已移至卡中的密钥(但没关系,因为如果我们需要为替换智能卡再次执行此操作,我们可以在备份中找到它们)。

验证密钥是否已移动

如果您现在执行 --list-secret-keys,您将在输出中看到一个细微的区别

$ gpg --list-secret-keys
sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb>  cv25519 2022-12-20 [E] [expires: 2024-12-19]
ssb>  ed25519 2022-12-20 [S]

ssb> 输出中的 > 表示子密钥仅在智能卡上可用。如果您回到您的密钥目录并查看其中的内容,您会注意到那里的 .key 文件已被存根替换

$ cd ~/.gnupg/private-keys-v1.d
$ strings *.key | grep 'private-key'

输出应包含 shadowed-private-key,表示这些文件仅为存根,实际内容在智能卡上。

验证智能卡功能是否正常

要验证智能卡是否按预期工作,您可以创建一个签名

$ echo "Hello world" | gpg --clearsign > /tmp/test.asc
$ gpg --verify /tmp/test.asc

这将要求您在第一次命令时输入智能卡 PIN,然后在您运行 gpg --verify 后显示“Good signature”。

恭喜您,您已成功地使窃取您的数字开发者身份变得极其困难!

其他常见的 GnuPG 操作

以下是您需要对 PGP 密钥进行的一些常见操作的快速参考。

挂载您的安全离线存储

以下任何操作都需要您的认证密钥,因此您首先需要挂载您的备份离线存储并告诉 GnuPG 使用它

$ export GNUPGHOME=/media/disk/foo/gnupg-backup
$ gpg --list-secret-keys

您要确保在输出中看到 sec 而不是 sec## 意味着密钥不可用,并且您仍在用常规的主目录位置)。

延长密钥有效期

认证密钥的默认有效期为创建日期起 2 年。这样做既出于安全原因,也为了使过时的密钥最终从密钥服务器上消失。

要将密钥有效期从当前日期延长一年,只需运行

$ gpg --quick-set-expire [fpr] 1y

您也可以使用一个特定的日期,如果这样更容易记住的话(例如您的生日、1 月 1 日或加拿大国庆日)

$ gpg --quick-set-expire [fpr] 2025-07-01

记得将更新后的密钥发送回密钥服务器

$ gpg --send-key [fpr]

任何更改后更新您的工作目录

使用离线存储对您的密钥进行任何更改后,您需要将这些更改导入回您的常规工作目录

$ gpg --export | gpg --homedir ~/.gnupg --import
$ unset GNUPGHOME

通过 ssh 使用 gpg-agent

如果您需要在远程系统上签署标签或提交,可以将 gpg-agent 通过 ssh 转发。请参阅 GnuPG wiki 上提供的说明

如果您可以修改远程端 sshd 服务器设置,它会运行得更流畅。

在 Git 中使用 PGP

Git 的核心功能之一是其去中心化的特性——一旦仓库被克隆到您的系统,您就拥有项目的所有历史记录,包括所有标签、提交和分支。然而,随着数百个克隆仓库的出现,任何人如何验证他们的 linux.git 副本没有被恶意第三方篡改?

或者,如果代码中发现了后门,并且提交中的“作者”行显示是您所为,而您非常确定自己与此无关,那会发生什么?

为了解决这两个问题,Git 引入了 PGP 集成。签名标签通过确保其内容与创建标签的开发者的工作站上的内容完全相同来证明仓库的完整性,而签名提交则使得未经您 PGP 密钥的访问几乎不可能冒充您。

配置 git 使用您的 PGP 密钥

如果您的密钥环中只有一个私钥,那么您实际上不需要做任何额外的事情,因为它会成为您的默认密钥。但是,如果您有多个私钥,您可以告诉 git 应该使用哪个密钥([fpr] 是您密钥的指纹)

$ git config --global user.signingKey [fpr]

如何使用签名标签

要创建签名标签,只需将 -s 开关传递给 tag 命令

$ git tag -s [tagname]

我们建议始终签署 git 标签,因为这允许其他开发者确保他们拉取的 git 仓库没有被恶意修改。

如何验证签名标签

要验证签名标签,只需使用 verify-tag 命令

$ git verify-tag [tagname]

如果您正在从项目仓库的另一个分支拉取标签,git 应该在合并操作期间自动验证您正在拉取的分支顶端的签名并向您显示结果

$ git pull [url] tags/sometag

合并消息将包含类似这样的内容

Merge tag 'sometag' of [url]

[Tag message]

# gpg: Signature made [...]
# gpg: Good signature from [...]

如果您要验证他人的 git 标签,则需要导入他们的 PGP 密钥。请参阅下面的“如何处理签名补丁”一节。

配置 git 始终签署带有注释的标签

如果您正在创建带有注释的标签,很有可能您会希望对其进行签名。要强制 git 始终签署带有注释的标签,您可以设置一个全局配置选项

$ git config --global tag.forceSignAnnotated true

如何使用签名提交

创建签名提交很容易,但在 Linux 内核开发中使用它们要困难得多,因为它依赖于发送到邮件列表的补丁,并且此工作流不会保留 PGP 提交签名。此外,当您将仓库变基以与上游匹配时,甚至您自己的 PGP 提交签名最终也会被丢弃。因此,大多数内核开发者不屑于签署他们的提交,并且会忽略他们工作中依赖的任何外部仓库中的签名提交。

然而,如果您的工作 git 树在某些 git 托管服务(kernel.org、infradead.org、ozlabs.org 或其他)上公开可用,那么建议您签署所有 git 提交,即使上游开发者不直接从中受益。

我们推荐这样做有以下原因

  1. 如果需要进行代码取证或跟踪代码来源,即使是带有 PGP 提交签名的外部维护树也将对此类目的很有价值。

  2. 如果您需要重新克隆本地仓库(例如,在磁盘故障后),这让您可以轻松验证仓库完整性,然后再恢复工作。

  3. 如果有人需要挑选您的提交,这允许他们在应用它们之前快速验证其完整性。

创建签名提交

要创建签名提交,您只需将 -S 标志传递给 git commit 命令(由于与另一个标志冲突,它是大写 -S

$ git commit -S

配置 git 始终签署提交

您可以告诉 git 始终签署提交

git config --global commit.gpgSign true

注意

请确保在开启此功能之前配置 gpg-agent

如何处理签名补丁

可以使用您的 PGP 密钥签署发送到内核开发者邮件列表的补丁。由于现有的电子邮件签名机制(PGP-Mime 或 PGP-inline)往往会给常规代码审查任务带来问题,您应该使用 kernel.org 为此目的创建的工具,该工具将加密认证签名放入邮件头中(类似于 DKIM)

安装和配置 patatt

Patatt 已经打包到许多发行版中,所以请先在那里检查。您也可以使用“pip install patatt”从 pypi 安装它。

如果您已经通过 user.signingKey 配置参数在 git 中配置了您的 PGP 密钥,那么 patatt 不需要进一步配置。您可以通过在所需的仓库中安装 git-send-email 钩子来开始签署您的补丁

patatt install-hook

现在,您使用 git send-email 发送的任何补丁都将自动用您的加密签名进行签名。

检查 patatt 签名

如果您使用 b4 来检索和应用补丁,它将自动尝试验证它遇到的所有 DKIM 和 patatt 签名,例如

$ b4 am 20220720205013.890942-1-broonie@kernel.org
[...]
Checking attestation on all messages, may take a moment...
---
  ✓ [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
  ✓ [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
  ✓ [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
  ---
  ✓ Signed: openpgp/broonie@kernel.org
  ✓ Signed: DKIM/kernel.org

注意

Patatt 和 b4 仍在积极开发中,您应该查看这些项目的最新文档以了解任何新增或更新的功能。

如何验证内核开发者身份

签署标签和提交很容易,但是如何验证用于签署内容的密钥属于实际的内核开发者而不是恶意的冒名顶替者呢?

使用 WKD 和 DANE 配置自动密钥检索

如果您还没有大量其他开发者的公共密钥,那么您可以依靠密钥自动发现和自动检索来快速启动您的密钥环。GnuPG 可以利用其他委托信任技术,即 DNSSEC 和 TLS,来帮助您,如果从头开始建立自己的信任网太过艰巨的话。

将以下内容添加到您的 ~/.gnupg/gpg.conf

auto-key-locate wkd,dane,local
auto-key-retrieve

基于 DNS 的命名实体认证(“DANE”)是一种在 DNS 中发布公钥并使用 DNSSEC 签名区域保护它们的方法。Web 密钥目录(“WKD”)是使用 HTTPS 查找来达到相同目的的替代方法。当使用 DANE 或 WKD 查找公钥时,GnuPG 将分别验证 DNSSEC 或 TLS 证书,然后才将自动检索的公钥添加到您的本地密钥环中。

Kernel.org 发布了所有拥有 kernel.org 账户的开发者的 WKD。一旦您在 gpg.conf 中进行了上述更改,您就可以自动检索 Linus Torvalds 和 Greg Kroah-Hartman 的密钥(如果您还没有的话)

$ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org

如果您有 kernel.org 帐户,那么您应该将 kernel.org UID 添加到您的密钥中,以便 WKD 对其他内核开发者更有用。

信任网 (WOT) 与首次使用信任 (TOFU)

PGP 整合了一种称为“信任网”的信任委托机制。其核心是试图取代 HTTPS/TLS 世界中对集中式认证机构的需求。PGP 不再由各种软件制造商来决定谁应该是您信任的认证实体,而是将这项责任留给每个用户。

不幸的是,很少有人理解信任网的工作原理。虽然它仍然是 OpenPGP 规范的一个重要方面,但 GnuPG 的最新版本(2.2 及以上)已经实现了一种名为“首次使用信任”(TOFU)的替代机制。您可以将 TOFU 理解为“类似于 SSH 的信任方法”。对于 SSH,您首次连接到远程系统时,其密钥指纹会被记录并记住。如果密钥将来发生更改,SSH 客户端将提醒您并拒绝连接,强制您决定是否选择信任更改后的密钥。类似地,您首次导入某人的 PGP 密钥时,它被假定为有效。如果将来 GnuPG 在任何时候遇到具有相同身份的另一个密钥,之前导入的密钥和新密钥都将被标记为无效,您将需要手动确定保留哪一个。

我们建议您使用组合的 TOFU+PGP 信任模型(这是 GnuPG v2 中的新默认设置)。要设置它,请在 ~/.gnupg/gpg.conf 中添加(或修改)trust-model 设置

trust-model tofu+pgp

使用 kernel.org 信任网仓库

Kernel.org 维护着一个包含开发者公共密钥的 git 仓库,以取代过去几年大多已停用的密钥服务器网络。有关如何将该仓库设置为公共密钥来源的完整文档可以在这里找到

如果您是内核开发者,请考虑提交您的密钥以包含在该密钥环中。