How to verify the integrity of a Linux distribution iso image

When we decide to install an operating system based on the Linux kernel, the first thing we do is to download its installation image, or ISO, from the official distribution website. Before proceeding with the actual installation, however, it is crucial to verify the integrity of the image, to be sure it is what it claims to be, and nobody has compromised it. In this tutorial we will see the basic steps we can follow to accomplish this task.

In this tutorial you will learn:

  • What is the basic difference between gpg encrypting and signing
  • How to download and import a gpg public key from a key server
  • How to verify a gpg signature
  • How to verify the checksum of an ISO

HOW TO VERIFY ISO IMAGE INTEGRITY

HOW TO VERIFY ISO IMAGE INTEGRITY

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution-independent
Software gpg, sha256sum (should be installed by default)
Other No other requirements
Conventions # – linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – linux-commands to be executed as a regular non-privileged user


The steps involved in checking the integrity of a downloaded ISO are basically two:

  1. Verifying the signature of the file containing the checksum of the ISO
  2. Verifying the checksum provided in the file is the same of the one of the actual ISO

Here we will see how to perform both steps.

Step 1

Verifying the gpg signature of the checksum file

To be sure an ISO we downloaded was not altered, there is one simple thing to do: check that its checksum corresponds to the one indicated in the file which is usually available in the same page the ISO was downloaded from. There is only one problem: how can we be sure that this file itself has not been altered? We must check its gpg signature! By the way, what is a gpg signature and what is the difference between signing and encrypting with gpg?

Encrypting vs signing

Gpg encryption is based on the use of key pairs. Each user generates a private and a public key: the former, as its name suggests, is strictly personal, and must be kept as safe as possible; the latter, instead, can be distributed and freely accessed by the public. There are basically two things we can do with gpg: encrypting and signing.

Let’s say we have two persons: Alice and Bob. If they want to benefit from the use of gpg, the first thing they must do is to exchange their public keys.

If Alice wants to send a private message to Bob, and wants to be sure that only Bob is able to read the message, she must encrypt it with Bob’s public key. Once the message is encrypted only Bob’s private key will be able to decrypt it.

That is gpg encryption; the other thing we can do with gpg is to create a digital signature. Suppose Alice wants to distribute a public message this time: everyone should be able to read it, but a method is needed to verify that the message is authentic and was really written by Alice. In this case Alice should use its private key to generate a digital signature; To verify Alice’s signature, Bob, (or any other person) uses Alice’s public key.



A real-world example – downloading and verifying Ubuntu 20.04 ISO

When we download an ISO from an official site we should also download, to verify it we should also download the corresponding checksum file and its signature. Let’s make a real-world example. Suppose we want to download and verify the ISO of the latest version of Ubuntu (20.04). We navigate to the release page and scroll to the bottom of the page; there we will find the list of files that can be downloaded:

ubuntu 20.04 releases

Ubuntu 20.04 releases page

Supposing we want to verify and install the “Desktop” version of the distribution, we should grab the following files:

  • ubuntu-20.04-desktop-amd64.iso
  • SHA256SUMS
  • SHA256SUMS.gpg

The first file is the distribution image itself; the second file, SHA256SUMS, contains the checksum of all the available images, and has we said is need to verify that the images has not been modified. The third file, SHA256SUM.gpg contains the digital signature of the previous one: we use it to verify that it is authentic.

Once we downloaded all the files, the first thing we need to do is to verify the gpg signature of the checksum file. To do that, we must use the following command:

gpg --verify SHA256SUMS.gpg SHA256SUMS

When more than one argument is provided to the gpg --verify command, the first one is assumed to be the file which contains the signature and the other ones to contain the signed data, which in this case is the checksum of the Ubuntu image. If the distribution we are currently working from is not Ubuntu, and it is the first time we check an Ubuntu image, the command should return the following result:

gpg: Signature made Thu 23 Apr 2020 03:46:21 PM CEST
gpg:                using RSA key D94AA3F0EFE21092
gpg: Can't check signature: No public key


