pacman/软件包签名
为了确定软件包是否是真实的,pacman 使用 OpenPGP 密钥在一个 信任网络 模型中。当前的主签名密钥可以在这里找到。至少使用这三个主签名密钥来签署开发者和软件包维护者自己的密钥。然后,他们使用这些密钥来签署他们的软件包。每个用户也有一个唯一的 OpenPGP 密钥,这个密钥在你配置 pacman-key(8) 时生成。正是这个信任网络将用户的密钥链接到主密钥。
信任网络示例
- 自定义软件包:使用本地密钥制作和签名的软件包。
- 非官方软件包:由开发者制作和签名的软件包。然后,使用本地密钥来签署开发者的密钥。
- 官方软件包:由开发者制作和签名的软件包。开发者的密钥由 Arch Linux 主密钥签名。您使用您的密钥签署了主密钥,并且您信任他们为开发者担保。
设置
配置 pacman
/etc/pacman.conf
中的 SigLevel
选项决定了使用 pacman -S
安装软件包所需的信任级别。有关 SigLevel
的详细解释,请参阅 pacman.conf(5) § 软件包和数据库签名检查,以及文件注释。可以全局设置签名检查,也可以按仓库设置。如果在 [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
当提示时,花时间验证主签名密钥,因为这些密钥用于共同签名(并因此信任)所有其他打包者的密钥。
OpenPGP 密钥对于人类来说太大了(2048 位或更多),无法直接使用,因此它们通常被哈希以创建一个 40 位十六进制数字的指纹,该指纹可以用于手动检查两个密钥是否相同。指纹的最后八位数字作为密钥的名称,称为“(短)密钥 ID”(指纹的最后十六位数字将是“长密钥 ID”)。
添加开发者密钥
官方开发者和软件包维护者的密钥由主密钥签名,因此您无需使用 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#升级软件包 定期升级系统可以防止大多数签名错误。如果延迟是不可避免的并且系统升级被延迟了很长时间,请手动同步软件包数据库并在系统升级之前升级 archlinux-keyring 软件包
# pacman -Sy --needed archlinux-keyring && pacman -Su
此命令不被认为是部分升级,因为它首先同步软件包数据库并升级密钥环软件包。两者都必须在启动系统升级之前处理,以确保可以正确验证所有升级软件包的签名。
archlinux-keyring-wkd-sync.service
和相关的 systemd 计时器 已被创建并默认启用,解决了 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,请使用 ntpd -qg
更正系统时间(以 root 身份),然后执行 hwclock -w
。
可以使用其他 NTP 客户端。请参阅时间同步。
如果更正系统时钟无法解决故障,请尝试以下方法之一
从缓存中移除软件包
某些软件包可能已损坏或可能未签名,从而导致失败。从系统缓存 rm /var/cache/pacman/pkg/pkgname
中删除每个有问题的软件包,以便重新下载它,或清除整个缓存。
重置所有密钥
通过删除 /etc/pacman.d/gnupg
目录(以 root 身份)并重新运行 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
清理缓存的软件包
如果您怀疑您的 pacman 缓存 /var/cache/pacman/pkg/
可能包含未签名的软件包,请尝试手动清理缓存或运行
# 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#使用密钥服务器。
honor-http-proxy
选项的情况下使用并失败,则重新启动可能会解决问题。