Manually Verifying Hashes of Installed Files


Some people choose to use a security feature which verifies files on /boot (which are typically unencrypted) before using them. One example is PureBoot, which verifies the hashes of all files on /boot against a file signed by the user’s GPG key. The correct usage of this feature is to sign the files immediately after they are installed/updated (under the assumption that the update process is secure) so that future tampering can be detected. However, an operational mistake may leave the files unsigned and unattended for an unacceptable period of time. This guide explains how to manually verify the files.

Required Equipment

  • A trusted ISO (or other media which can be booted, as this cannot be done with the untrusted files in /boot)
  • A trusted copy of the QubesOS signing key for the relevant version (or the QMSK, which can be used to establish trust in a downloaded signing key)
  • An internet connection


For each package, we have to:

  1. Download the relevant RPM and buildinfo files from the QubesOS server
  2. Verify both files
  3. Extract the binaries & compare their hashes

The process will use an example of an updated (and currently untrusted) hypervisor, consisting of the following files:

  • /boot/xen-4.17.2.gz
  • /boot/efi/EFI/qubes/xen-4.17.2.efi
  • /boot/efi/EFI/quebs/xen.efi

Download the relevant files

We can manually download RPM and buildinfo files from For example, at time of writing the packages for 4.2 are found at Index of /r4.2/current/host/fc37/rpm/ (if you need to check files that were installed to dom0 or domU, replace host with dom0 or vm, repsectively). A single buildinfo file might contain hashes for multiple RPM packages. For example, in this case we need the buildinfo file xen-4.17.2-8.fc37.x86_64.buildinfo to verify the RPM file xen-hypervisor-4.17.2-8.fc37.x86_64.rpm.

Verify both files

The buildinfo package should be signed by the release signing key for the relevant QubesOS release. It can be checked just like any other GPG-signed file:

gpg --verify xen-4.17.2-8.fc37.x86_64.buildinfo

Then check the hash of the RPM file and check that it matches the hash listed in the buildinfo file (buildinfo is a plaintext format, so you can just grep the file for the hash):

grep $(sha256sum xen-hypervisor-4.17.2-8.fc37.x86_64.rpm | cut -f1) xen-4.17.2-8.fc37.x86_64.buildinfo

Extract the binaries

RPM files can be unpacked using the rpm2cpio utility:

rpm2cpio xen-hypervisor-4.17.2-8.fc37.x86_64.rpm | cpio -imvd

Then, the hashes should match (replace {boot-drive} with the drive designation for your boot partition, such as sda1, and leave out the curly braces):

mount /dev/{boot-drive} /mnt
sha256sum boot/xen-4.17.2.gz /mnt/xen-4.17.2.gz
sha256sum boot/efi/EFI/qubes/xen-4.17.2.efi /mnt/efi/EFI/qubes/xen-4.17.2.efi /mnt/efi/EFI/qubes/xen.efi

Note that xen.efi is a copy of xen-4.17.2.efi, and the copy is not stored literally within the RPM, but since they hash to the same value we can be confident that they are not malicious.