Packagecloud logo

HOWTO: GPG sign and verify deb packages and APT repositories

TL;DR 

GPG can be used to create a digital signature for both Debian package files and for APT repository metadata.

Many Debian-based Linux distributions (e.g., Ubuntu) have GPG signature verification of Debian package files (.deb) disabled by default and instead choose to verify GPG signatures of repository metadata and source packages (.dsc). The setting which enables GPG signature checking of the individual .deb packages can be found in /etc/dpkg/dpkg.cfg and is set to no-debsig, but there are important caveats to enabling this option explained below.

Further, most official Debian package files from the publicly accessible repositories do not have GPG signatures. The official repository metadata is GPG signed, as are the source packages, but the .deb packages themselves are not.

If you publish a Debian package and GPG sign the package yourself before distributing it to users, those users’ systems will, in most cases, not verify the signature of the package unless they have done a considerable amount of configuration. However, their system will, in most cases, automatically verify repository metadata.

This post explains how Debian package GPG signatures are implemented, how to enable GPG signature checking of packages on your system, and how to GPG sign packages you create.

This post will also explain how APT repository GPG signatures are implemented and how to sign your APT repository metadata.

Debian package GPG signatures

Signing data with a GPG key enables the recipient of the data to verify that no modifications occurred after the data was signed (assuming the recipient has a copy of the sender’s public GPG key).

Debian package files (.deb files), Debian source packages (.dsc files), and Debian changes files (.changes files) can all be signed with GPG.

 

GPG signing Debian source packages (.dsc files) and changes files

Debian source packages and Debian changes files are text-based files which can be used to rebuild a Debian package from source code. Theses files can be signed with a GPG key by using a program called debsign.

debsign will add a GPG signature to .dsc and .changes files themselves. You can use debsign like this:

$ debsign -k E732A79A test_1.0-7.dsc

This command specifies the GPG key ID to use when signing the Debian source file test_1.0-7.dsc. The signature is embedded in the file test_1.0-7.dsc and can be verified by running:

$ gpg --verify test_1.0-7.dsc

The Debian source package file and changes file both contain SHA1, SHA256, and MD5 checksums of all source files that comprise the source package. Since this data is signed, any modifications to the source file checksums, file size, or other data in the dsc or changes files would cause signature verification to fail.

As long as a recipient who wishes to build the deb package from a dsc file verifies the checksums of each file in the source package and verifies the signature of the source package itself, the recipient knows their build uses precisely the same files that the packager used when building.

apt-get source packagename will automatically check the GPG signature of the source package file and the checksums of the source files listed in the source package.

 

GPG signing Debian package files (.deb files)

A Debian package file itself is actually an AR archive that contains at least three entries:

  • debian-binary: a file describing the deb format version
  • control: an archive containing package metadata such as pre-install or post-install scripts
  • data: an archive containing the actual installable files

The control and data archives are typically tar, tar.gz, tar.bz2, tar.xz, tar.lzma, or another archive format.

When a Debian package is signed with a GPG key, the signature is also included in the archive and is named based on its type.

Debian package signatures are typically associated with a role. Some commonly used roles include:

  • origin: the signature of the organization which distributes the .deb file
  • maint: the signature of the package maintainer
  • archive: the signature of the archive providing the package to reassure users that the package is the actually provided by the archive

In order to sign a Debian package, you can use the program debsigs:

$ debsigs --sign=origin -k E732A79A test_1.0-7_amd64.deb

In the above example, the Debian file is signed using the GPG key on my system with the ID E732A79A. The signature type is origin and thus the deb package will be modified to include a file called _gpgorigin that contains the GPG signature of the debian-binary file, control archive, and data archive from the deb package concatenated together.

I used the type origin because I am person distributing the deb package test_1.0-7_amd64.deb.

Verifying signatures on Debian .deb package files is a bit more involved than the other verification methods.

 

Verifying GPG signatures of .deb package files

In order to verify .deb package files, you must have the program debsig-verify installed, import the public GPG keys you will use to verify packages to the debsig-verify keyrings, and you must also create an XML policy document for signature verification.

First, create a keyring directory for the public key and import the public key to the debsig-verify GPG keyring:

$ mkdir /usr/share/debsig/keyrings/DDDF2F4CE732A79A/
$ gpg --no-default-keyring \
      --keyring /usr/share/debsig/keyrings/DDDF2F4CE732A79A/debsig.gpg \
      --import my-public-key

In the above example, the keyring subdirectory, DDDF2F4CE732A79A, is the fingerprint of the GPG key which will be imported. Note that the name of the keyring debsig.gpg will be used in the XML policy document created next. You can use any filename you like.

Now that the public key is imported, the XML policy document can be constructed.

First, create a directory for the policy document. It must have the GPG key fingerprint in the path:

$ mkdir /etc/debsig/policies/DDDF2F4CE732A79A/

Next create the XML document. The debsig-verify man page indicates that the filename is irrelevant so long as the filename ends with .pol and resides in a directory named after the GPG key fingerpint.

You can find more information regarding how the build the policy document in /usr/share/doc/debsig-verify/policy-syntax.txt and some examples in /usr/share/doc/debsig-verify/examples.

