RPM and GPG: How to verify Linux packages before installing them
Large and popular RPM repositories are typically replicated around the world. The projects and companies providing the packages utilize content distribution networks (CDNs) and mirror sites to make their packages available to consumers. For many open-source projects, that includes hosting by volunteers. To detect and avoid malicious replacement packages, package owners can sign the package files, and consumers can verify those signatures.
While GPG can sign any file, manually checking package signatures is not scalable for system administrators. The RPM format has an area specifically reserved to hold a signature of the header and payload. The
rpm utility uses GPG keys to sign packages and its own collection of imported public keys to verify the packages. YUM and DNF use repository configuration files to provide pointers to the GPG public key locations and assist in importing the keys so that RPM can verify the packages.
For this article, I will use keys and packages from EPEL. The public key is included in an RPM package, which also configures the
yum repo. For some projects, the key may also be available directly from a source web site.
The rpm utility has its own key management
rpm utility has its own key management, there is no need to import the GPG public keys to your personal GPG keyring. In fact, you cannot just verify the file with
gpg commands because the signature is not of the entire .rpm file. Instead, the signature is only associated with the critical portions of the package.
Run the following command to use
rpm to verify a package:
$ rpm -K epel-release-latest-8.noarch.rpm epel-release-latest-8.noarch.rpm: digests SIGNATURES NOT OK
In this case, the "SIGNATURES NOT OK" message appears because the key has not yet been imported for RPM. The default behavior of
rpm commands is to verify the signature of packages during any install or verify interactions. If that is not possible, because the package is not signed or the public key is not available, you may need to specify the
--nogpgcheck option to skip this step.
If you have access to the GPG public key, you can use the following command to manually import a key:
$ rpm --import RPM-GPG-KEY-EPEL-8
Since the metadata for the key is stored in the RPM database, you can query and delete keys the same as any package.
Use the following command to list the keys:
$ rpm -qa gpg-pubkey* gpg-pubkey-7fac5991-4615767f gpg-pubkey-2f86d6a1-5cf7cefb
Use this command to get the information on a key:
$ rpm -qi gpg-pubkey-2f86d6a1-5cf7cefb Name : gpg-pubkey Version : 2f86d6a1 Release : 5cf7cefb Architecture: (none) Install Date: Mon 01 Jun 2020 12:14:38 PM EDT Group : Public Keys Size : 0 License : pubkey Signature : (none) Source RPM : (none) Build Date : Wed 05 Jun 2019 10:17:31 AM EDT Build Host : localhost Relocations : (not relocatable) Packager : Fedora EPEL (8) <firstname.lastname@example.org> Summary : gpg(Fedora EPEL (8) <email@example.com>) Description : -----BEGIN PGP PUBLIC KEY BLOCK----- Version: rpm-4.14.2 (NSS-3) ...omitted...
The following command is used to remove a key:
$ sudo rpm -e gpg-pubkey-2f86d6a1-5cf7cefb
More options for key management are described in the man page included with the
YUM and DNF can add keys to the RPM database
Other package managers make key management even easier. YUM and DNF use configuration files in
/etc/yum.repos.d to specify a URL for the GPG key used to verify packages in that repository. The utilities can then import the key if it is not already available for verification.
yum repo configuration file, the line gpgcheck=1 indicates that GPG checking should be done for all packages in this repository. It is a Boolean value that can be changed in the configuration or overridden temporarily on the command line with the
If the GPG public key has not yet been imported to RPM when a package installation begins, then the
dnf) utility can initiate an import of the key. The gpgkey=URI line specifies the source of the key to be imported. This source can be any URI, including a local file or a remote web link. The
dnf utility will pause and ask for confirmation to import the key after showing the key ID and fingerprint.
warning: /var/cache/dnf/epel-fafd94c310c51e1e/packages/zsh-syntax-highlighting-0.7.1-1.el8.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID 2f86d6a1: NOKEY Extra Packages for Enterprise Linux 8 - x86_64 1.6 MB/s | 1.6 kB 00:00 Importing GPG key 0x2F86D6A1: Userid : "Fedora EPEL (8) <firstname.lastname@example.org>" Fingerprint: 94E2 79EB 8D8F 25B2 1810 ADF1 21EA 45AB 2F86 D6A1 From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8 Is this ok [y/N]: y
The key is added to RPM, and then the verification and installation of the package continues.
Prepare to sign a package
If you are creating and distributing your own RPM package files, you can sign those packages with the
The first step is to create a GPG keypair for signing. Be sure to also export and share the public key. For packages that will be distributed publicly, it is a good idea to use a new keypair and a keyring in a shared location. Additionally, use the
--full-gen-key option and then choose to create a signing-only key instead of the default, which creates both a signing and encryption key.
$ gpg --keyring /shared/rpm/.gpg --no-default-keyring --full-gen-key
Even if only one person is using the key to sign packages, make a separate keypair to use for signing. Do not use the same key for other daily tasks such as personal email encryption.
Next, we need to install the
rpm-sign package and set up an
rpmmacros file specifying the key to use. The
rpm-sign package includes a man page for
rpmsign which describes the process. Note that the package name has a dash that is not a part of the command name.
$ sudo yum install rpm-sign $ man rpmsign
RPM commands get their configuration from several
rpmmacros files. There is a default file with lots of samples located at
/usr/lib/rpm/macros. If multiple people are responsible for signing packages using the same key, place a central configuration file in the
/etc/rpm/macros location. Finally, for a specific person signing the packages, the user's
~/.rpmmacros file can be configured to point to the correct GPG key.
The minimum entry for the
rpmmacros file is to specify the name of the key. You can use a name or the key ID. Obtain the key ID with the
gpg --list-keys command.
Tip: Run the
rpmsign command before setting the gpg_name variable and the message will show the format.
$ rpmsign --addsign my-custom-package.rpm You must set "%_gpg_name" in your macro file
In addition to the key name, if the keyring is anywhere other than the default user
~/.gnupg directory, use the gpg_path variable to set the location. This value will be the same as used with the
--keyring option when the key was created.
There are additional options available if the GPG binary or command syntax requires something beyond the expected defaults.
Sign and publish packages
You are now ready to sign the package or packages. According to the
rpmsign man page, the
--resign commands are interchangeable. Both will replace the signature portion of an RPM package file with current information.
The following command is an example of using the
$ rpmsign --addsign myprod-2.x86_64.rpm myprod-libs-2.x86_64.rpm
Older versions of
rpmbuild included a
--sign option that could sign the package during the build process if the GPG keys and
rpmmacro files were configured correctly. The
--sign option is now deprecated in favor of the separate step of using
rpmsign. This approach encourages a build, test, sign, publish workflow.
Finally, make the packages and GPG public key available to clients. One option is to mimic the EPEL project and create an RPM file that includes the GPG public key and one or more
yum repo files pointing to the location of the signed packages. For organizations hosting packages on a Red Hat Satellite Server, start by uploading the GPG public key, and then assigning that key to the product or repository that holds the signed packages. All packages in a repository must be signed with the same key. This is a common reason for Satellite administrators to resign packages before uploading.
Now that you know more about managing RPM packages with GPG, you can better understand how to work with
[ Want to learn more about security? Check out the IT security and compliance checklist. ]