pacman/软件包签名
为了保证软件包来自开发者, Pacman 使用信任网络中的 GnuPG 密钥进行软件包验证。这个网址记录了 Archlinux 的主密钥。其中至少三个主密匙被用来签署官方开发者和授信用户自己的密钥,而他们将用这些密钥签署自己的包。用户在配置 pacman-key 时也会生成一个唯一的密钥。所以信任网络也会把用户的密钥连接到五大主密钥上面。
信任网络示例:
- 自定义软件包: 用户自己构建软件包并用本地密钥签名。
- 非官方软件包: 开发者构建软并签名软件包。用户需要用自己的密钥签名开发者的密钥,将其变为可信。
- 官方软件包: 开发者构建软件包,而开发者的密钥已经被 Arch 主密钥签名。最终用户用自己的密钥签名主密钥,这样就能信任所有官方开发者。
配置[编辑 | 编辑源代码]
配置 pacman[编辑 | 编辑源代码]
/etc/pacman.conf
中的 SigLevel
配置用 pacman -S
安装软件时使用的检查级别。文件的注释中列出了几个可选设置,pacman.conf(5) § PACKAGE AND DATABASE SIGNATURE CHECKING 有详细介绍。签名检查可以全局配置或针对某个仓库配置。如果 SigLevel
在 [options] 节中进行了全局设置,那么所有的包都必须签名。如果使用 pacman.conf
中默认的 LocalFileSigLevel
,所有编译和用 pacman -U
安装的软件包都不需要使用 makepkg
进行签名。
默认的设置下,系统只安装被授信的密钥签署的软件包。
/etc/pacman.conf
SigLevel = Required DatabaseOptional
TrustedOnly
是 pacman 的默认设置。
默认配置的效果与下行等同:
SigLevel = Required DatabaseOptional TrustedOnly
上面这些也可以在仓库内部进行设置,比如:
[core] SigLevel = PackageRequired # ’Optional’ here would turn off a global ’Required’ for this repository Include = /etc/pacman.d/mirrorlist
软件仓库中的软件启用了签名验证,但是并不要求仓库数据库也被签名了。
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
运行时系统没有足够的熵,可能会需要很长时间。请在目标机器上安装 haveged 或 rng-tools。然后在用 root 权限执行pacman-key --init
前启动 haveged.service
。管理密钥[编辑 | 编辑源代码]
验证主密钥[编辑 | 编辑源代码]
通过以下命令进行配置:
# pacman-key --populate
该命令对 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
选项)下载。
下载开发者密钥后,以后都不需要下载。以后会用它验证所有这个开发者构建的软件包。
如果开发者和 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
提示和技巧[编辑 | 编辑源代码]
Upgrade system regularly[编辑 | 编辑源代码]
Upgrading the system regularly via pacman#Upgrading packages prevents most signing errors. If delay is unavoidable and system upgrade gets delayed for an extended period, manually sync the package database and upgrade the archlinux-keyring包 package before system upgrade:
# pacman -Sy archlinux-keyring && pacman -Su
This command is not considered a partial upgrade since it syncs the package database and upgrades the keyring package first. Both must be processed just before starting system upgrade to ensure signatures of all upgraded packages can be properly verified.
Update system time regularly[编辑 | 编辑源代码]
When the 系统时间 is faulty, signing keys could be considered expired (or invalid) and signature checks on packages will fail. Synchronize the system clock regularly by using the Network Time Protocol daemon.
问题解决[编辑 | 编辑源代码]
error: signature from xxx is invalid[编辑 | 编辑源代码]
Pacman-key 依赖于系统时间。如果系统时间是错误的,将会获得一个报错:
error: PackageName: signature from "User <email@archlinux.org>" is invalid error: failed to commit transaction (invalid or corrupted package (PGP signature)) Errors occured, no packages were upgraded.
如果是使用 ntpd, (root权限) 执行 ntpd -qg
,然后执行 hwclock -w
.
如果使用的是其他 NTP 客户端,请参考系统时间#时钟同步。
如果问题依然存在,请尝试下面方法:
删除报错的包[编辑 | 编辑源代码]
如果相同的包持续失败,并且您确定 pacman-key 的相关操作是正确的,可以尝试移除软件包 rm /var/cache/pacman/pkg/packagename
或者清空所有缓存,然后可以重新下载软件包。
重置所有密钥[编辑 | 编辑源代码]
如果要删除或重置系统,删除 /etc/pacman.d/gnupg
目录并重新运行 pacman-key --init
。通过 pacman-key --populate
重新添加默认密钥。
禁用签名检查[编辑 | 编辑源代码]
如果不在意软件包签名,可以完全禁用 PGP 签名检查,编辑 /etc/pacman.conf
并取消注释 [options] 下的如下行:
SigLevel = Never #LocalFileSigLevel = Optional #RemoteFileSigLevel = Required
需要同时注释掉单独软件源的 SigLevel 设置,因为他们会覆盖全局设置。
这样就不会进行任何签名检查,和 pacman 4 之前一样。如果这样,就不需要用 pacman-key 建立密钥环。
密钥导入失败[编辑 | 编辑源代码]
有三种可能的情况导致这个问题:
- 过期的archlinux-keyring包 包。
- 不正确的系统时间。
- 你的ISP屏蔽了用于导入 PGP keys 的端口。
- pacman 缓存中包含之前的未签名软件包
- 未正确设置
dirmngr
过期的 archlinux-keyring包 包可能会导致这个问题,根据情况采用下面的解决方法
切换公钥服务器[编辑 | 编辑源代码]
如果这样没有起作用,并且系统时间是正确的,你可以尝试切换到 Ubuntu 提供的公钥服务器(keyserver)。编辑 /etc/pacman.d/gnupg/gpg.conf
将 keyserver
行替换为
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.
honor-http-proxy
选项,执行失败,重启可能能够解决问题。