apt 中的keyrings(gpg)

十一月 25, 2025 #apt #gpg

apt gpg 作用

在 APT 的工作流程中,GPG 签名验证(signed-by= 指定的公钥)是在 “获取 Release 文件并校验其完整性与真实性” 阶段起作用的,具体发生在 apt update 的早期阶段,早于包列表下载和安装决策。

# 1. 故意破坏签名验证(删掉 keyring)
sudo rm /etc/apt/keyrings/docker.asc
sudo apt update 2>&1 | grep -A2 -B2 "GPG\|NO_PUBKEY"
# → 报错:The following signatures couldn't be verified...
# 2. 或临时禁用验证(危险!仅测试)
sudo apt -o Acquire::Check-Valid-Until=false \
         -o Acquire::AllowInsecureRepositories=true \
         -o Acquire::AllowDowngradeToInsecureRepositories=true \
         update

# → 仍可能失败,因为 signed-by 指定了强制 key,除非改 sources.list 去掉 signed-by

使用镜像源(mirror)的 APT 服务,还能正常 GPG 认证吗?

验证实操(推荐)

# 1. 下载 InRelease(中科大镜像)
wget https://mirrors.ustc.edu.cn/docker-ce/linux/debian/dists/bookworm/InRelease

# 2. 用你本地的 docker.asc 公钥验证
gpg --keyring /etc/apt/keyrings/docker.asc \
    --verify InRelease
# 应输出:Good signature from "Docker Release (CE deb) ..."

# 3. 对比原始源(应完全一致)
diff InRelease \
  <(curl -s https://download.docker.com/linux/debian/dists/bookworm/InRelease)
# → 无输出(完全相同)

报错排查

gpg: [don't know]: invalid packet (ctb=2d)
gpg: keydb_search failed: 无效的数据包
gpg: 无法检查签名:缺少公钥

先 dearmor 成二进制,再验证(推荐)

# 1. 确保 docker.asc 是 ASCII-armored(检查开头)
head -n2 /etc/apt/keyrings/docker.asc
# 应输出:-----BEGIN PGP PUBLIC KEY BLOCK-----
# 2. 转成二进制格式(例如 docker.gpg)
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg /etc/apt/keyrings/docker.asc
# 3. 用 .gpg(二进制)验证
gpg --keyring /etc/apt/keyrings/docker.gpg \
    --verify ./InRelease
# ✅ 此时应显示:Good signature from "Docker Release (CE deb)..."

不指定 --keyring,而是先导入公钥到临时 keyring

# 创建临时 home
mkdir -p /tmp/gpghome && chmod 700 /tmp/gpghome
# 导入公钥(自动 dearmor)
gpg --homedir /tmp/gpghome --import /etc/apt/keyrings/docker.asc
# 用临时 keyring 验证
gpg --homedir /tmp/gpghome --verify ./InRelease
# 清理
rm -rf /tmp/gpghome

为什么 apt 本身能工作?

因为 APT 内部 自动处理 dearmor! 当你在 sources.list 写:

deb [signed-by=/etc/apt/keyrings/docker.asc] ...

APT 会: 检测 .asc 后缀或文件内容含 -----BEGIN → 自动 dearmor 后加载

不依赖 gpg CLI 行为 → 所以 apt update 正常,但你手动用 gpg --keyring 却失败。

# 查看二进制 keyring 内容
gpg --keyring /etc/apt/keyrings/docker.gpg --list-packets </dev/null
# 应显示 pub, sub 等 key packets,无 "invalid packet"

# 或直接看指纹(对比官网)
gpg --keyring /etc/apt/keyrings/docker.gpg --with-fingerprint --list-keys
# 应含:7EA0 A9C3 F273 FCD8 (即你日志中的 RSA 密钥 ID)

总结: