警告:apt-key已经被弃用。请在trusted.gpg.d中管理密钥环文件。

127

我正在按照这份指南安装elasticsearch,但实际上elasticsearch并不是这个问题的重点。

在第一步中,我需要添加密钥:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

并收到以下消息:

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
安装过程很顺利,但由于它已被弃用,我正在寻找替换apt-key的新方法。(我安装软件包时没有问题。)从man apt-key我看到:

apt-key(8)将在Debian 11和Ubuntu 22.04中最后可用。

...

应与任何apt版本一起使用的二进制密钥环文件因此应始终使用gpg --export创建。

但它没有提到apt-key add的替代方法。我尝试过:
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --export

但是没有起作用。那么当apt-key被删除后,我在wget的管道符号后面该使用什么?


3
请查看此链接 - Raptor
11个回答

138
将密钥添加到/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

# Optional (you can find the email address / ID using `apt-key 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:
    (真正的密钥应该比这个长得多。这个太短了,不够安全。)
    -----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-----
    
然后,您可以用单个文件/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:行。

其他资源


40
е°†apt-keyеәѓз”ЁиЂЊжІҰжњ‰жЏђдң›еђЊж ·з”Ёж€·еЏ‹еӨҢдё”еү«йЂџзљ„е‘Ң令жқӨд»Әж›үе®ѓзљ„DebianеәЂеЏ‘иЂ…пәЊдёғNSAе’ЊFSBеё¦жқӨдғ†жһЃе¤§зљ„дңү利пәЃ - ankostis
5
我不是楼主,但感谢您的说明。由于使用 > 会请求提升权限,我使用 gpg-o 开关。因此,我将执行以下操作,而不是第一行:wget -O- https://example.com/EXAMPLE.gpg | sudo gpg --dearmor -o /usr/share/keyrings/EXAMPLE.gpg 这样可以在不需要 > 的情况下使用 sudo。 - Lockszmith
2
@ankostis 有什么比复制文件更用户友好和快捷的呢? - x-yuri
5
@x-yuri,这不仅仅是一个文件复制,还需要进行文件编辑以引用新文件,容易出错,导致人们简单地忽略警告 - 对于这样一个敏感问题来说,这种态度是不可接受的。 - ankostis
11
我追随事物的历史演变,但从用户的角度来看,简洁的 apt-key CRUD CLI 已被一系列宽泛的建议所取代,仅此而已。 - ankostis
显示剩余7条评论

20

!!已弃用且不安全!!

答案在这里找到: https://suay.site/?p=526

简而言之:

检索密钥并添加密钥:

curl -s URL | sudo gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/NAME.gpg --import

授权用户 _apt :

sudo chown _apt /etc/apt/trusted.gpg.d/NAME.gpg

6
与其使用 chown 命令更改文件所有权,参考文章建议将文件权限从 600 改为 644,这样该文件就变成了可读取的公共密钥。操作命令为:sudo chmod 644 /etc/apt/trusted.gpg.d/NAME.gpg - Peter
1
您可以通过以下方式避免保存额外的文件:curl -s URL | sudo gpg ...。此外,您还可以通过将NAME参数化来使脚本可复制粘贴。 - dibery
3
这是不安全的:密钥将被信任于所有存储库,甚至是您发行版自己的存储库。这正是为什么apt-key必须被弃用的原因。我在我的答案中解释了Debian推荐并由Signal使用的方法。 - FWDekker
2022年08月,这个答案有效! - Ivan Hanák
3
@IvanHanák 请注意,尽管此答案可行,但Debian手册(以及其他一些文献)建议不要这样做,因为它将信任该密钥用于所有存储库,而不仅仅是您在此处添加的存储库。 - FWDekker
如果curl失败,可以尝试使用wget -qO - URL | gpg ...... - bortunac

6

正如目前被接受的答案中所提到的,将密钥添加到/etc/apt/trusted.gpg.d 中是不安全的,因为它会为所有存储库添加密钥。这就是为什么apt-key会给出此警告的原因。

你可以使用以下更简单的解决方案:

curl -fsSL https://example.com/EXAMPLE.gpg | sudo gpg --dearmor -o /usr/share/keyrings/EXAMPLE.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/EXAMPLE.gpg] \
 https://example.com/apt stable main" \
| sudo tee -a /etc/apt/sources.list.d/EXAMPLE.list > /dev/null

sudo apt update
sudo apt install <package-name>

1
你可以使用 sudo gpg --dearmor -o /usr/share/keyrings/EXAMPLE.gpg(带或不带 --yes 自动覆盖)代替 sudo tee ... >/dev/null。请参阅我对另一个答案的回复 - Lockszmith
1
@Lockszmith,经过测试,我已根据您的建议修改了解决方案。 - Vamsi Nerella

4

来自man apt-key(Ubuntu 22.04)

如果您现有的apt-key add使用方式如下:

wget -qO- https://myrepo.example/myrepo.asc | sudo apt-key add -

那么您可以直接替换为以下内容(但请注意下面的建议):

wget -qO- https://myrepo.example/myrepo.asc | sudo tee /etc/apt/trusted.gpg.d/myrepo.asc


1
https://askubuntu.com/a/1307181/887635详细解释了为什么您的答案不安全且不应该被推荐。 - undefined

2
MX Linux有一个叫做“MX Fix GPG keys”的实用脚本来解决这个问题。由于它只是一个bash脚本,因此很可能在任何其他基于Debian的发行版上都可以正常工作。它在这里:https://github.com/MX-Linux/checkaptgpg