Here’s an example XML policy document:

<?xml version="1.0"?>
<!DOCTYPE Policy SYSTEM "http://www.debian.org/debsig/1.0/policy.dtd">
<Policy xmlns="http://www.debian.org/debsig/1.0/">

  <Origin Name="test" id="DDDF2F4CE732A79A" Description="Test package"/>

  <Selection>
    <Required Type="origin" File="debsig.gpg" id="DDDF2F4CE732A79A"/>
  </Selection>

   <Verification MinOptional="0">
    <Required Type="origin" File="debsig.gpg" id="DDDF2F4CE732A79A"/>
   </Verification>
</Policy>

Once this document is constructed, you can verify the GPG signature of the Debian .deb package:

$ debsig-verify test_1.0-7_amd64.deb
debsig: Verified package from `Test package' (test)

 

dpkg support for debsig-verify

dpkg has support for verifying GPG signatures of Debian package files, but this verification is disabled by default. This means that when a package is installed on a Debian-based system, the signature checking for individual packages is disabled.

In order to enable it, the file /etc/dpkg/dpkg.cfg will need to be modified to remove the no-debsig option from the config file.

CAUTION: Doing this may cause dpkg to reject installation of unsigned Debian files. If you plan to enable this, it is strongly recommended you try this first in a testing environment. You’ll also need to ensure you have the correct XML policy files created, as explained above.

 

Another Debian package signing tool: dpkg-sig

There is a another tool available for signing and verifying Debian package files called dpkg-sig. Signatures created by this tool are not compatible with debsigs and the tools cannot understand or verify each other signatures.

dpkg-sig generates a Debian control file with several userful fields:

  • Version of dpkg-sig which generated the signature
  • Gpg key signer information
  • Role
  • Files section with checksums, file sizes, and filenames of the control, data, and debian-binary files in the Debian package

This file is named based on the role selected, which is defaulted to builder if none is specified. So, signing a Debian package file with no role would result in a file named _gpgbuilder being created and added to the package file. This file is signed with GPG and the signature is embedded as plain text (a “clearsign” GPG signature).

The result of this scheme is that the GPG signature can be verified using commonly available software. The Debian package can be extracted with ar and the signature of the control file can be checked with just gpg --verify.

Signing a Debian file with dpkg-sig is straight forward:

$ dpkg-sig -k E732A79A --sign builder test_1.0-7_amd64.deb

The signature can also be checked by using dpkg-sig directly, if desired:

$ dpkg-sig --verify test_1.0-7_amd64.deb
Processing test_1.0-7_amd64.deb...
GOODSIG _gpgbuilder 284E8BE753AE45DFF8D82748DDDF2F4CE732A79A 1414371553

Additionally, no XML policy document is required for signature verification, which makes signature verification much simpler to integrate into a workflow.

 

dpkg support for dpkg-sig

Unfortunately, dpkg does not have built-in support for dpkg-sig, but the discussion appears to have been moved to a bug ticket with Debian (last updated in 2012): https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340306.

 

GPG signatures for APT repository metadata

It is also possible to generate GPG signatures for APT repositories in addition to generating signatures for Debian packages themselves.

Generating signatures of the repository metadata allows you to verify that the repository metadata has not been tampered with since it was generated by the repository host.

This is critical to preventing a Man-in-the-Middle attack attack where a malicious actor plants repository metadata causing a user’s package manager to install potentially malicious packages.

Luckily, generating GPG sigantures for APT repositories is straightforward with reprepro.

Assuming you have a GPG key you’d like to use to sign the repository metadata, you can simply modify your reprepro repository config to add your GPG key.

Using the same GPG key ID used in the earlier examples, the conf/distributions config file can be modified to add the field:

SignWith: E732A79A 

This will cause reprepro to generate GPG signatures of the repository metadata. reprepro will generate a signature of the apt Release file and store the signature in the file Release.gpg. This is called a “detached GPG signature.”

Newer version of reprepro will generate an embedded text GPG signature (a “clearsign” GPG signature) in a file named InRelease.

The apt client will download the GPG Release file(s) it understands and will automatically attempt to verify the GPG signature of the repository.

Users of the repository will need to have the GPG key installed on the system. This can be done by end users running the command: apt-key:

$ sudo bash -c 'wget -O - https://packagecloud.io/gpg.key | apt-key add -'

The above command downloads a GPG key and adds the GPG key to the system using apt-key.

Conclusion

GPG signing of Debian package files, source packages, and repository metadata is critical to establishing the authenticity of the package objects and repository metadata.

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.

Unfortunately, signing and checking the signatures of Debian packages is not as streamlined and integrated as it could be, so vendors currently signing their Debian package files may be surprised to learn that the majority of their customers are not automatically checking the GPG signature of their packages. At the very least, vendors should be signing their repository metadata. Also signing their Debian package files and providing instructions for how users can verify those signatures would be a great way to help improve their end user’s security.

packagecloud.io signs repository metadata it generates using a GPG key so that users of our repositories know, without a doubt, that the repository metadata their package manager downloaded was generated by packagecloud.io.

You might also like other posts...