The message is clear: gpg cannot verify the signature because we don’t have the public key associated with the private key that was used to sign data. Where we can get the key? The easiest way is to download it from a keyserver: in this case we will use keyserver.ubuntu.com. To download the key and import it in our keyring we can run:

$ gpg --keyserver keyserver.ubuntu.com --recv-keys D94AA3F0EFE21092

Let’s take a moment to explain the command above. With the –keyserver option, we specified the keyserver we want to use; the –recv-keys option, instead, takes a key-id as argument, and is needed to reference the key that should be imported from the keyserver. In this case the id of the key we want to search and import is D94AA3F0EFE21092. The command should produce this output:

gpg: key D94AA3F0EFE21092: public key "Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1

We can verify the key is now in our keyring by launching the following command:

$ gpg --list-keys

We should easily find the entry relative to the imported key:

pub   rsa4096 2012-05-11 [SC]
      843938DF228D22F7B3742BC0D94AA3F0EFE21092
uid           [ unknown] Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>

Now that we imported the public key, we can re-attempt to verify the SHA256SUM signature:

gpg --verify SHA256SUMS.gpg SHA256SUMS

This time, as expected, the command succeeded, and we were notified of a good signature:

gpg: Signature made Thu 23 Apr 2020 03:46:21 PM CEST
gpg:                using RSA key D94AA3F0EFE21092
gpg: Good signature from "Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 8439 38DF 228D 22F7 B374  2BC0 D94A A3F0 EFE2 1092


Reading the above output, a question would almost certainly arise: what does the “There is no indication that the signature belongs to the owner” message mean? The message appears because even if we imported the key in our keyring, we have not declared it as trusted, and there is no actual proof that it belongs to the specified owner. To get rid of the message we must declare that we trust the key; how we can be sure it is actually to be trusted? There are two ways:

  1. Personally verify the key belongs to the specified user or entity;
  2. Check that it has been signed by a key we already trust, directly or through a series of intermediate keys.

Furthermore, there are multiple levels of trust we can assign to a key; if you are interested in this subject (you definitely should be!), and want to know more about it, the GNU Privacy Handbook is a good source of information.

Step 1

Verifying the image checksum

Now that we verified that the SHA256SUM signature is ok, we can actually proceed and verify that the checksum of the downloaded image, corresponds to the one actually stored in the file, which has the following content:

e5b72e9cfe20988991c9cd87bde43c0b691e3b67b01f76d23f8150615883ce11 *ubuntu-20.04-desktop-amd64.iso
caf3fd69c77c439f162e2ba6040e9c320c4ff0d69aad1340a514319a9264df9f *ubuntu-20.04-live-server-amd64.iso

As you can see on each line of the file we have a checksum associated with an image. Assuming the SHA256SUM file is located in the same directory where the Ubuntu 20.04 image was downloaded, to verify the ISO integrity, all we have to do is to run the following command:

$ sha256sum -c SHA256SUM


sha256sum is the program used to compute and also check SHA256 message digest. In this case we launched it using the -c option, which is the short for --check. When this option is used, it instructs the program to read the checksums stored in the file passed as argument (in this case SHA256SUM) and verify it for the associated entry. The output of the command above, in this case, is the following:

ubuntu-20.04-desktop-amd64.iso: OK
sha256sum: ubuntu-20.04-live-server-amd64.iso: No such file or directory
ubuntu-20.04-live-server-amd64.iso: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

From the output we can see that the ubuntu-20.04-desktop-amd64.iso ISO has been verified, and its checksum corresponds to the one indicated in the file. We are also notified that was impossible to read and verify the checksum of the ubuntu-20.04-live-server-amd64.iso image: this makes sense, since we never downloaded it.

Conclusions

In this tutorial we learned how to verify a downloaded ISO: we learned how to check that its checksum corresponds to the one provided in the checksum file, and how to check the gpg signature of the latter is good. To check a gpg signature we need the public key corresponding to the private one that generated it: in the tutorial we also saw how to download a public key from a keyserver, by specifying its ID.



Comments and Discussions
Linux Forum