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
设置。
SigLevel
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
后跟 hwclock -w
校正系统时间(以 root 身份)。
可以使用其他 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
选项的情况下使用 pacman-key 并且失败,则重启可能可以解决问题。