mirror of
https://codeberg.org/openpgp/notes.git
synced 2025-09-10 11:49:40 +02:00
91 lines
6.8 KiB
Markdown
91 lines
6.8 KiB
Markdown
<!--
|
|
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
|
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
-->
|
|
|
|
(verification_chapter)=
|
|
# Verification
|
|
|
|
Signature verification in the OpenPGP protocol is a complex process.
|
|
Some signatures can be verified standalone, while others require the verification of a chain-like structure of other signatures, mostly on the issuers certificate.
|
|
|
|
We will call the former category *self-authorizing* signatures.
|
|
Typically, self-authorizing signatures are self-signatures, meaning signatures issued by an OpenPGP key over its own components.
|
|
Examples for self-authorizing signatures are direct-key self-signatures (0x1F), User-ID self-certifications (0x10-0x13), key-revocation self-signatures (0x20), certification revocation self-signatures (0x30) or signatures used to bind or revoke subkeys (0x18, 0x19, 0x28).
|
|
|
|
Examples for signatures which are not self-authorizing are data signatures (0x00, 0x01) and signatures issued over third-party certificates, such as third-party direct-key signatures (0x1F) or key-revocations (0x20), third-party certification or revocation signatures (0x10-0x13, 0x30).
|
|
To verify such signatures, it is not sufficient to only look at the signature itself.
|
|
|
|
The reason is, that the issuer (sub-) key needs to be authorized to create such a signature.
|
|
This authorization typically comes via another self-signature on the key itself.
|
|
For example, a data signature over an email body may be issued by a subkey only if that subkey is validly bound to the users certificate via a subkey binding signature, and that binding signature needs to contain a key flags subpacket marking the subkey as **S**igning capable.
|
|
Similarly, certification signatures over third-party certificates require the issuer key to carry a self-signature authorizing it to **C**ertify other keys.
|
|
|
|
Self-authorizing signatures have no such limitations.
|
|
|
|
## When are signatures valid?
|
|
|
|
There is a difference between signature *correctness* and *validity*.
|
|
A signature might be correct, but still disqualify as a valid signature.
|
|
|
|
The validity of a signature is constrained by a number of conditions.
|
|
First and foremost, a signature must be cryptographically correct, meaning the signature, as well as the signed information must be intact.
|
|
|
|
### Temporal validity
|
|
|
|
A signature is valid only for a constrained period of time.
|
|
A hard, lower constraint for the validity period is the creation time of the signature.
|
|
An upper constraint might be its expiration time.
|
|
|
|
When checking a signature for validity, a reference time is defined.
|
|
For an email that might be the signature creation time itself, or the reception date.
|
|
For the signature to qualify as valid, it needs to be effective, in other words, the reference time must fall into the period from signature creation to signature expiration.
|
|
|
|
Futhermore, signatures on a certificate form a chain, or rather a tree of signatures, originating from the certificates primary key down to signatures issued by the certificate.
|
|
In order to verify, whether a signature is valid, the whole signature chain must be checked, taking expiration dates, capabilities and revocations into account.
|
|
|
|
For example, in order to verify a data signature over a text document, an implementation would need to verify not only the data signature itself, but also the binding signature (and back-signature) of the signing subkey, as well as the direct-key signature on the primary key of the issuer certificate.
|
|
|
|
The signature might be invalidated by corruption of the text document, corruption of the data signature packet, expiration or revocation of the primary or signing subkey, or revocation/expiration of the primary User ID.
|
|
Furthermore, the signature might not be valid in the first place, due to a missing subkey binding signature, or a missing `SIGN_DATA` keyflag on the subkey binding signature.
|
|
|
|
```{include} mermaid/09-sigtree.md
|
|
```
|
|
|
|
|
|
- Validity as a tree of signatures
|
|
|
|
## Which signatures take precedence?
|
|
|
|
An OpenPGP certificate can have multiple signatures with conflicting information in them.
|
|
For example, the latest direct-key signature could list "SHA512, SHA384" as hash algorithm preferences, while the latest self-certification of User-ID "Bob" could list "SHA256" only.
|
|
For yet another User-ID "Bobby", the self-signature could list no hash algorithm preferences at all.
|
|
If the user wants to compose a signed message using the associated OpenPGP key, they need to figure out, which preferences to use.
|
|
The specification recommends, that implementations decide which signature takes precendence by the way the certificate is "addressed".
|
|
If the user wants to write an email as "Bob", it should consider the signature on "Bob", so SHA256 should be used as hash algorithm.
|
|
If instead the user wants to write as "Bobby", the impementation should inspect the self-certification on "Bobby" instead.
|
|
However, since this signature does not carry any hash algorithm preferences subpacket, the implementation must fall back to the direct-key signature instead.
|
|
The same is true, if the certificate is used without any User-ID as sender.
|
|
|
|
But it gets more complicated still.
|
|
Algorithm preferences can also "live" on subkey binding signatures, so if the certificate has a dedicated signing subkey, there is yet another signature which could take precendence.
|
|
Preferences from the subkey binding signature take precendence over the direct-key signature, but not over self-certifications on the User-ID.
|
|
|
|
TODO: Have a table that lists which signatures take precendence in which cases.
|
|
|
|
There can be more than one signature on a component. For example, there could be 3 direct-key signatures, e.g. because the user extended the lifespan of their key 2 times already.
|
|
In general, for each component, only the newest self-signature is "in effect", and older signatures are "shadowed".
|
|
For each certificate, there is at most one "active" direct-key signature, for each User-ID at most one active self-certification and for each subkey exactly one subkey binding.
|
|
TODO: Direct-Key Signaures can be revoked, canceling them, meaning an older one might get active?
|
|
|
|
## Complexity of the packet format
|
|
Unfortunately, the OpenPGP packet format allows for quite a lot of flexibility when composing certificates.
|
|
User-ID packets for example, are not fixed with regards to their position, which means that an attacker (or canonicalizer) can change the order in which User-IDs appear in the certificates packet sequence.
|
|
|
|
|
|
|
|
As a concrete example, consider a certificate with multiple User-IDs, all marked as primary. Or equaly, a certificate with multiple User-IDs of which none is marked as primary.
|
|
Clients might apply different heuristics to figure out, which User-ID actually qualifies as the primary User-ID here.
|
|
|
|
You might wonder, which signature on the primary key takes precendence in case of multiple signature candidates with conflicting signature subpackets.
|
|
|