The Qubes OS Project uses `digital signatures <https://en.wikipedia.org/wiki/Digital_signature>`__ to
guarantee the authenticity and integrity of certain important assets.
This page explains how to verify those signatures. It is extremely
important for your security to understand and apply these practices.
What digital signatures can and cannot prove
--------------------------------------------
Most people — even programmers — are confused about the basic concepts
underlying digital signatures. Therefore, most people should read this
section, even if it looks trivial at first sight.
Digital signatures can prove both **authenticity** and **integrity** to
a reasonable degree of certainty. **Authenticity** ensures that a given
file was indeed created by the person who signed it (i.e., that a third
party did not forge it). **Integrity** ensures that the contents of the
file have not been tampered with (i.e., that a third party has not
undetectably altered its contents *en route*).
Digital signatures **cannot** prove, e.g., that the signed file is not
malicious. In fact, there is nothing that could stop someone from
signing a malicious program (and it happens from time to time in
reality).
The point is that we must decide who we will trust (e.g., Linus
Torvalds, Microsoft, or the Qubes Project) and assume that if a trusted
party signed a given file, then it should not be malicious or
negligently buggy. The decision of whether to trust any given party is
beyond the scope of digital signatures. It’s more of a social and
political decision.
Once we decide to trust certain parties, digital signatures are useful,
because they make it possible for us to limit our trust only to those
few parties we choose and not to worry about all the bad things that can
happen between them and us, e.g., server compromises (qubes-os.org will
surely be compromised one day, so :ref:`don’t blindly trust the live version of this site <introduction/faq:should i trust this website?>`), dishonest IT staff
at the hosting company, dishonest staff at the ISPs, Wi-Fi attacks, etc.
We call this philosophy :ref:`distrusting the infrastructure <introduction/faq:what does it mean to "distrust the infrastructure"?>`.
By verifying all the files we download that purport to be authored by a
party we’ve chosen to trust, we eliminate concerns about the bad things
discussed above, since we can easily detect whether any files have been
tampered with (and subsequently choose to refrain from executing,
installing, or opening them).
However, for digital signatures to make sense, we must ensure that the
public keys we use for signature verification are the original ones.
Anybody can generate a cryptographic key that purports to belong to “The
Qubes OS Project,” but of course only the keys that we (the real Qubes
developers) generate are the genuine ones. The rest of this page
explains how to verify the authenticity of the various keys used in the
project and how to use those keys to verify certain important assets.
OpenPGP software
----------------
We use `PGP <https://en.wikipedia.org/wiki/Pretty_Good_Privacy>`__
Once you’ve obtained the QMSK, you must verify that it’s authentic
rather than a forgery. Anyone can create a PGP key with the name “Qubes
Master Signing Key” and the short key ID ``0x36879494``, so you cannot
rely on these alone. You also should not rely on any single website, not
even over HTTPS.
So, what *should* you do? One option is to use the PGP `Web of Trust <https://en.wikipedia.org/wiki/Web_of_trust>`__. In addition, some
operating systems include the means to acquire the QMSK securely. For
example, on Fedora, ``dnf install distribution-gpg-keys`` will get you
the QMSK along with several other Qubes keys. On Debian, your keyring
may already contain the necessary keys.
Perhaps the most common route is to rely on the key’s fingerprint, which
is a string of 40 alphanumeric characters, like this:
..code:: bash
427F 11FD 0FAA 4B08 0123 F01C DDFA 1A3E 3687 9494
Every PGP key has one of these fingerprints, which uniquely identifies
it among all PGP keys. (On the command line, you can view a key’s
fingerprint with the ``gpg2 --fingerprint <KEY_ID>`` command.)
Therefore, if you know the genuine QMSK fingerprint, then you always
have an easy way to confirm whether any purported copy of it is
authentic, simply by comparing the fingerprints.
But how do you know which fingerprint is the real one? After all, :ref:`this website could be compromised <introduction/faq:should i trust this website?>`, so
the fingerprint you see here may not be genuine. That’s why we strongly
suggest obtaining the fingerprint from *multiple independent sources in several different ways*, then comparing the strings of letters and
numbers to make sure they match.
For the purpose of convincing yourself that you know the authentic QMSK
fingerprint, spaces and capitalization don’t matter. In other words, all
of these fingerprints are considered the same:
..code:: bash
427F 11FD 0FAA 4B08 0123 F01C DDFA 1A3E 3687 9494
427f 11fd 0faa 4b08 0123 f01c ddfa 1a3e 3687 9494
427F11FD0FAA4B080123F01CDDFA1A3E36879494
427f11fd0faa4b080123f01cddfa1a3e36879494
Instead, what matters is that *all* the characters are present in
*exactly* the same order. If even one character is different, the
fingerprints should not be considered the same. Even if two fingerprints
have all the same characters, if any of those characters are in a
different order, sequence, or position, then the fingerprints should not
be considered the same.
However, for the purpose of *searching for*, *looking up*, or *entering*
keys, spaces and capitalization can matter, depending on the software or
tool you’re using. You may need to try different variations (e.g., with
and without spaces). You may also sometimes see (or need to enter) the
entire fingerprint prefixed with ``0x``, as in:
..code:: bash
0x427F11FD0FAA4B080123F01CDDFA1A3E36879494
0x427f11fd0faa4b080123f01cddfa1a3e36879494
The ``0x`` prefix is sometimes used to indicate that the string
following it is a hexadecimal value, and some PGP-related tools may
require this prefix. Again, for the purpose of convincing yourself that
you know the authentic QMSK fingerprint, you may safely ignore the
``0x`` prefix, as it is not part of the fingerprint. As long as the
40-character string after the ``0x`` matches exactly, the fingerprint is
considered the same. The ``0x`` prefix only matters if the software or
tool you’re using cares about it.
The general idea of “comparing fingerprints” is to go out into the world
(whether digitally, physically, or both) and find other 40-character
strings purporting to be the QMSK fingerprint, then compare them to your
own purported QMSK fingerprint to ensure that the sequence of
alphanumeric characters is exactly the same (again, regardless of spaces
or capitalization). If any of the characters do not match or are not in
the same order, then at least one of the fingerprints is a forgery. Here
are some ideas to get you started:
- Check the fingerprint on various websites (e.g., `mailing lists <https://groups.google.com/g/qubes-devel/c/RqR9WPxICwg/m/kaQwknZPDHkJ>`__,
gpg: Signature made Tue 08 Mar 2016 07:40:56 PM PST using RSA key ID 03FA5082
gpg: using PGP trust model
gpg: Good signature from "Qubes OS Release X Signing Key"
gpg: binary signature, digest algorithm SHA256
This is just an example, so the output you receive will not look exactly
the same. What matters is the line that says
``Good signature from "Qubes OS Release X Signing Key"``. This confirms
that the signature on the ISO is good.
If you don’t see a good signature here, go back and follow the
instructions in this section carefully, and consult the `troubleshooting FAQ <#troubleshooting-faq>`__ below.
How to re-verify installation media after writing
-------------------------------------------------
*This is an optional section intended for advanced users.*
After you have authenticated your Qubes ISO and written it onto your
desired medium (such as a USB drive or optical disc), you can re-verify
the data that has been written to your medium. Why would you want to do
this when you’ve already verified the original ISO? Well, it’s
conceivable that a sufficiently sophisticated adversary might allow your
initial ISO verification to succeed (so as not to alert you that your
machine has been compromised, for example), then surreptitiously modify
the data as it is being written onto your installation medium, resulting
in a compromised Qubes installer. This might increase the odds that the
attack goes undetected. One way to mitigate this risk is to re-verify
the installer after writing it onto an installation medium that cannot
be altered, such as a USB drive with a properly-implemented physical
write-protect switch and firmware that is either unflashable or
cryptographically-signed (or both), as discussed in our :doc:`installation security considerations </user/downloading-installing-upgrading/install-security>`.
This section will walk through an example of re-verifying the installer
on such a device. We begin by assuming that you have just :ref:`written your desired Qubes ISO onto the USB drive <user/downloading-installing-upgrading/installation-guide:copying the iso onto the installation medium>`.
First, unplug your USB drive and flip the write protect switch so that
the data on the drive can no longer be altered. If you have a different
computer from the one you used to create the installation medium,
consider using that computer. If not, try to at least use a fresh VM
(e.g., if it’s a Qubes system). The idea is that the original machine
may have been compromised, and using a different one for re-verification
forces your hypothetical adversary to compromise an additional machine
in order to succeed.
Now, our goal is to perform the same verification steps as we did with
the original ISO, except, this time, we’ll be reading the installer data
directly from the write-protected USB drive instead of from the original
ISO file. First, let’s compute the SHA-256 hash value of the data on the
drive. (This assumes you’re already familiar with `how to verify the cryptographic hash values of Qubes ISOs <#how-to-verify-the-cryptographic-hash-values-of-qubes-isos>`__.)
In order to do this, we have to know the exact size, in bytes, of the
original ISO. There are two ways to get this information: from the ISO
itself and from the Qubes website. Here’s an example of the first way:
2.`Import and authenticate the Qubes Master Signing Key. <#how-to-import-and-authenticate-the-qubes-master-signing-key>`__
3.:doc:`Import and authenticate keys from the Qubes security pack (qubes-secpack). </project-security/security-pack>` Please see our :ref:`PGP key policies <project-security/security-pack:pgp key policies>` for important
information about these keys.
Whenever you use one of the `Qubes repositories <https://github.com/QubesOS>`__, you should use Git to
verify the PGP signature in a tag on the latest commit or on the latest
commit itself. (One or both may be present, but only one is required.)
If there is no trusted signed tag or commit on top, any commits after
the latest trusted signed tag or commit should **not** be trusted. If
you come across a repo with any unsigned commits, you should not add any
of your own signed tags or commits on top of them unless you personally
vouch for the trustworthiness of the unsigned commits. Instead, ask the
person who pushed the unsigned commits to sign them.
You should always perform this verification on a trusted local machine
with properly authenticated keys rather than relying on a third party,
such as GitHub. While the GitHub interface may claim that a commit has a
verified signature from a member of the Qubes team, this is only
trustworthy if GitHub has performed the signature check correctly, the
account identity is authentic, an admin has not replaced the user’s key,
GitHub’s servers have not been compromised, and so on. Since there’s no
way for you to be certain that all such conditions hold, you’re much
better off verifying signatures yourself. (Also see: :ref:`distrusting the infrastructure <introduction/faq:what does it mean to "distrust the infrastructure"?>`.)
How to verify a signature on a Git tag
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..code:: bash
$ git tag -v <tag name>
or
..code:: bash
$ git verify-tag <tag name>
How to verify a signature on a Git commit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..code:: bash
$ git log --show-signature <commit ID>
or
..code:: bash
$ git verify-commit <commit ID>
Troubleshooting FAQ
-------------------
Why am I getting "Can't check signature: public key not found"?
You’re not verifying against the correct `detached PGP signature file <#how-to-verify-detached-pgp-signatures-on-qubes-isos>`__, or the
signature file has been modified. Try downloading it again or from a
different source.
Do I have to verify both the `detached PGP signature file <#how-to-verify-detached-pgp-signatures-on-qubes-isos>`__ and the `cryptographic hash values <#how-to-verify-the-cryptographic-hash-values-of-qubes-isos>`__?