没试过,但还是谢谢你的分享。 - dibery

0

在尝试在Ubuntu 20.04中安装nodejsnpm时,我收到了他的警告。

更准确地说:

不是这样:

curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \

使用这个:
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \
echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \

因此,完整的安装脚本如下:

apt-get install -y nodejs \
apt-get install -y npm gnupg2 \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \
echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \

0

Linux用户通过UI快速解决此问题的方法:

  1. 搜索PPA并执行sudo add-apt-repository ppa:[MY_PPA](新的带有密钥环的PPA会自动添加并更新)

  2. sudo apt update

  3. 导航到“软件源- > PPA”,删除旧的PPA(确保新的PPA已正确添加并带有密钥环)

Software Sources


0

最近在尝试在我的EC2实例上安装Jenkins时遇到了这个错误。但是,通过以下步骤我成功解决了它:

  1. 运行以下命令将存储库密钥添加到系统中:

"wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key |sudo gpg --dearmor -o /usr/share/keyrings/jenkins.gpg"

您可能需要将jenkins替换为您要安装的软件包/软件。

  1. 运行以下命令将Debian软件包仓库地址附加到服务器的sources.list文件中:

"sudo sh -c 'echo deb [signed-by=/usr/share/keyrings/jenkins.gpg] http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'"

  1. 运行以下命令:

"apt update"

这样apt就会使用新创建的软件仓库。

  1. 继续尝试/重新尝试安装。

希望这能有所帮助 :) 来源: https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-22-04


感谢您的分享!如果将命令格式化为两个 `,那么格式会更好看。 - dibery

0

另一个示例片段,使用更新的deb822格式解决问题:

{ echo 'Types: deb'
  echo 'URIs: https://dl.k6.io/deb'
  echo 'Suites: stable'
  echo 'Components: main'
  echo 'Signed-By:'
  set -eo pipefail
  KEY=C5AD17C747E3415A3642D57D77C6C491D6AC1D69
  curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x$KEY" \
    | sed -e 's/^$/./g;s/^/ /g' 
} | sudo tee /etc/apt/sources.list.d/k6.sources

sudo apt-get update && sudo apt-get install k6

在这种情况下,我正在Ubuntu 22.04 LTS上安装k6.io CLI。根据需要进行调整。
请注意.sources——而不是.list
deb822的好处是软件包签名pubkey会内联在源文件中(仅验证此存储库的软件包-这比信任所有其他存储库更安全)。 内联在文件中可以避免使用| sudo tee命令:
Types: deb
URIs: https://dl.k6.io/deb
Suites: stable
Components: main
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: Hockeypuck 2.1.0-189-g15ebf24
 Comment: Hostname: 
 .
 xsFNBGBLRGQBEADCqEcl4YKYLAW8p/rEzBrDLi8fewyqPTLFWosWeu1a4fKzPcW8
 ggl/pjRcXxAxgCt1EhX9bjOrzavdnfnKLYuNkwR0vLWZtNEhAsOovsDzFF6n+WsN
 jtxL9nBZZ/7tgImxMUds8EXotx3R0Le5kbW0QWaWK8NDNayUChGF4ijM1dcacefA
 1ObrQvEKMybdFMxQM+oQjLeIe8TARaoATeLXh/LprNHqDWSAqE3KogChAMykp10i
...

因为他们的官方指南再次出问题,所以不得不快速制作以上内容。


0
我在使用在线提供的GPG密钥添加kubernetes-xenial存储库时,在运行Apple Silicon(M1 / aarch64 / arm64)上的Ubuntu 22.04.1环境中遇到了apt-key过时问题和警告。下面提供的解决方案与Vamsi Nerella在本帖子中提出的解决方案非常相似,但它包括一个显式示例 - 还包括创建新的密钥环目录(“/etc/apt/keyrings”)。

此解决方案还避免了“/etc/apt/trusted.gpg.d”密钥环目录的任何使用,一些消息来源说这对于解决导致首次弃用apt-key的问题是没有用的。

尽管在此示例末尾添加的软件包来自Kubernetes,但这种方法应该适用于其他软件包,就像Vamsi讨论的那样。

此解决方案与Promise Preston所提出的解决方案非常相似(请参见线程),但它包括对系统架构的引用,我需要为我的应用程序。也许其他人会从这个示例中受益。

不要这样做:

使用诸如vim或nano之类的文本编辑器创建'kubernetes.list'文件:

sudo vim /etc/apt/sources.list.d/kubernetes.list

将以下文本添加到新文件中:
deb http://apt.kubernetes.io/ kubernetes-xenial main

下载gpg密钥并使用已弃用的apt-key启用新存储库的使用:

sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
sudo apt-get update
sudo apt-get install kubeadm kubelet kubectl

使用这个:

sudo mkdir -p /etc/apt/keyrings

sudo curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes.gpg
     
sudo echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/kubernetes.gpg] \
  http://apt.kubernetes.io/ kubernetes-xenial main" \
  | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null

sudo apt-get update
sudo apt-get install kubeadm kubelet kubectl

如果你需要特定版本的 Kubernetes 包,例如 1.26(而不是最新版本),你可以在最后一步执行以下操作:
sudo apt-get install -y kubelet=1.26.0-00 kubeadm=1.26.0-00 kubectl=1.26.0-00

如前所述,您可以将此示例中使用的密钥替换为其他密钥('https://packages.cloud.google.com/apt/doc/apt-key.gpg')。在去除装甲的密钥中选择“kubernetes.gpg”是任意的。

参考资料:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接