Verify a signature
Signatures over data are used to verify the authenticity of that data. They are created with a key and are verified with the corresponding certificate. A signature is unique for a given amount of data - there are no "stand-alone" signatures.
Signatures come in 3 different formats:
- Inlined: the signed data and the signature are combined into a single file.
- Cleartext: the signature is appended to the data, using an ascii-armor.
- Detached: the signature is placed in a separate file.
Inlined and cleartext signatures can be verified by:
$ sq verify --message $FILE
or
$ sq verify --cleartext $FILE
sq
will detect if you chose the wrong option and will try to verify the $FILE
nonetheless.
Instead of providing the data to verify via a file, you can pipe it through STDIN
:
$ cat $FILE | sq verify --message
In case the necessary certificate is locally available, these commands return a success message:
$ sq verify $FILE
Authenticating B535B0D4736F809892B42F4A388344D1DEAA4483 (Alice (UNAUTHENTICATED)) using the web of trust:
B535B0D4736F809892B42F4A388344D1DEAA4483: <alice@example.com> is unauthenticated and may be an impersonation!
Fully authenticated (120 of 120) B535B0D4736F809892B42F4A388344D1DEAA4483, Alice
◯─┬ 7FDAD1C466501980F0765EE53B7051904AED91CF
│ └ (Local Trust Root)
│
│ certified the following binding on 2025‑01‑10
│
└─┬ B535B0D4736F809892B42F4A388344D1DEAA4483
└ Alice
Authenticated signature made by B535B0D4736F809892B42F4A388344D1DEAA4483 (Alice (authenticated))
1 authenticated signature.
If you get
Can't authenticate signature allegedly made by
$SOME_FINGERPRINT: missing certificate.
Hint: Consider searching for the certificate using:
$ sq network search $SOME_FINGERPRINT
0 authenticated signatures, 1 uncheckable signature.
Error: Verification failed: could not authenticate any signatures
you are missing the certificate - sq
proposes a way to get the certificate from a key server, WKD or DANE. Beware: this will get you the certificate of the key which created the signature - there is no guaranty that this key is the right one. Double check the displayed fingerprint to make sure that it is from the right certificate and not from an impostor.
If you get a result like the following:
...
Authenticating $FINGERPRINT ($USER_ID (UNAUTHENTICATED)) using the
web of trust:
$FINGERPRINT: $USER_ID is unauthenticated and may be an impersonation!
...
Can't authenticate signature made by $FINGERPRINT
($USER_ID (UNAUTHENTICATED)): the certificate can't be authenticated.
Hint: After checking that $FINGERPRINT belongs
to $USER_ID (UNAUTHENTICATED), you can mark it as authenticated using:
$ sq pki link add --cert=$FINGERPRINT --userid=$USER_ID
0 authenticated signatures, 1 unauthenticated signature.
Error: Verification failed: could not authenticate any signatures
then you have the certificate locally available and the signature is valid. This however doesn't imply that the key which created this signature is the right one. There are several ways to continue from here:
- You can pass the fingerprint of a certificate, which just checks if the signature is made by the corresponding key - ignoring User IDs associated with the certificate:
$ sq verify --signer $FINGERPRINT $FILE
- You can authenticate (at least) one of the User IDs of the certificate by adding a link:
$ sq pki link add --cert=$FINGERPRINT --userid=$USER_ID
If you verify again, sq
will recognize the authentication and return success.
Detached signatures
Inlined and cleartext signatures are included into the signed data, thus changing its datatype. Before the data can be used again, this mix has to be untangled. Detached signatures are written to an extra file, which leaves the data untouched. This way the data can be used immediately, allowing the user to skip the signature verification.
The file containing the detached signature has to be passed explicitly to sq
:
$ sq verify --signature-file $SIGNATURE_FILE $FILE
Time
If you want to verify a signature, but the corresponding certificate is expired, you can modify the concept of "now" for sq
. You can use --time
to tell sq
explicitly what time and date to assume as a reference when checking expiration dates.
$ sq verify --time 20120501 --message $FILE
This allows you to verify a signature as if today would be the first of may, 2012. The expiration time of the certificate is then matched against this date and not today.
Example: Download and verify Qubes OS
Qubes OS is a Linux distribution and - as usual - you can download an installation image from their website. To ensure the authenticity and integrity of the image, it is signed by the Cubes OS maintainers with a specific release key. As there are several releases, there are several release keys. To ease the adoption, each release key is certified by an additional key, the "Qubes Master Signing Key", functioning as a Certificate Authority.
To utilize the CA, first retrieve the "Qubes Master Signing Key" certificate:
$ sq network search 0x427F11FD0FAA4B080123F01CDDFA1A3E36879494
This example takes a fingerprint from the website of Qubes OS. If you want to install Qubes OS (and therefore download an untainted installation image), recheck the fingerprint!
Now declare the new certificate as trust introducer:
$ sq pki link authorize --depth 1 --cert 427F11FD0FAA4B080123F01CDDFA1A3E36879494 --regex 'Qubes OS Release ([0-9])+.([0-9])+ Signing Key' --all
Passing --depth 1
authorizes the certificate to only authenticate directly certified certificates. --regex
further limits the capabilities to only authorize certificates having a User IDs matching the regular expression.
With the CA certificate in place, the next step is to download the release key.
$ sq network search https://keys.qubes-os.org/keys/qubes-release-4.2-signing-key.asc
The URL is taken from the download page of the Qubes OS project - it might be different when you read this.
$ sq cert list
- 427F11FD0FAA4B080123F01CDDFA1A3E36879494
- created 2010-04-01 12:26:33 UTC
- [ ✓ ] Qubes Master Signing Key
- 9C884DF3F81064A569A4A9FAE022E58F8E34D89F
- created 2022-10-04 14:10:01 UTC
- [ ✓ ] Qubes OS Release 4.2 Signing Key
- C67DF04E3C358CA5A6BFF664A8C9447ECEE006F0
- [ ✓ ] Local Trust Root
Hint: To view why a user ID is considered valid, pass `--show-paths`.
Hint: To see more details about a certificate, for example C67DF04E3C358CA5A6BFF664A8C9447ECEE006F0, run:
$ sq inspect --cert=C67DF04E3C358CA5A6BFF664A8C9447ECEE006F0
7 bindings found.
Skipped 4 bindings, which could not be authenticated.
Pass `--gossip` to see the unauthenticated bindings.
Because the "Qubes Master Signing Key" is marked as a trust introducer, the "Qubes OS Release 4.2 Signing Key" - which is directly certified by the master key (satisfying --depth 1
) and has a User ID matching the pattern from --regex
- is considered authentic.
Now get the installation image and the detached signature:
$ wget https://mirrors.edge.kernel.org/qubes/iso/Qubes-R4.2.3-x86_64.iso
$ wget https://mirrors.edge.kernel.org/qubes/iso/Qubes-R4.2.3-x86_64.iso.asc
The URLs are - again - from the download page of Qubes OS.
Now verify the download:
$ sq verify --signature-file Qubes-R4.2.3-x86_64.iso.asc Qubes-R4.2.3-x86_64.iso
Authenticating 9C884DF3F81064A569A4A9FAE022E58F8E34D89F (Qubes OS Release 4.2 Signing Key (UNAUTHENTICATED)) using the web of trust:
Fully authenticated (120 of 120) 9C884DF3F81064A569A4A9FAE022E58F8E34D89F, Qubes OS Release 4.2 Signing Key
◯─┬ C67DF04E3C358CA5A6BFF664A8C9447ECEE006F0
│ └ (Local Trust Root)
│
│ certified the following certificate on 2025‑01‑14 as a meta-introducer (depth: unconstrained)
│
├─┬ 427F11FD0FAA4B080123F01CDDFA1A3E36879494
│ └ (Qubes Master Signing Key)
│
│ certified the following binding on 2023‑06‑03
│
└─┬ 9C884DF3F81064A569A4A9FAE022E58F8E34D89F
└ Qubes OS Release 4.2 Signing Key
Authenticated signature made by 9C884DF3F81064A569A4A9FAE022E58F8E34D89F (Qubes OS Release 4.2 Signing Key (authenticated))
1 authenticated signature.
The signature of the image file is good. This is a proof that the image is authentic and its integrity is confirmed.
Download
Once you downloaded and authenticated the release key, there is a shorter, more convenient subcommand sq
offers:
$ sq download --url https://mirrors.edge.kernel.org/qubes/iso/Qubes-R4.2.3-x86_64.iso --signature-url https://mirrors.edge.kernel.org/qubes/iso/Qubes-R4.2.3-x86_64.iso.asc --signer-userid "Qubes OS Release 4.2 Signing Key" --output qubes_4.2.3.iso
Alleged signer 9C884DF3F81064A569A4A9FAE022E58F8E34D89F is good listed.
Finished downloading data. Authenticating data.
Authenticated signature made by 9C884DF3F81064A569A4A9FAE022E58F8E34D89F (Qubes OS Release 4.2 Signing Key (UNAUTHENTICATED))
1 authenticated signature.