What commands (exactly) should replace the deprecated apt-key?
You need to know why apt-key add
is deprecated
All of the answers so far work around the symptom ("Don't use apt-key add
") but fail to address the actual problem that led to apt-key add
being deprecated. The problem is not a question of appending a key to one big keyring file etc/apt/trusted.gpg
vs manually putting single-key keyring files into the directory /etc/apt/trusted.gpg.d/
. These two things are equivalent, and doing either one is a huge security risk.
The problem is that any key you add to either of the above is completely and unconditionally trusted by apt. This means that any third-party repo whose apt signing key is in there is allowed to replace any package on your entire system, no questions asked. Even if we assume none of the repo owners are malicious, an attacker might compromise a repo, which has the same end result.
The instructions given in Ugo Delle Donne's answer for converting the key to the (legacy) keyring v4 format that apt will accept are correct and helpful, but that's only half of the solution. I'll reiterate them here (cleaned up slightly) so all the steps are consolidated in one place:
- Download the key:
-
wget https://host.domain.tld/path/to/<keyfile>.<ext>
(No need for-O
or>
;wget
defaults to saving the file in your current directory with the same filename it has on the server.)
-
- Verify that the filetype is "PGP public key block Public-Key (old)":
file <keyfile>.<ext>
-
gpg
supports a number of key formats, so if your key is in a different format, convert it by importing it into a temp keyring, then exporting it again:gpg --no-default-keyring --keyring ./temp-keyring.gpg --import <keyfile>.<ext>
gpg --no-default-keyring --keyring ./temp-keyring.gpg --export --output <your-keyfile-name>.gpg
rm temp-keyring.gpg
Now that you have your converted key, do not add it to apt
's trusted keystore by copying it into /etc/apt/trusted.gpg.d/
. Instead, put it somewhere like /usr/local/share/keyrings/
. (You'll need to create that keyrings
directory first.) There's nothing special about that location, it's just convention that /usr/local
is for stuff that's specific to this machine, share
because it's not a binary or a library or specific to any given user, and keyrings
is just a descriptive name.
At this point, nothing has changed and apt
doesn't know the key exists. The last step is to modify the specific .list
file for the repository to tell apt where to find the key for that specific repo.
- Edit the file
/etc/apt/sources.list.d/<example>.list
, and in betweendeb
and the url, add[signed-by=/usr/local/share/keyrings/<your-keyfile-name>.gpg]
Now apt will accept that key's signature for all packages in that repo and only that repo.
Notes:
- If you already have keyring files in
/etc/apt/trusted.gpg.d/
, you cancopymove them to/usr/local/share/keyrings/
as-is, and then update all the corresponding.list
files so each one has asigned-by
field pointing to its own key. - If you already have keys in the
/etc/apt/trusted.gpg
keyring file beyond the official repo keys, this answer details the steps to locate and remove them. You can then follow all the same steps above to set them up the safer way. (Exporting them from that keyring is also possible, but the exact steps are left as an exercise for the reader.) - To import a repo's key from a keyserver to a standalone file:
gpg --no-default-keyring --keyring <output-file-name>.gpg --keyserver <some.keyserver.uri> --recv-keys <fingerprint>
- This should give you a key that apt will accept without conversion.
- Apt is still very trusting, and a malicious or compromised repo can bypass this measure easily because packages currently can run arbitrary shell code as root in their setup scripts. Closing off one attack vector doesn't hurt, though, and progress is (slowly) being made on other fronts.
- Optionally, you can switch to the newer, more verbose
Deb822
format using individual.sources
files instead of.list
files. It's more work, but personally I find the result far more readable.
Sources:
- Debian Wiki
- Excellent and detailed answer on Unix&Linux StackExchange
I stumbled on the same problem and luckily some other question lighted the way. In my example I was trying to add a teamviewer repository to a recent Kali linux and I was being blocked by the key verification.
I'm quite sure there's a more elegant way to do this but the following steps helped me fix the problem:
-
Download the relevant key
wget -O - https://download.teamviewer.com/download/linux/signature/TeamViewer2017.asc > ~/teamviewer.key
-
Verify the type of file
file ~/teamviewer.key
it should be PGP public key block Public-Key (old)
-
Create a keyring
gpg --no-default-keyring --keyring ./teamviewer_keyring.gpg --import teamviewer.key
-
This file is still not a valid key that can be added to /etc/apt/trusted.gpg.d/ since it's a keyring, but from the keyring we can extract the key with
gpg --no-default-keyring --keyring ./teamviewer_keyring.gpg --export > ./teamviewer.gpg
-
This file is the key you want to move to the trusted key folder
sudo mv ./teamviewer.gpg /etc/apt/trusted.gpg.d/
happy sudo apt update
!!!
The reason for this deprecation is because using apt-key add
simply appends the gpg key to the trusted global APT keyring. It's similar to the preferred method of adding local_repo.list
to /etc/apt/sources.list.d/
instead of using add-apt-repository dep /link/to/repo version
, which appends the message to the global sources.list
file.
I think it's a bit more awkward to understand than using the .d folder, but essentially we want to get the gpg key into a standalone keyring file, then point to this keyring file in the source listing. The default keyring file location is /usr/share/keyrings
, and it can be a .asc or .gpg file. I'm not sure the difference but I do know the global keyring files are binary files, not plaintext.
For example:
Using generic names can be a bit hard to understand sometimes, so here is an example of installing mongoDB:
Get the MongoDB gpg key and add it to a new keyring file
curl https://www.mongodb.org/static/pgp/server-4.2.asc | sudo tee -a /usr/share/keyrings/buster-mongodb-org-4_2.asc
Add a source entry for apt, pointed to this new keyring
echo "deb [signed-by=/usr/share/keyrings/buster-mongodb-org-4_2.asc] https://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main
Install mongodb from this newly added repo
sudo apt install -y mongodb-org
Reference
This is still new to me, but most of what I know came from this excellent answer in the unix SE
I created a shell script that can download and install keys to be used with [signed-by=]
declaration in sources.list
.
It's available on github.com/ameinild/add-apt-key.
POSIX Script for installing APT keys
General help
This script will help with installing PGP keys for APT repositories.
This script supports up to 2 arguments:
- 1st argument is input file. This can be either:
- An URL - key will be downloaded into current path (using wget or curl)
- A filename - reads an existing key in current path
- A path and a filename - reads an existing key in given path
- 2nd argument is key output path and output name. This can be either:
- Only filename - output path is set in config, saved as given filename
- A path and a filename - output path is given here, saved as given filename
- Only a path (end with /) - output path is given here, filename is taken from existing key
- Empty - output path is set in config, filename is taken from existing key
This script has a config file
/usr/local/etc/add-apt-key.conf
, where the following variables can be set:
keypath
: path to store converted key - default is/usr/share/keyrings
verbosity
: if set to Yes - displays extra outputremovetmp
: if set to Yes - remove input (non-converted) fileExample 1: (
PWD=/root
)sudo add-apt-key https://mariadb.org/mariadb_release_signing_key.asc /usr/local/share/keyrings/
Will download key in
/root
, convert it and store as/usr/local/share/keyrings/mariadb_release_signing_key.gpg
Example 2: (
PWD=/home/user
)sudo add-apt-key /root/mariadb_release_signing_key.asc /usr/local/share/keyrings/mariadbkey
Will use existing key in
/root
, convert it and store as/usr/local/share/keyrings/mariadbkey.gpg
Example 3: (
PWD=/home/user
)sudo add-apt-key mariadb_release_signing_key.asc mariadbkey
Will use existing key in
/home/user
, convert it and store as/usr/share/keyrings/mariadbkey.gpg
After installing the PGP key, it is also possible to add the key and repository to
/etc/apt/sources.list
- The choice to add this will be presented in the script as the first input option
- If Yes is chosen, the repository string must be pasted as the second input option
This completes the key installation by adding the corresponding repository line to
/etc/apt/sources.list
Installation
Install by running the following commands:
sudo curl -L https://raw.githubusercontent.com/ameinild/add-apt-key/master/add-apt-key -o /usr/local/bin/add-apt-key sudo curl -L https://raw.githubusercontent.com/ameinild/add-apt-key/master/add-apt-key.conf -o /usr/local/etc/add-apt-key.conf sudo chmod a+rx /usr/local/bin/add-apt-key
Keys for use by apt
are stored in /etc/apt/trusted.gpg.d/
. apt-key
managed these keyrings for you, but now that it's deprecated you need to choose a suitable file name <KEYRING>
for the keyring yourself.
If you have the key already as a local file <FILE>
, run
gpg --no-default-keyring --keyring=gnupg-ring:/etc/apt/trusted.gpg.d/<KEYRING>.gpg --import <FILE>
To directly read the key from <URL>
, run
curl -sSfL <URL> | gpg --no-default-keyring --keyring=gnupg-ring:/etc/apt/trusted.gpg.d/<KEYRING>.gpg --import
Note: the prefix gnupg-ring:
before the keyring name is required to create the keyring in the apt
compatible (legacy) v4 format, rather than the (newer) keybox v1 format.