Fedora 作为红帽公司主导的社区发行版,其软件仓库中的每一个 RPM 包都带有 GPG 签名。这套签名体系是防止软件包在传输或镜像过程中被篡改的核心防线。理解签名验证的原理与操作方法,对于排查安装失败、接入第三方仓库以及安全审计都非常有帮助。本文将围绕 RPM 包签名的生成机制、验证命令、dnf 的自动验签行为以及第三方仓库的安全实践展开详细说明。

RPM 包签名的工作原理
RPM 包的签名本质上是一段由 Fedora 构建系统的私钥对包头与包内容生成的 GPG 签名,它被嵌入在 RPM 文件内部。当系统安装该包时,包管理器会使用预先导入的公钥检查这段签名:如果包内容与签名不匹配,或者本地没有对应的公钥,安装就会被拒绝或给出警告。
Fedora 每个发行版本都会发布独立的 GPG 密钥,例如 Fedora 40 使用的是 Fedora (40) <fedora@fedoraproject.org> 这样的密钥身份。这些公钥默认存放在系统的 RPM 数据库中,也以文件形式保存在 /etc/pki/rpm-gpg/ 目录下。可以用下面这条命令查看当前系统已经导入的公钥列表:
rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n'输出结果中会列出每个公钥的指纹摘要。如果想查看完整的 40 位指纹,可以再用 --qf '%{SIGPGP:pgpsig}\n' 扩展查询,或者在导入前用 gpg --show-keys 检查密钥文件,确认指纹与官网公布的一致后再导入,这是防止中间人替换密钥的关键步骤。
手动验证单个 RPM 包的签名
有时你需要安装一个从镜像站或朋友那里拿到的 RPM 文件,这时手动验签是必要的。最直接的方式是使用 rpm -K 命令,它会检查包的摘要与签名状态:
# 检查签名(需要先导入对应公钥) rpm -K zsh-5.9-2.fc40.x86_64.rpm # 未导入公钥时的输出示例: # zsh-5.9-2.fc40.x86_64.rpm: digests SIGNATURES NOT OK # 导入 Fedora 官方公钥 rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-40-primary # 再次验证,成功时输出: # zsh-5.9-2.fc40.x86_64.rpm: digests signatures OK
注意 digests signatures OK 中两个词的含义不同:digests 表示包内各文件的哈希摘要校验通过,signatures 表示 GPG 签名验证通过。如果只显示 digests OK 而签名报 NOKEY,说明本地缺少公钥;如果显示 NOT OK 或 BADSIG,则说明包被改动过或密钥不对,务必拒绝安装。
除了 rpm 自带的机制,也可以先用命令提取签名信息再交给 gpg 处理。不过对日常使用来说,rpm -K 加上 rpm --import 已经覆盖了绝大多数场景。还有一个常见误区是直接安装 .src.rpm 时忽略了验签,源码包同样有签名,重建二进制前也应该先执行 rpm -K 确认。
dnf 与 yum 的自动验签行为
正常情况下用户不需要手动验签,因为 dnf 在每次安装时都会自动完成验证。仓库配置文件 /etc/yum.repos.d/*.repo 中有一个 gpgcheck 参数,Fedora 官方仓库默认设置为 1,即强制验签。你可以查看官方仓库的定义:
cat /etc/yum.repos.d/fedora.repo # 关键片段 [fedora] name=Fedora $releasever - $basearch gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-primary
当系统第一次使用某个仓库时,dnf 会提示是否导入该仓库的 GPG 公钥,并显示密钥指纹。此时一定要核对指纹是否与 Fedora 官网 security 页面公布的一致,确认后再选择同意导入。导入后密钥会持久保存,后续安装不再重复询问。
需要警惕的是一些第三方教程会让你把 gpgcheck=0 写进配置以跳过验证,这等于完全放弃了对包完整性的检查,攻击者可以向仓库推送任意篡改过的软件。正确的做法是为第三方仓库配置其官方发布的 gpgkey 地址,让 dnf 自动导入并验证。此外,localpkg_gpgcheck 选项可以控制对本地 RPM 文件的验签行为,在安全要求较高的环境中建议在 /etc/dnf/dnf.conf 中将其设为 1。
密钥轮换与常见问题排查
Fedora 每个版本发布新的密钥,旧版本的密钥在版本生命周期结束后停止使用。升级系统后如果遇到 GPG key retrieval failed 或 public key not available 错误,通常是密钥文件缺失或 gpgkey 配置里的 URL 失效。解决方法是手动导入对应版本的密钥:
# 从官方地址导入 rpm --import https://fedoraproject.org/fedora.gpg # 或者从本地密钥目录导入 ls /etc/pki/rpm-gpg/ rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-latest-primary
如果怀疑系统导入过不可信的密钥,可以查询并删除它。先用 rpm -q gpg-pubkey --qf '%{version}-%{release} %{summary}\n' 找到可疑密钥的标识,再用 rpm -e gpg-pubkey-密钥短ID 移除。定期审计已导入的公钥列表是一个好习惯,尤其是在接入了多个第三方仓库的机器上。
最后补充一点:RPM 的 GPG 签名与包内文件的哈希校验是两层独立的保护。即使签名验证通过,dnf 在解包时仍会逐个校验文件摘要,任何一环失败都会中止安装。理解这套双层机制,就能在遇到安装报错时快速定位问题出在密钥、签名还是包本身,避免盲目关闭安全选项。