pacman/Package signing
为了确定软件包的真实性,pacman 使用 OpenPGP 密钥,并遵循 信任网络模型。当前的 Master Signing Keys 可以在 此处找到。至少三把这些 Master Signing Keys 用于签名开发人员和软件包维护者的密钥。然后,这些密钥用于签名他们的软件包。每个用户也有一个唯一的 OpenPGP 密钥,该密钥在配置 pacman-key(8) 时生成。正是这个信任网络将用户的密钥与主密钥连接起来。
信任网络的示例
- 自定义软件包:使用本地密钥创建和签名的软件包。
- 非官方软件包:由开发者创建和签名的软件包。然后,使用本地密钥对开发者的密钥进行签名。
- 官方软件包:由开发者创建和签名的软件包。开发者的密钥由 Arch Linux 主密钥签名。您使用自己的密钥对主密钥进行签名,并且您信任它们会为开发者担保。
设置
配置pacman
/etc/pacman.conf 中的 SigLevel 选项决定了使用 pacman -S 安装软件包时所需的信任级别。有关 SigLevel 的详细解释,请参阅 pacman.conf(5) § PACKAGE AND DATABASE SIGNATURE CHECKING 和文件注释。可以全局设置签名检查,或按仓库设置。如果在 [options] 部分全局设置了 SigLevel,则所有使用 pacman -S 安装的软件包都将需要签名。使用默认 pacman.conf 中的 LocalFileSigLevel 设置,您构建并使用 pacman -U 安装的任何软件包,将不需要使用makepkg进行签名。
对于远程软件包,默认配置将仅支持安装由受信任密钥签名的软件包
/etc/pacman.conf
SigLevel = Required DatabaseOptional
TrustedOnly 是一个默认编译的pacman参数。默认配置与使用全局选项相同
SigLevel = Required DatabaseOptional TrustedOnly
以上也可以在配置的更下方通过仓库级别实现,例如
[core] SigLevel = PackageRequired Include = /etc/pacman.d/mirrorlist
明确为该仓库的软件包添加签名检查,但不要求数据库已签名。这里的 Optional 将关闭此仓库的全局 Required。
TrustAll 选项用于调试目的,并且可以非常容易地信任未经验证的密钥。您应该为所有官方仓库使用 TrustedOnly。初始化密钥环
要初始化pacman密钥环,请运行
# pacman-key --init
管理密钥环
验证主密钥
密钥的初始设置通过以下方式实现
# pacman-key --populate
花时间验证 Master Signing Keys,因为它们用于共同签名(从而信任)所有其他打包者的密钥。
OpenPGP 密钥对于人类来说太大(2048 位或更高),无法直接操作,因此它们通常被哈希化以创建 40 位十六进制指纹,该指纹可用于手动检查两个密钥是否相同。指纹的最后八位数字用作密钥的名称,称为“(短)密钥 ID”(指纹的最后十六位数字是“长密钥 ID”)。
添加开发者密钥
官方的开发者和Package Maintainers的密钥由主密钥签名,因此您无需使用pacman-key自行签名。每当pacman遇到它不认识的密钥时,它会提示您从/etc/pacman.d/gnupg/gpg.conf中配置的keyserver下载,或者使用命令行上的--keyserver选项。维基百科维护了一个密钥服务器列表。
一旦下载了开发者的密钥,您就无需再次下载它,并且它可用于验证该开发者签名的任何其他软件包。
pacman-key --refresh-keys(以root身份)更新密钥。在执行--refresh-keys时,您的本地密钥也会在远程密钥服务器上查找,并且您会收到一条关于找不到它的消息。这无需担心。添加非官方密钥
此方法可用于将密钥添加到pacman密钥环,或启用已签名的非官方用户仓库。
首先,从其所有者那里获取密钥 ID(keyid)。然后使用以下两种方法之一将其添加到密钥环:
- 如果密钥在密钥服务器上找到,则使用以下命令导入:
# pacman-key --recv-keys keyid
- 如果提供了指向密钥文件的链接,则下载它,然后运行:
# pacman-key --add /path/to/downloaded/keyfile
建议验证指纹,就像对待任何主密钥或您将要签名的任何其他密钥一样。
$ pacman-key --finger keyid
最后,您必须在本地签名导入的密钥:
# pacman-key --lsign-key keyid
现在您信任此密钥来签名软件包。
使用gpg进行调试
出于调试目的,您可以使用gpg直接访问pacman的密钥环,例如:
# gpg --homedir /etc/pacman.d/gnupg --list-keys
技巧与提示
定期升级系统
通过 pacman#Upgrading packages 定期升级系统可以防止大多数签名错误。如果延迟不可避免且系统升级被长时间延迟,请手动同步软件包数据库并升级 archlinux-keyring 软件包,然后再升级系统。
# pacman -Sy --needed archlinux-keyring && pacman -Su
此命令不被视为部分升级,因为它会同步软件包数据库并在系统升级之前处理密钥环软件包。两者都必须在开始系统升级之前处理,以确保所有升级软件包的签名都能被正确验证。
archlinux-keyring-wkd-sync.service 和相关的 systemd timer 已默认创建并启用,无需任何用户干预即可解决 signature from "Some Developer <developer_email@archlinux.org>" is marginal trust(例如 BBS#278332)等问题,方法是每周一次获取已信任密钥的新签名。定期更新系统时间
当系统时间不正确时,签名密钥可能被视为过期(或无效),软件包的签名检查将失败。通过使用网络时间协议守护进程定期同步系统时钟。
故障排除
签名无效错误
pacman-key 依赖于系统时间。如果您的系统时钟未同步,系统安装/升级可能会失败,并出现以下错误:
error: PackageName: signature from "User <email@archlinux.org>" is invalid error: failed to commit transaction (invalid or corrupted package (PGP signature)) Errors occurred, no packages were upgraded.
如果使用 ntpd,请(以 root 身份)使用 ntpd -qg 然后是 hwclock -w 来纠正系统时间。
可以使用其他 NTP 客户端。请参阅 时间同步。
如果校正系统时钟不能解决故障,请尝试以下方法之一:
从缓存中移除软件包
某些软件包可能已损坏或未签名,导致失败。从系统缓存中删除每个有问题软件包 rm /var/cache/pacman/pkg/pkgname,以便重新下载,或清除整个缓存。
重置所有密钥
通过删除(以 root 身份)/etc/pacman.d/gnupg 目录并重新运行 pacman-key --init,然后是 pacman-key --populate 来重新添加默认密钥,从而移除或重置系统中安装的所有密钥。
禁用签名检查
如果您不关心软件包签名,可以完全禁用 OpenPGP 签名检查。编辑 /etc/pacman.conf,在 [options] 下添加以下行:
SigLevel = Never #LocalFileSigLevel = Optional #RemoteFileSigLevel = Required
您需要注释掉任何特定于仓库的 SigLevel 设置,因为它们会覆盖全局设置。这将导致没有签名检查,这是 pacman 4 之前的行为。如果您这样做,您就不需要使用pacman-key设置密钥环。如果您决定启用软件包验证,以后可以更改这些选项。
无法导入密钥
这个问题有多种可能的根源:
- 过时的 archlinux-keyring 软件包。
- 时钟设置不正确。
- 您的 ISP 阻止了用于导入 OpenPGP 密钥的端口。
- 您的pacman缓存包含先前尝试中的未签名软件包的副本。
dirmngr未正确配置。
在进行升级同步时,您可能会因为过时的 archlinux-keyring 软件包而卡住。
以下是一些根据您的情况可能有效的解决方案。
升级系统
首先尝试看是否可以通过升级系统来解决。
更换密钥服务器
如果您怀疑密钥服务器工作不正常,可以尝试切换到 Ubuntu 密钥服务器。为此,请编辑 /etc/pacman.d/gnupg/gpg.conf 并将 keyserver 行更改为:
keyserver hkp://keyserver.ubuntu.com
清理缓存的软件包
如果您怀疑 /var/cache/pacman/pkg/ 下的 pacman 缓存可能包含未签名软件包,请尝试手动清理缓存或运行:
# pacman -Sc
这将删除所有未安装的缓存软件包。
签名信任未知
有时在运行 pacman -Syu 时,您可能会遇到此错误:
error: package-name: signature from "packager" is unknown trust
这是因为软件包 package-name 中使用的packager的密钥在本地 pacman-key gpg 数据库中不存在和/或不被信任。Pacman 似乎并不总是能检查密钥是否已接收并标记为受信任,然后继续。这也可能是因为某个密钥在你将其添加到密钥链后已过期。
缓解方法:
- 在系统升级之前手动升级 archlinux-keyring 软件包,或
- 使用
pacman-key --refresh-keys刷新密钥,或 - 重置所有密钥,或
- 手动在本地签名不受信任的密钥(不推荐),或
- 暂时将
SigLevel设置为TrustAll(不推荐)。
最后两个选项会破坏信任链,应谨慎使用。
通过代理更新密钥
要使用代理更新密钥,必须在 /etc/gnupg/dirmngr.conf 和 /etc/pacman.d/gnupg/dirmngr.conf 中都设置 honor-http-proxy 选项。有关更多信息,请参阅 GnuPG#Use a keyserver。
honor-http-proxy 选项运行并失败,重启可能会解决问题。