将密钥添加到
/etc/apt/trusted.gpg.d
是不安全的,因为它会为所有存储库添加密钥。
这正是为什么
apt-key
必须被弃用的原因。
简短版本
做类似于Signal的操作。
如果您想要在/etc/apt/sources.list.d/EXAMPLE.list
中列出的存储库中使用位于https://example.com/EXAMPLE.gpg
的密钥,请使用以下命令:
sudo mkdir -m 0755 -p /etc/apt/keyrings/
wget -O- https://example.com/EXAMPLE.gpg | \
gpg --dearmor | \
sudo tee /etc/apt/keyrings/EXAMPLE.gpg > /dev/null;
sudo chmod 644 /etc/apt/keyrings/EXAMPLE.gpg
echo "deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt stable main" | \
sudo tee /etc/apt/sources.list.d/EXAMPLE.list;
sudo chmod 644 /etc/apt/sources.list.d/EXAMPLE.list
sudo apt-key del support@example.com
长版本
尽管废弃通知建议将密钥添加到/etc/apt/trusted.gpg.d
,但这是一种不安全的解决方案。引用Linux Uprising的这篇文章:
更改的原因是,当将用于签署APT存储库的OpenPGP密钥添加到/etc/apt/trusted.gpg
或/etc/apt/trusted.gpg.d
时,APT会无条件地信任该密钥,即使在系统上配置了其他没有signed-by
选项的官方Debian / Ubuntu存储库。结果是,任何非官方的APT存储库,只要其签名密钥添加到/etc/apt/trusted.gpg
或/etc/apt/trusted.gpg.d
,就可以替换系统上的任何软件包。因此,出于安全原因(您的安全),进行了此更改。
适当的解决方案在
那篇Linux Uprising文章和
Debian Wiki中有详细说明:将密钥存储在
/etc/apt/keyrings/
(如果密钥由软件包管理,则存储在
/usr/share/keyrings/
),然后在apt源列表中引用该密钥。
因此,适当的方法如下:
如果PGP密钥的目录不存在,则创建该目录并设置其权限。
每个步骤都会明确设置
推荐的权限,因为有些人可能设置了奇怪的
umask。
在Debian 12和Ubuntu 22.04之前的版本中,只有在创建目录时才是必需的,但无论如何运行此行都不会有害。
sudo mkdir -m 0755 -p /etc/apt/keyrings/
从
https://example.com/EXAMPLE.gpg
下载密钥并将其存储在
/etc/apt/keyrings/EXAMPLE.gpg
中。
Debian wiki解释,您应该解码密钥(即将其从base64转换为二进制)以与旧软件兼容。
> /dev/null
只是阻止二进制密钥在终端中显示。
wget -O- https://example.com/EXAMPLE.gpg | \
gpg --dearmor | \
sudo tee /etc/apt/keyrings/EXAMPLE.gpg > /dev/null;
sudo chmod 644 /etc/apt/keyrings/EXAMPLE.gpg
可选地,您可以通过运行
file /etc/apt/keyrings/EXAMPLE.gpg
并检查输出来验证您下载的文件确实是PGP密钥。
将密钥添加到存储库使用的源文件中。
在
/etc/apt/sources.list.d/
中找到适当的文件并编辑它,以便它链接到您刚刚添加的密钥环。
如果该文件不存在,您可以创建一个。
最后,它应该看起来像这样:
deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt stable main
(可选)
如果之前添加过密钥,请从
apt-key
中删除它。
运行
sudo apt-key list
列出所有密钥,并找到先前添加的密钥。
使用密钥的电子邮件地址或指纹,运行
sudo apt-key del support@example.com
。
使用更新的DEB822格式
使用更新的DEB822格式来指定apt软件源更加美观和易于使用,但并不是所有平台上的所有工具都完全支持该格式。
简化版本
不要运行上述提到的脚本,而是运行
echo "Types: deb
URIs: https://example.com/apt
Suites: stable
Components: main
Signed-By:
$(wget -O- https://example.com/EXAMPLE.gpg | sed -e 's/^$/./' -e 's/^/ /')" | sudo tee /etc/apt/sources.list.d/EXAMPLE.sources > /dev/null
sudo chmod 644 /etc/apt/sources.list.d/EXAMPLE.sources
长版本
除了在sources.list.d
中使用单行格式的源,您还可以使用更新的多行格式DEB822。
这种格式对人类和计算机来说更易读,并且自2015年以来一直在apt中可用。
Debian和Ubuntu计划从2023年底开始使用DEB822作为默认格式。
Repolib的文档对新格式的动机进行了很好的比较和介绍。。
此外,apt 2.2.4及更高版本支持直接在sources.list
中嵌入公钥。
如果您维护在第三方存储库上托管的软件包,请考虑为用户提供一个可选的填写好的DEB822 .sources
。
目前在这个答案中将这部分内容单独列出来的原因是,一些仍然得到支持的Debian和Ubuntu版本会预装旧版本的apt工具。
具体来说,Debian 9(EOL:2024-06-30)和Ubuntu 20.04(EOL:2025-05-29)版本太旧了,但Debian 10及更高版本以及Ubuntu 22.04及更高版本是可以使用的。
此外,一些解析源文件而不是包装apt的工具可能还不完全支持所有这些功能。
要从单行格式切换到DEB822格式,假设您有以下两个文件:
/etc/apt/sources.list.d/example.list
:
deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt stable main
/etc/apt/keyrings/EXAMPLE.gpg
:
(真正的密钥应该比这个长得多。这个太短了,不够安全。)
mI0EZWiPbwEEANPyu6pUQEydxvf2uIsuuYOernFUsQdd8GjPE5yjlxP6pNhVlqNo
0fjB6yk91pWsoALOLM+QoBp1guC9IL2iZe0k7ENJp6o7q4ahCjJ7V/kO89mCAQ09
yHGNHRBfbCo++bcdjOwkeITj/1KjYAfQnzH5VbfmgPfdWF4KqS/TmJP9ABEBAAG0
G0phbmUgRG9lIDxqYW5lQGV4YW1wbGUub3JnPojMBBMBCgA2FiEEK8v49DttJG7D
35BwcvTpbeNfCTgFAmVoj28CGwMECwkIBwQVCgkIBRYCAwEAAh4BAheAAAoJEHL0
6W3jXwk4YLID/0arCzBy9utS8Q8g6FDtWyJVyifIvdloCvI7hqH51ZJ+Zb7ZLwwY
/p08+Xnp4Ia0iliwqSHlD7j6M8eBy/JJORdypRKqRIbe0JQMBEcAOHbu2UCUR1jp
jJTUnMHI0QHWQEeEkzH25og6ii8urtVGv1R2af3Bxi9k4DJwzzXc5Zch
=8hwj
然后,您可以用单个文件
/etc/apt/sources.list.d/example.sources
替换这两个文件。
Types: deb
URIs: https://example.com/apt
Suites: stable
Components: main
Signed-By:
-----BEGIN PGP PUBLIC KEY BLOCK-----
.
mI0EZWiPbwEEANPyu6pUQEydxvf2uIsuuYOernFUsQdd8GjPE5yjlxP6pNhVlqNo
0fjB6yk91pWsoALOLM+QoBp1guC9IL2iZe0k7ENJp6o7q4ahCjJ7V/kO89mCAQ09
yHGNHRBfbCo++bcdjOwkeITj/1KjYAfQnzH5VbfmgPfdWF4KqS/TmJP9ABEBAAG0
G0phbmUgRG9lIDxqYW5lQGV4YW1wbGUub3JnPojMBBMBCgA2FiEEK8v49DttJG7D
35BwcvTpbeNfCTgFAmVoj28CGwMECwkIBwQVCgkIBRYCAwEAAh4BAheAAAoJEHL0
6W3jXwk4YLID/0arCzBy9utS8Q8g6FDtWyJVyifIvdloCvI7hqH51ZJ+Zb7ZLwwY
/p08+Xnp4Ia0iliwqSHlD7j6M8eBy/JJORdypRKqRIbe0JQMBEcAOHbu2UCUR1jp
jJTUnMHI0QHWQEeEkzH25og6ii8urtVGv1R2af3Bxi9k4DJwzzXc5Zch
=8hwj
-----END PGP PUBLIC KEY BLOCK-----
重要的是,你
必须每行至少缩进一个空格,并且你
必须用缩进的
.
代替空行。
(删除空行将使密钥无效。)
上面的脚本正是这样做的。
最后,如果你有一个指定了确切路径的存储库,比如
deb [signed-by=/etc/apt/keyrings/EXAMPLE.gpg] https://example.com/apt deb/
那么你的DEB822必须设置Suites: deb/
(必须以/
结尾),并且它不能有Components:
行。
其他资源