Signatures are perhaps the single most central mechanism in OpenPGP. They act as the syntax that allows forming and interpreting rich statements about certificates and their components, as well as data.
Without signatures, there would only be loose keys, impossible to associate with a certificate, or their owner. Signatures are the glue that allows for components (component keys and identity components) to be assembled into hierarchical certificates, and for messages to gain authenticity.
- [*OpenPGP signature packets*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-packet-type-id-2), which combine a *type* setting, additional metadata, and a raw cryptographic signature.
The OpenPGP standard defines a set of [Signature Types](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-types), each identified by a numerical *signature type ID*. Signature types define the intent of a signature, and how it needs to be interpreted.
### Generation and validation of cryptographic signatures in OpenPGP
The central element of an OpenPGP signature packet is the raw cryptographic signature it contains. This cryptographic signature is calculated by the issuer of that signature packet.
In abstract terms, the cryptographic signature certifies a set of input data ("signature over"): The signer is making a statement about that set of input data. That statement is encoded as the signature packet.
If we look more closely, the cryptographic signature is actually calculated in two steps:
1. A hash digest is calculated from the set of input data.
2. The signature is calculated for this hash digest.
The exact input data depends on the signature type. However, the input data always comprises the information that the signature makes a statement about. It includes the metadata in the OpenPGP signature packet itself.
A bare cryptographic signature - even when combined with a signature type ID - is usually not sufficiently expressive. So, to encode additional metadata in signature packets, the OpenPGP protocol introduced signature subpackets (in [RFC 2440](https://datatracker.ietf.org/doc/html/rfc2440)).
Subpackets are well-defined data structures that can be placed into signature packets as sub-elements. They provide additional context and meaning for a signature. Subpackets encode data in a key-value format. The RFC defines all possible keys as [subpacket type IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-subpacket-types-r) and provides the value format (and meaning) for all of them.
- The [*issuer fingerprint*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#issuer-fingerprint-subpacket) subpacket, which encodes the fingerprint of the component key that issued the signature, or
- The [*key flags*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags) subpacket, that defines which capabilities are assigned to a component key, in a certificate.
Signature subpackets can reside in [two different areas](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-hashed-vs-unhashed-subpacke) of a signature packet:
- Subpackets in the *hashed area* are included in the hash digest for that signature. In other words: hashed subpackets are covered by the cryptographic signature in the signature packet. Recipients of the signature can be sure that these subpackets express the intent of the issuer of the signature.
- Subpackets in the *unhashed area*, by contrast, are not included in the hash digest for that signature. They are therefore not protected against tampering. The unhashed area can be used to retroactively add, change or remove metadata in a signature packet, without invalidating it. Since the unhashed area doesn't provide any cryptographic guarantees, it is only intended for advisory packets, or packets that self-authenticate (e.g. the issuer fingerprint subpacket, whose "correctness" can be proven by successfully verifying the signature using the referenced issuer key).
Each signature subpacket has a flag that indicates whether the subpacket is *critical*. When set, the criticality flag signals that a receiving implementation that does not know a subpacket type, must consider this an error, and may not consider the signature valid.
The reason for this mechanism is that OpenPGP implementations may only support subsets of the standard - and the standard may be extended over time, including by the addition of new subpacket types.
However, it would be fatal if, for example, an implementation did not understand the concept of signature expiration. Such an implementation would potentially accept an already expired signature.
By marking the expiration date subpacket as critical, the creating implementation can indicate that recipients who do not understand this of subpacket must consider the signature as invalid.
RFC Sections [5.2.3.11](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-creation-time) - [5.2.3.36](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr) give guidance on which subpackets should be marked as critical.
[Notations](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#notation-data) are a signature subpacket type that can be used to effectively extend the otherwise limited set of signature subpacket types with user-defined notations. An issuer can use notations to add name-value data to an OpenPGP signature.
Notation names are UTF-8 encoded strings. They may reside in the "user namespace," which means a notation *tag* (in UTF-8 string format) followed by a DNS domain name.
#### Use of notations by Keyoxide
Notations have, for example, been used for the popular decentralized identity verification service [Keyoxide](https://keyoxide.org/). Keyoxide uses notations in the `ariadne.id` namespace. See the [Keyoxide documentation](https://docs.keyoxide.org/wiki/ariadne-identity/) for more details.
investigate, discuss: GnuPG uses preference packets for the User ID that was addressed while sequoia completely omits User ID preferences and either uses Direct Key Sigs or (I think) primary User ID.
C-R 5.2. says: An implementation MUST generate a version 6 signature when signing with a version 6 key. An implementation MUST generate a version 4 signature when signing with a version 4 key.