Wyrd sisters

Ubuntu 22.04 and apt-key deprecation

by Ty Myrddin

Published on May 12, 2022

After upgrading to Ubuntu 22.04 from 20.04 several repositories are disabled, and deprecation warnings on its signing keys are given.

The apt-key deprecation message reads, "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8))", and "Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details."

Long story short, installing a key in the global keyring the way we used to mean that any packages signed by that key are trusted. The new [signed-by] option limits the damage when a repository's keys are compromised; the key cannot be used to forge packages unrelated to the repository itself and limits the damage done.

New repositories need to be signed in a different way, and existing keys need to be exported to /usr/share/keyrings and the associated source.list files adapted to reflect that change.

Below is a summarized version of applying the excellent instructions given by Debian and apt-key Is Deprecated. How To Add OpenPGP Repository Signing Keys Without It On Debian, Ubuntu, Linux Mint, Pop!_OS, Etc. for our setup in Ubuntu 22.04.

Note that curl can be used instead of wget, and that key extensions can also be .pgp, .asc, .key, .whatever, as long as it is a key in a format apt supports. If a key is not ascii-armored, gpg will exit successfully without changing anything. If apt chokes on the resulting key, it is likely because the key is in another format like the newer binary "keybox database" format, which apt does not support.

Adding keys the new way

Checking whether a key is armored:

    $ wget https://example.com/key/repo-key.gpg
    $ file repo-key.gpg

If the answer is repo-key.gpg: PGP public key block Public-Key (old) , then it is an armored key, but there is no harm in piping through --dearmor by default.

Armored keys:

    $ wget -O- <https://example.com/key/repo-key.gpg> | gpg --dearmor | sudo tee /usr/share/keyrings/<myrepository>-archive-keyring.gpg

Non-armored keys:

    $ wget -O- <https://example.com/key/repo-key.gpg> | sudo tee /usr/share/keyrings/<myrepository-archive-keyring.gpg>

Getting keys from a keyserver:

    $ sudo gpg --no-default-keyring --keyring /usr/share/keyrings/<myrepository>-archive-keyring.gpg --keyserver <hkp://keyserver.ubuntu.com:80> --recv-keys <fingerprint>

All keys will be stored in the /usr/share/keyrings/ folder to be used in adding the repository with the signed-by option in a sources.list file.

The sources.list files

Each of the sources.list files in /etc/apt/sources.list.d/ is to contain a [signed-by] reference to its own key:

    deb [arch=amd64 signed-by=/usr/share/keyrings/<myrepository>-archive-keyring.gpg] https://repository.example.com/debian/ stable main


An example of adding the repository for helm, signing with its armored key, the old way:

    $ curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
    $ echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

And the new way:

    $ wget -O- https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm-archive-keyring.gpg
    [sudo] password for [user]:
    $ echo "deb [signed-by=/usr/share/keyrings/helm-archive-keyring.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm.list

Exporting existing signatures

In order to be able to keep using the existing list of signatures and enable the disabled repositories again, it is necessary to export the individual keys to individual signature files. The below method also works for re-enabling repositories that use install scripts and do not have their signing keys listed on their sites, like for nordvpn and slack.

Moving keys from /etc/apt/trusted.gpg.d

First move all existing keyring files in /etc/apt/trusted.gpg.d/ to the (newly created) /usr/local/share/keyrings/ directory as-is.

    /etc/apt/trusted.gpg.d$ sudo mv repo-key.gpg /usr/share/keyrings/

Then, using an editor of choice, update all the corresponding .list files in /etc/apt/sources.list.d to have the [signed-by] field referencing its own key (as described above), and remove the hash that disabled the repository.

Exporting keys from /etc/apt/trusted.gpg

List all remaining keys:

    $ apt-key list

Remove all expired keys to shrink the list:

    $ sudo apt-key del [last 8 digits]

Export a useful key:

    $ apt-key export [last 8 digits]|sudo gpg --dearmor -o /usr/share/keyrings/<myrepository>-archive-keyring.gpg

Example exporting slack signing key in /etc/apt/trusted.gpg

    pub rsa4096 2014-01-13 [SCEA] [expired: 2019-01-12]
        418A 7F2F B0E1 E6E7 EABF 6FE8 C2E7 3424 D590 97AB
    uid [ expired] packagecloud ops (production key) <ops@packagecloud.io>

    pub rsa4096 2016-02-18 [SCEA]
        DB08 5A08 CA13 B8AC B917 E0F6 D938 EC0D 0386 51BD
    uid [ unknown] https://packagecloud.io/slacktechnologies/slack (https://packagecloud.io/docs#gpg_signing) 
    sub rsa4096 2016-02-18 [SEA]

Remove the expired key:

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

Export the useful key:

    $ apt-key export 038651BD|sudo gpg --dearmor -o /usr/share/keyrings/slack-archive-keyring.gpg

Change the slack.list file in /etc/apt/sources.list.d:

    deb [arch=amd64 signed-by=/usr/share/keyrings/slack-archive-keyring.gpg] https://packagecloud.io/slacktechnologies/slack/debian/ jessie main

Now remove the just exported key from /etc/apt/trusted.gpg:

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

And such for each key in the key list for trusted.gpg (not trusted.gpg.d). Test with sudo apt update all is well.

WHERE'S MY COW?! Wyrd Sisters