Fix "apt-key is deprecated" warnings

I’m using Ubuntu LTS version on my server. Previously it was 20.04, but after upgrading to 22.04, every time I update the system it reports a bunch of warning messages. Although it doesn’t affect the functionality, there must be something wrong, and as an obsessive-compulsive person I had to find out what it was. I found out that the problem is related to the deprecation of apt-key, and the whole apt signature system has a new configuration scheme. Today I’ll share with you the process of dealing with it.

Every time I run apt-get update after upgrading my system, I get the following warning:

W: http://security.ubuntu.com/ubuntu/dists/jammy-security/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/a
pt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
W: http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted
.gpg), see the DEPRECATION section in apt-key(8) for details.
W: http://archive.ubuntu.com/ubuntu/dists/jammy-updates/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt
/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
W: http://archive.ubuntu.com/ubuntu/dists/jammy-backports/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/a
pt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

It says that the OpenPGP public keys of the above repositories are still stored in trusted.gpg file, which is no longer recommended, please refer to the DEPRECATION section of the apt-key(8) manual for details.

I read the manual and it mainly says that it is now recommended to save the OpenPGP public key to the /etc/apt/trusted.gpg.d directory, using a separate file for each key. Now the question is how to extract the above key.

apt-key has a list subcommand:

$ sudo apt-key list
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
/etc/apt/trusted.gpg
--------------------
pub   rsa4096 2018-09-17 [SC]
      F6EC B376 2474 EDA9 D21B  7022 8719 20D1 991B C93C
uid           [ unknown] Ubuntu Archive Automatic Signing Key (2018) <[email protected]>

To export a key, you need to use its ID, that is, the last two parts of the second line, 991B and C93C, with the apt-key export command.

$ sudo apt-key export 991BC93C
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBFufwdoBEADv/Gxytx/LcSXYuM0MwKojbBye81s0G1nEx+lz6VAUpIUZnbkq
...
-----END PGP PUBLIC KEY BLOCK-----

The part between BEGIN and END is the exported public key. Since apt-key is no longer recommended, another warning message is output on the screen.

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

The apt-key output is in ASCII format, but we need to save it in binary format, so we need to use the gpg utility to convert it.

sudo apt-key export 991BC93C | sudo gpg --dearmour \
  -o /etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg

-o means save the converted content to the specified path. If you update the system after this step, you will not see the warning above. We can now delete the public key from trusted.gpg.

sudo apt-key del 991BC93C

Actually, on my server, the file ubuntu-keyring-2018-archive.gpg~ already exists in the trusted.gpg.d directory. I’m not sure how it was created. Just remove the ~ at the end of the file name.

Now updating the system there will be no warning.

$$ sudo aptitude update
Hit http://archive.ubuntu.com/ubuntu jammy InRelease
Get: 1 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [108 kB]
Get: 2 https://deb.goaccess.io jammy InRelease [3062 B]
Get: 3 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get: 4 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Hit https://apt.syncthing.net syncthing InRelease
Fetched 340 kB in 1s (345 kB/s)

Going from trusted.gpg to trusted.gpg.d is an improvement because it is easier to see what keys are currently available and easier to add and remove them. However, there is another security concern with this approach, which is called cross-signing.

If we add two repositories A and B, then we need to add two public keys \( G_A \) and \( G_B \). Once the public keys are added, the system will trust \( G_A \) and \( G_B \), and even if the software in repository B is signed with the key of A, the corresponding software can be installed normally. This is called cross-signing.

In order for the system to operate safely, we should adhere to the principle of least trust. This means that \( G_A \) can only be used for software in repository A, and \( G_B \) as well. The original global trust approach of using trusted.gpg and trusted.gpg.d is then not recommended.

I have Syncthing on my system, and since the official Ubunut repository has a lower version, I’ve configured the official Syncthing APT source, so I’ll use that as an example.

First create the /etc/apt/sources.list.d/syncthing.list file with the following contents:

deb [signed-by=/etc/apt/keyrings/syncthing.gpg] https://apt.syncthing.net/ syncthing stable

Then download the OpenPGP public key:

sudo curl -o /etc/apt/keyrings/syncthing.gpg https://syncthing.net/release-key.gpg

Here signed-by is used to specify the path to the OpenPGP public key file, which I saved to the /etc/apt/keyrings/ directory. This is also the recommended location for APT systems. With this configuration, syncthing.gpg can only be used to verify software from the official Syncthing repositories, and Syncthing’s signing key will not be used to sign software from other repositories, even if it is accidentally leaked.

Although it is relatively unlikely that such an attack can be realized, security is not a trivial matter. So it is recommended that everyone migrates to the latest signed-by scheme as soon as possible.

In addition to software signing, GPG is used in a variety of ways. The closest to us is Git. We can sign Git commits with our private key, and others can verify it with the public key we publish. We can also publish our GPT public key to GitHub, which will automatically display a verification flag. However, ordinary developers rarely generate their own GPG public key. Later, OpenSSH also supports signing arbitrary data with SSH keys, which can replace GPG to some extent. most developers should have their own SSH keys, and even Git supports signing with SSH keys.