Home Wiki > openSUSE:Package source verification
Sign up | Login

openSUSE:Package source verification

tagline: From openSUSE

Package Source Verification


The Open Build Service and the openSUSE distribution projects (Tumbleweed and Leap) are made of thousands of packages from numerous upstream sites.

Generally, software is packaged in "good faith", relying on the upstream not to add malicious code in their software releases. However, occasionally there have been hackers trying to backdoor released software tarballs.

As during the regular package integration of packages it is very hard and even impossible for us to review all the changes in upstream tarballs, we want to rely on some form of integrity guarantee from the upstream communities. The most suitable established process on relying is signing the released tarballs using GPG (GNU Pretty Good Privacy).

A large number of projects already do so to provide us with an established means to automatically check these signatures.

Source including verification

The GPG signature and the GPG keyring is included alongside the source package, and listed in its sources.

So looking at GNU Hello (RPM package "hello"):

Source0:  http://ftp.gnu.org/pub/gnu/hello/hello-%{version}.tar.gz
Source1:  http://ftp.gnu.org/pub/gnu/hello/hello-%{version}.tar.gz.sig
Source2:  %{name}.keyring

The source URL given must be valid and the file must also be included as a local copy in the OBS repository. This is because when the package is submitted to Factory, the source files will be downloaded again and verified against the uploaded version.

If you wish to rename a source file, use the following URL syntax (where the file is uploaded to OBS as "some-other-name-%{version}.tar.gz"):

Source0:  http://ftp.gnu.org/pub/gnu/hello/hello-%{version}.tar.gz#/some-other-name-%{version}.tar.gz

Source without verification

If the source URL no longer exists (is "dead") or the tarball has to be modified before uploading for some reason, just list the name of the package in the "Source:" tag. Make sure to leave a comment about where you last retrieved the file from or how to recreate the modified tarball.

# URL no longer exists, last downloaded from http://example.com/mypackage-v0.5.9.tar.xz on 22 Nov 2016
Source:  mypackage-v%{version}.tar.xz

Creating a .keyring file

In order to create a keyring file, you must have imported the public key that corresponds to the key used to sign the release.

The keyring should be retrieved from a reliable source (usually from the website). If possible, comment the URL where you got it from, placing it above the Source line in the .spec file.

You can also verify if the key is in the GPG web of trust and chain to more accounts, although this is usually lacking.

It is very important that this key comes from a trusted source and is not a malicious key -- please use due diligence in verifying this.

Any changes to the keyring should be documented in the .changes file of the package to avoid replacement with bad keys.

In order to run the gpg-offline tool, it is necessary to install it:

zypper install gpg-offline

Using a trusted signature

If you have a trusted signature and you want to create keyring:

gpg --keyserver-options=auto-key-retrieve --verify mypackage.tar.gz.sig

Online GPG verification will be performed. You will get a text containing description and ID of the signing key. Pick the key ID from the output and and call:

gpg-offline --package={my_package} --add {key_id}

Note: if upstream uses multiple keys to sign their releases, all possible keys should be included in the keyring if possible.

Using existing GPG keyring

gpg-offline keyrings are standard armored GPG keyrings that contains text header that must exactly match to the keyring contents.

If you already have a trusted keyring in another format (e. g. plain or armored keyring without a header), it is easy to convert it to gpg-offline format. Rename it to {my_package}.keyring, and then use the following command:

gpg-offline --refresh

The command will present an error to you, but you can silently ignore it: Yes, you are aware that text header does not match (or does not exist). (You can use --offline option to perform only the refresh and don't search keyservers.)

Validating signature in source tag (recommended)

As the method during build takes time to check and also pulls in GnuPG in the build dependencies, we have implemented the checking of the signatures in the "source_validator" service (in the "obs-service-source_validator" RPM).

This service is not just run during package check in, but also by the factory bot checking scripts. The script checks the signatures against the %name.keyring file in the source directory. It can handle .asc and .sig(n) extensions of the tarballs.

If the signature does not validate, the checkin or the submission will be declined.

You can run it locally on your submissions using:

osc service localrun source_validator

The code lives in the obs-service-source_validator RPM package, in the script /usr/lib/obs/service/source_validators/20-files-present-and-referenced.

Previous method (DO NOT USE)

This method is obsolete and is only provided for reference.

Originally, verification was performed using an explicit call to the %gpg_verify macro.

In the GNU hello case you would use:

BuildRequires: gpg-offline

and in the %prep phase:

%gpg_verify %{SOURCE0}

This automatically appends .asc/.sig(n) to the filename in %SOURCE0, and also looks for the %name.keyring file to locally verify the signature during build. If the signature does not validate, the build will fail.

The code and macro can be found in the gpg-offline package.