pacman (简体中文)/Package signing (简体中文)

From ArchWiki

翻译状态:本文是 Pacman/Package_signing翻译。上次翻译日期:2021-09-07。如果英文版本有所更改,则您可以帮助同步翻译。

为了保证软件包来自开发者, Pacman 使用信任网络中的 GnuPG 密钥进行软件包验证。这个网址记录了 Archlinux 的主密钥。其中至少三个主密匙被用来签署官方开发者和授信用户自己的密钥,而他们将用这些密钥签署自己的包。用户在配置 pacman-key 时也会生成一个唯一的密钥。所以信任网络也会把用户的密钥连接到五大主密钥上面。

信任网络示例:

  • 自定义软件包: 用户自己构建软件包并用本地密钥签名。
  • 非官方软件包: 开发者构建软并签名软件包。用户需要用自己的密钥签名开发者的密钥,将其变为可信。
  • 官方软件包: 开发者构建软件包,而开发者的密钥已经被 Arch 主密钥签名。最终用户用自己的密钥签名主密钥,这样就能信任所有官方开发者。
提示: HKP协议使用11371/tcp端口用来通信。为了从服务器得到签署的密钥(使用pacman-key),这个端口必须打开。

配置

配置 pacman

首先通过 /etc/pacman.conf 中的 SigLevel 确定要使用的检查级别。文件的注释中列出了几个可选设置,pacman.conf(5) § PACKAGE AND DATABASE SIGNATURE CHECKING 有详细介绍。签名检查可以全局配置或针对某个仓库配置。如果 SigLevel 在 [options] 节中进行了全局设置,那么所有的包都必须签名。包括你自己编译构建的包,也需要使用 makepkg 进行签名。

注意: 尽管所有的官方软件包现在都进行了签名,但是在2018年11月的时候签名数据库还在开发。如果设置了 Required ,那么 DatabaseOptional 也应该被设置。

默认的设置下,系统只安装被授信的密钥签署的软件包。

/etc/pacman.conf
SigLevel = Required DatabaseOptional

TrustOnly 是 pacman 的默认设置。

默认配置的效果与下行等同:

SigLevel = Required DatabaseOptional TrustedOnly

上面这些也可以在仓库内部进行设置,比如:

[core]
SigLevel = PackageRequired # ’Optional’ here would turn off a global ’Required’ for this repository
Include = /etc/pacman.d/mirrorlist

软件仓库中的软件启用了签名验证,但是并不要求仓库数据库也被签名了。

警告: SigLevel TrustAll 设置仅仅为了测试而存在,使用它会信任未被验证的密钥。对于所有的官方软件源你应该使用 TrustedOnly

初始化密钥环

要初始化 pacman 密钥:

# pacman-key --init

初始化密钥,需要收集到足够的。请随意移动鼠标,随机按键盘或者运行一些磁盘读写操作(比如在其他终端运行ls -R /或者find / -name foo 或者 dd if=/dev/sda8 of=/dev/tty7之类的)应该会收集足够的熵。如果你的系统没有足够的熵,这项工作需要好几个小时,但是如果你有,那么就会快多了。

这会在 /etc/pacman.d/gnupg 初始化密钥并生成系统主密钥。

注意: 如果pacman-key --init运行时系统没有足够的熵,可能会需要很长时间。请在目标机器上安装 havegedrng-tools。然后在用 root 权限执行pacman-key --init启动 haveged.service

管理密钥

验证主密钥

通过以下命令进行配置:

# pacman-key --populate archlinux

该命令对 Master Signing Keys 进行验证,when prompted as these are used to co-sign (and therefore trust) all other packager's keys.

PGP 通常很长(2048 位或更长),不太容易使用,所以通常创建一个40位十六进制指纹,最后八位被称为密钥 ID,是密钥的名字。长签名可以用来检测两个密钥是否相同。

官方开发者密钥

官方开发者和 TU 的密钥已经被主密钥签名认证,所以不需要用 pacman-key 认证它们。pacman 遇到不认识的签名时,它将会询问是否从密钥服务器(设置在/etc/pacman.d/gnupg/gpg.conf文件中,或在命令行中使用--keyserver选项)下载。

提示: Wikipedia maintains a list of keyservers.

下载开发者密钥后,以后都不需要下载。以后会用它验证所有这个开发者构建的软件包。

注意:

如果开发者和 TU 的密钥是较早之前导入,它们的签名可能还不存在于本地数据库,用下面命令更新:

# pacman-key --refresh-keys
当使用--refresh-keys 时,本地签名也会被远程查找,并收到未找到的消息,这是正常的。

导入非官方密钥

