8 KiB
(verification_chapter)=
Verification
Signature verification in the OpenPGP protocol is a complex process. There are lots of different factors that can influence the validity of a signature. Some signatures can be verified standalone, while others require the verification of a chain-like structure of other signatures, mostly on the issuers certificate. Signatures can be invalid due to the absence or presence of other signatures. A signature can be valid at one point in time and invalid merely a second later.
When are signatures valid?
As a necessary condition, a valid signature must be cryptographically correct, meaning the signature, as well as the signed information must be intact. However, there is a difference between signature correctness and validity. A signature might be correct, but still disqualify as a valid signature. Put mathematically, the set of valid signatures is a subset of the set of correct signatures.
The validity of a correct signature is additionally constrained by a number of conditions: Signatures need to be well-formed, meaning they must contain required signature subpackets in the proper subpacket area and must not contain unknown critical subpackets or notations. Most signatures have a limited validity period, constrained by the signature creation- and expiration time. Furthermore, some signatures need to be qualified by another valid signature in order to be considered valid. Lastly, signatures can be invalidated by revocations.
Temporal validity
A signature is valid only for a constrained period of time. A lower constraint for the validity period is the creation time of the signature. An exception from this rule are hard revocation signatures, where this lower constraint is dropped. An upper constraint might be the signatures 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.
The same reference time must be used when verifying additional qualifying signatures.
Self-qualifying and non-self-qualifying signatures
Some signatures can be verified on their own, while others require the verification of additional signatures on the issuer certificate. We will call the former category self-qualifying signatures. Typically, self-qualifying signatures are self-signatures, meaning signatures issued by an OpenPGP key over its own components. Examples for self-qualifying 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-qualifying 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 qualified to create such a signature. This qualification 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 Signing capable. Similarly, certification signatures over third-party certificates require the issuer key to carry a self-signature qualifying it to Certify other keys.
Self-qualifying signatures have no such limitations. For example, a certificate consisting only of a primary key and a single key-revocation self-signature contains everything needed to verify the revocation, as key-revocation self-signatures are self-qualifying. This construct is referred to as a revocation certificate.
On the other hand, 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, which qualify the signing subkey.
Revocations
A signature might be disqualified by the presence of a revocation signature. Revocations can be limited in scope, e.g. a subkey-revocation signature only revokes a single subkey. Moreover, revocations can also be constrained to a certain validity period by including a soft revocation reason and expiration time in the revocation signature.
TODO: Give guidance, which revocations need to be considered for different types 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.