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

Jump to content

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

From ArchWiki
< Pacman (简体中文)

相关文章

- GnuPG
- DeveloperWiki:Package signing

翻译状态：本文是 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`运行时系统没有足够的熵，可能会需要很长时间。请在目标机器上安装 haveged 或 rng-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@archlinux.org>" 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 <Some.Person@example.com>" 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.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.

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

## 参阅

- DeveloperWiki:Package Signing Proposal for Pacman
- Pacman Package Signing – 1: Makepkg and Repo-add
- Pacman Package Signing – 2: Pacman-key
- Pacman Package Signing – 3: Pacman
- Pacman Package Signing – 4: Arch Linux

Category:

- Package management (简体中文)