Generating RPM and YUM Signatures for Secure Software Distribution
RPM Signautures important to ensure end-to-end security during RPM package distribution over network.
RPM package files (.rpm) and yum repository metadata can be signed with GPG.
Signing RPM package with a GPG key enables the recipient of the package to verify that no modifications occurred after the data was signed (assuming the recipient has a copy of the sender’s public GPG key).
Why do we need Signature for RPM or YUM repos?
RPM package signatures can be used to implement cryptographic integrity checks for RPM packages. This approach is end-to-end in the sense that the package build infrastructure at the vendor can use an offline or half-online private key (such as one stored in hardware security module), and the final system which consumes these packages can directly verify the signatures because they are built into the
.rpm package files.
Intermediates such as proxies and caches (which are sometimes used to separate production servers from the Internet) cannot tamper with these signatures.
RPM file Format
The RPM file format is a binary file format that consists of:
- A data structure called a
lead, which has mostly been obsoleted and superseded by the header structure.
- A signature section which may contain a GPG signature that can be used for verifying that the RPM file has not been modified since it was created.
- A header section containing a set of index entries, which map numbered types to values. This is used for storing internal information about RPM package files.
- A gzip compressed CPIO archive containing the actual files to be written to the filesystem.
A GPG signature for an RPM file is calculated from data found in the header and the compressed CPIO archive and stored in the signature section.
Generating RPM signature with rpmsign
To add an RPM signature to a
.rpm signature, you need to generate a GnuPG key first, using
gpg --gen-key. Let’s assume that this key has the user ID “
firstname.lastname@example.org”. We first export the public key part to a file in a special directory, otherwise
rpmsign will not be able to verify the signatures we create as it uses the RPM database as a source of trusted signing keys (and not the user GnuPG keyring):
$ mkdir $HOME/rpm-signing-keys $ gpg --export -a email@example.com > $HOME/rpm-signing-keys/example-com.key
The name of the directory
$HOME/rpm-signing-keys does not matter, but the name of the file containing the public key must end in “
.key”. On Red Hat Enterprise Linux 7, CentOS 7, and Fedora, you may have to install the
rpm-sign package, which contains the
rpmsign command to create the signature looks like this:
$ rpmsign -D '_gpg_name firstname.lastname@example.org' --addsign hello-2.10.1-1.el6.x86_64.rpm Enter pass phrase: Pass phrase is good. hello-2.10.1-1.el6.x86_64.rpm:
(On success, there is no output after the file name on the last line, and the shell prompt reappears.) The file
hello-2.10.1-1.el6.x86_64.rpm is overwritten in place, with a variant that contains the signature embedded into the RPM header. The presence of a signature can be checked with this command:
$ rpm -Kv -D "_keyringpath $HOME/rpm-signing-keys" hello-2.10.1-1.el6.x86_64.rpm hello-2.10.1-1.el6.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID de337997: OK Header SHA1 digest: OK (b2be54480baf46542bcf395358aef540f596c0b1) V4 RSA/SHA1 Signature, key ID de337997: OK MD5 digest: OK (6969408a8d61c74877691457e9e297c6)
If the output of this command contains “
NOKEY” lines instead, like the following, it means that the public key in the directory
$HOME/rpm-signing-keys has not been loaded successfully:
hello-2.10.1-1.el6.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID de337997: NOKEY Header SHA1 digest: OK (b2be54480baf46542bcf395358aef540f596c0b1) V4 RSA/SHA1 Signature, key ID de337997: NOKEY MD5 digest: OK (6969408a8d61c74877691457e9e297c6)
Afterwards, the RPM files can be distributed as usual and served over HTTP or HTTPS, as if they were unsigned.
Generating Signature for YUM Repo metadata
We can sign yum repository metadata with GPG signatures. The purpose of signing repository metadata is to ensure that the metadata has not been modified or tampered with since it was generated. This is an often overlooked component of generating secure yum repositories.
Once we have generated the repository metadata using
createrepo, we can then generate a detached GPG signature by running:
$ gpg --detach-sign --armor repodata/repomd.xml
This command will create a file named
repodata/repomd.xml.asc which contains an ASCII version of the GPG signature of the repository metadata file
yum clients will automatically request this file and attempt to verify the signature contained here if the proper options are set in the repository config
Verifying the Signatures before using them
Verifying the RPM Signatures
To enable RPM signature checking in
rpm explicitly, the
yum repository file must contain a
gpgcheck=1 line, as in:
[gnu-hello] name=gnu-hello for Fedora $releasever baseurl=https://download.example.com/dist/fedora/$releasever/os/ enabled=1 gpgcheck=1
Once signature checks are enabled in this way, package installation will fail with a
NOKEYerror until the signing key used by
.rpm files in the repository is added to the system RPM database. This can be achieved with a command like this:
$ rpm --import https://download.source.com/keys/rpmsign.asc
The file needs to be transported over a trusted channel, hence the use of an
https:// URL in the example. (It is also possible to instruct the user to download the file from a trusted web site, copy it to the target system, and import it directly from the file system.) Afterwards, package installation works as before.
After a key has been import, it will appear in the output of the “
rpm -qa” command:
$ rpm -qa | grep ^gpg-pubkey- … gpg-pubkey-ab0e12ef-de337997 …
More information about the key can be obtained with “
rpm -qi gpg-pubkey-ab0e12ef-de337997”, and the key can be removed again using the “
rpm --erase gpg-pubkey-ab0e12ef-de337997”, just as if it were a regular RPM package.
Verifying the Signatures of YUM repo
In order to properly verify GPG keys associated with YUM repo metadata, two things must happen on the client system:
- You must install the
pygpgmepackage so that yum can verify gpg signatures. If this package is not installed. yum will skip verification of GPG signatures. In order to install this package, you will need to have the EPEL repository installed on your system.
- You must also enable the proper options in the yum repository configuration file, as mentioned belownext.
yum repositories are configured by writing a file ending with
.repo to a client’s
/etc/yum.repos.d/ directory, for example:
There are two separate options which must be enabled in this file depending on which type of GPG verification is desired:
repo_gpgcheck=1enables GPG verification of the yum repository metadata
gpgcheck=1enables GPG verification of RPM files themselves
Important Note about YUM Locally installed packages
Package signatures are only checked by yum if the package is downloaded from a repository (which has checking enabled). This happens if the package is specified as a name or name-version-release on the yum command line. When packages are installed locally via yum localinstall <rpm_package> the signature won’t be checked.
But starting from RHEL 6 , there is a new option called localpkg_gpgcheck introduced. Setting it to ‘1’ in yum repo file will force the yum to verify the signature of packages installed via yum localinstall as well.
You can specify the public GPG keys which should be imported by listing their URLs to the
You may specify multiple keys if desired, as well:
Generating and verfying GPG signatures is critical to establishing the authenticity of package objects and the repositories storing those objects.
Knowing that a package being installed on your system is the same package that was generated by a vendor, and that you were able to retrieve that package from the repository generated by the vendor is the only way to ensure that you are safely installing software in your infrastructure.
If you are creating a repository of packages you should ensure give your users a secure way to consume them. You can do this by following these recommendations:
https://URLs everywhere in configuration advice regarding RPM repository setup for yum.
- Create a signing key and use them to sign RPM packages, as outlined above.
- Make sure RPM signature checking is enabled in the
- Use an
https://URL to download the public key in the setup instructions.