可以通过此方法在pacman密钥环中添加你自己的密钥,或者启用已签名的 非官方软件仓库

首先从密钥持有者手中拿到密钥 ID(keyid),然后把密钥加入密钥环:

  • 如果密钥位于密钥服务器,通过下面命令导入:
    # pacman-key -r keyid
  • 如果提供了地址,先下载,然后用下面密钥导入:
    # pacman-key --add /path/to/downloaded/keyfile

对于所有要签名的密钥,都通过指纹进行验证:

$ pacman-key -f keyid

最后,本地签名导入的密钥:

# pacman-key --lsign-key keyid

现在可以用这个密钥签名软件包了。

用GPG调试

如果需要,可以直接使用GPG调试pacman钥匙环,例如:

# gpg --homedir /etc/pacman.d/gnupg --list-keys

问题解决

error: signature from xxx is invalid

警告: Pacman-key 依赖于 Time (简体中文). 如果系统时间是错误的,将会获得一个报错:
error: PackageName: signature from "User <[email protected]>" is invalid
error: failed to commit transaction (invalid or corrupted package (PGP signature))
Errors occured, no packages were upgraded.

这是 gpg 相关的错误,意味着磁盘上的问题软件包和 TU 签署的软件包并不完全一致。原因并不明确,但是大部分情况下删除文件并重新获取就可以解决。下面三个段落可以解决大部分的问题,如果还是不清楚,可以到论坛提问。

删除报错的包

如果相同的包持续失败,并且您确定 pacman-key 的相关操作是正确的,可以尝试移除软件包 rm /var/cache/pacman/pkg/badpackage* 然后可以重新下载软件包。

这样可能可以解决在升级时遇到的error: linux: signature from "Some Person <[email protected]>" is invalid 或者相似的报错 (这可能并不是一个中间人攻击,仅仅是下载的文件损坏了).

重置所有密钥

如果要删除或重置系统,删除 /etc/pacman.d/gnupg 目录并重新运行 pacman-key --init。通过 pacman-key --populate archlinux 重新添加默认密钥。如果 archlinux-keyring 不是最新的,需要在更新系统前先执行 pacman -S archlinux-keyring

禁用签名检查

警告: 小心使用,禁用签名检查,pacman 会自动安装不信任的软件包。

如果不在意软件包签名,可以完全禁用 PGP 签名检查,编辑 /etc/pacman.conf 并取消注释 [options] 下的如下行:

SigLevel = Never

需要同时注释掉软件源的 SigLevel 设置,因为他们会覆盖全局设置。

这样就不会进行任何签名检查,和 pacman 4 之前一样。如果这样,就不需要用 pacman-key 建立密钥环。

密钥导入失败

有三种可能的情况导致这个问题:

  • 过期的archlinux-keyring 包。
  • 不正确的系统时间。
  • 你的ISP屏蔽了用于导入 PGP keys 的端口。
  • pacman 缓存中包含之前的未签名软件包
  • 未正确设置 dirmngr
  • 长时间没有更新,gpg/pacman 无法处理陈旧的软件仓库

过期的 archlinux-keyring 包可能会导致这个问题,根据情况采用下面的解决方法

更新系统

尝试 升级系统 能否解决这个问题。

切换公钥服务器

如果这样没有起作用,并且系统时间是正确的,你可以尝试切换到 Ubuntu 提供的公钥服务器(keyserver)。编辑 /etc/pacman.d/gnupg/gpg.confkeyserver 行替换为

keyserver hkp://keyserver.ubuntu.com

清理软件包缓存

如果上面方法都不起作用,pacman 缓存 /var/cache/pacman/pkg/ 可以包含之前下载的未签名软件包,手动清空缓存:

# pacman -Sc

=== Signature is unknown trust ===

在执行 pacman -Syu 时可能出现下面错误:

error: package-name: signature from "packager" is unknown trust

这是因为 package-name 软件包使用的 packager 的密钥不被本地的 pacman-key gpg 数据库信任。可能是密钥在加入密钥链之后失效了,可以通过下面方法解决:

  • pacman-key --refresh-keys 刷新密钥
  • 本地手动签署密钥
  • 刷新所有密钥
  • SigLevel 设置成 TrustAll (不推荐)

通过代理更新密钥

要使用代理更新密钥,必须同时在 /etc/gnupg/dirmngr.conf/etc/pacman.d/gnupg/dirmngr.conf 中设置 honor-http-proxy 选项。更多信息请阅读 GnuPG#Use a keyserver.

注意: 如果 pacman-key 没有用 honor-http-proxy 选项,执行失败,重启可能能够解决问题。

参阅