iTranslated by AI
Managing APT Repository Keys After apt-key Deprecation
As those using the official Debian probably already know, the apt-key command, used by the APT package management tool to manage OpenPGP public keys for electronic signatures, has been deprecated. Furthermore, it seems the apt-key command will be removed in Debian 12.
Ubuntu, being a Debian-based distribution, naturally follows suit.
$ sudo apt update
...
W: https://download.docker.com/linux/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.
I don't recall seeing this kind of warning until Ubuntu 21.10, so I had been ignoring it. But, well, it's about time to address it. Fortunately, handling third-party public keys doesn't seem to be too difficult in APT 2.4 and later[1].
In this article, I will introduce the steps for importing public keys and registering repositories, using the Docker Engine APT installation procedure on Ubuntu 22.04 LTS and later as an example.
Previous Installation Procedure
Although it seems to have been removed now, the old instructions on the “Install Docker Engine on Ubuntu” page were as follows:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
to register the public key, and
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
to register the repository. In this state, you could install it with:
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Third-party OpenPGP public keys imported via the apt-key command are stored in the /etc/apt/trusted.gpg keyring file. You can view the contents of this file using the apt-key list command.
$ 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 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown ] Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
...
Whoa. A warning appeared right away (lol).
Importing Third-Party OpenPGP Public Keys
On the current "Install Docker Engine on Ubuntu" page, the procedure for importing the OpenPGP public key is as follows:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
To explain briefly, the first half of the command downloads the public key, and the second half stores it in the /usr/share/keyrings/docker-archive-keyring.gpg file. Since the file downloaded in the first half is in ASCII Armor format text, the gpg command in the second half converts it using --dearmor (i.e., into binary) before storing it. The key point here is that the public key data is placed as a standalone file rather than being added to a keyring file via the apt-key add command.
ASCII Armor is Perfectly Fine
Looking at the apt-key manual with the man command, it says:
Make sure to use the "asc" extension for ASCII armored keys and the "gpg" extension for the binary OpenPGP format (also known as "GPG key public ring"). The binary OpenPGP format works for all apt versions, while the ASCII armored format works for apt version >= 1.4.
So, in current versions, it seems perfectly fine to store it in ASCII Armor format. Furthermore, regarding the location of the public key files:
Recommended: Instead of placing keys into the /etc/apt/trusted.gpg.d directory, you can place them anywhere on your filesystem by using the Signed-By option in your sources.list and pointing to the filename of the key. See sources.list(5) for details. Since APT 2.4, /etc/apt/keyrings is provided as the recommended location for keys not managed by packages.
It is recommended to place them in the /etc/apt/keyrings/ directory in combination with the Signed-By option (described later). Therefore, the previous command can be replaced without even needing the gpg command:
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker-key.asc
(The output filename is arbitrary). Simple! ♪
[Promotion] Pre-verify public keys with gpgpdump
You can use my gpgpdump command to analyze and display any OpenPGP data on the web. For example:
$ gpgpdump fetch -u --indent 2 https://download.docker.com/linux/ubuntu/gpg
Public-Key Packet (tag 6) (525 bytes)
Version: 4 (current)
Public key creation time: 2017-02-22T18:36:26Z
Public-key Algorithm: RSA (Encrypt or Sign) (pub 1)
RSA public modulus n (4096 bits)
RSA public encryption exponent e (17 bits)
User ID Packet (tag 13) (43 bytes)
User ID: Docker Release (CE deb) <docker@docker.com>
Signature Packet (tag 2) (567 bytes)
Version: 4 (current)
Signiture Type: Positive certification of a User ID and Public-Key packet (0x13)
Public-key Algorithm: RSA (Encrypt or Sign) (pub 1)
Hash Algorithm: SHA2-512 (hash 10)
Hashed Subpacket (33 bytes)
Signature Creation Time (sub 2): 2017-02-22T19:34:24Z
Key Flags (sub 27) (1 bytes)
Flag: This key may be used to certify other keys.
Flag: This key may be used to sign data.
Flag: This key may be used to encrypt communications.
Flag: This key may be used to encrypt storage.
Flag: This key may be used for authentication.
Preferred Symmetric Algorithms (sub 11) (4 bytes)
Symmetric Algorithm: AES with 256-bit key (sym 9)
Symmetric Algorithm: AES with 192-bit key (sym 8)
Symmetric Algorithm: AES with 128-bit key (sym 7)
Symmetric Algorithm: CAST5 (128 bit key, as per) (sym 3)
Preferred Hash Algorithms (sub 21) (4 bytes)
Hash Algorithm: SHA2-512 (hash 10)
Hash Algorithm: SHA2-384 (hash 9)
Hash Algorithm: SHA2-256 (hash 8)
Hash Algorithm: SHA2-224 (hash 11)
Preferred Compression Algorithms (sub 22) (4 bytes)
Compression Algorithm: ZLIB <RFC1950> (comp 2)
Compression Algorithm: BZip2 (comp 3)
Compression Algorithm: ZIP <RFC1951> (comp 1)
Compression Algorithm: Uncompressed (comp 0)
Features (sub 30) (1 bytes)
Flag: Modification Detection (packets 18 and 19)
Key Server Preferences (sub 23) (1 bytes)
Flag: No-modify
Unhashed Subpacket (10 bytes)
Issuer (sub 16): 0x8d81803c0ebfcd88
Hash left 2 bytes
b2 c9
RSA signature value m^d mod n (4094 bits)
Public-Subkey Packet (tag 14) (525 bytes)
Version: 4 (current)
Public key creation time: 2017-02-22T18:36:26Z
Public-key Algorithm: RSA (Encrypt or Sign) (pub 1)
RSA public modulus n (4096 bits)
RSA public encryption exponent e (17 bits)
Signature Packet (tag 2) (1086 bytes)
Version: 4 (current)
Signiture Type: Subkey Binding Signature (0x18)
Public-key Algorithm: RSA (Encrypt or Sign) (pub 1)
Hash Algorithm: SHA2-256 (hash 8)
Hashed Subpacket (9 bytes)
Signature Creation Time (sub 2): 2017-02-22T18:36:26Z
Key Flags (sub 27) (1 bytes)
Flag: This key may be used to sign data.
Unhashed Subpacket (553 bytes)
Issuer (sub 16): 0x8d81803c0ebfcd88
Embedded Signature (sub 32) (540 bytes)
Signature Packet (tag 2) (540 bytes)
Version: 4 (current)
Signiture Type: Primary Key Binding Signature (0x19)
Public-key Algorithm: RSA (Encrypt or Sign) (pub 1)
Hash Algorithm: SHA2-256 (hash 8)
Hashed Subpacket (6 bytes)
Signature Creation Time (sub 2): 2017-02-22T18:36:26Z
Unhashed Subpacket (10 bytes)
Issuer (sub 16): 0x7ea0a9c3f273fcd8
Hash left 2 bytes
d5 60
RSA signature value m^d mod n (4095 bits)
Hash left 2 bytes
f2 b8
RSA signature value m^d mod n (4095 bits)
Something like that. This allows you to pre-verify the details of the public key you are about to import.
Furthermore, by adding the --raw option to the gpgpdump fetch command, you can output the fetched data directly to standard output. So, instead of using the curl command for importing as shown earlier, you could do:
$ sudo sh -c "gpgpdump fetch --raw https://download.docker.com/linux/ubuntu/gpg > /etc/apt/keyrings/docker-key.asc"
or
$ gpgpdump fetch --raw https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker-key.asc > /dev/null
That concludes the promotion (lol).
Linking Repositories and Public Keys with Signed-By
Referring to the current "Install Docker Engine on Ubuntu" page, let's register the Docker Engine APT repository in source.list. Assuming the imported OpenPGP public key file is /etc/apt/keyrings/docker-key.asc, the repository registration would look like this:
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker-key.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Or if you prefer using the add-apt-repository command:
$ sudo add-apt-repository "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker-key.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
This should also work. The key point is the signed-by option. You can use this to link the repository and the public key.
Once this is done, you can install and update packages as usual with apt update/install/upgrade.
Users Manage Third-Party Package Public Keys
The reason for doing this seemingly troublesome task is that if the private key corresponding to a third-party package's public key is leaked, the official APT side cannot address it, so they want to separate it from the keyring. If an unmanaged key whose private key has been leaked is left unattended, the possibility of "trusted malware" being injected increases.
Well, but the idea of separating management rather than excluding third-party keys is very Linux-like. It sets itself apart from the app stores of certain companies like A, G, or M (lol).
In return, the management of third-party public keys becomes the user's responsibility. If management of the public keys, including revocation, is not properly performed on the user side, you will end up carrying the risk yourself.
Be careful out there!
[Bonus] Installing pgAdmin 4
When installing pgAdmin, a friend to PostgreSQL service administrators, via APT, you also need to import the public key. Since v6.9, which supports Ubuntu 22.04 LTS, is out, let's try to handle it. It would look something like this (the output filename is arbitrary).
$ sudo curl -fsSL https://www.pgadmin.org/static/packages_pgadmin_org.pub -o /etc/apt/keyrings/pgadmin-4-key.asc
Repository registration is as follows:
$ sudo sh -c 'echo "deb [signed-by=/etc/apt/keyrings/pgadmin-4-key.asc] https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list'
That's it. After that, update and upgrade as usual, and there should be no problems.
Discussion