<!--
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
SPDX-License-Identifier: CC-BY-SA-4.0
-->

(component_signatures_chapter)=
# Signatures on components

In this chapter, we'll consider OpenPGP signatures that apply to components. That is, signatures that apply to:

- Component keys (primary keys or subkeys), or
- Identity components (User IDs or User attributes).

This chapter adds a lot of detail to the material we discussed in the {ref}`certificates_chapter` chapter. Signatures on components are a crucial mechanism for forming OpenPGP certificates (which combine component keys and identities, via signatures on those components).

Additionally, signatures on components play a crucial role for authentication of identities. Mechanisms for decentralized authentication are one of OpenPGP's core strengths, we'll look into how they work.

Finally, signatures on components are also a central mechanism for life-cycle management of OpenPGP certificates and their components. This includes defining or changing expiration dates, or issuing revocations, for certificates or their components.

## Self-signatures and third-party signatures

There are two important scenarios to distinguish:

- *Self-signatures*: Issued by the certificate's owner, using the primary key of the same certificate.
- *Third-party signatures*: Issued by a key that is part of a different certificate.

### Meaning differs between self- and third-party signatures

The meaning of a signature depends in part on who issued it. A self-signature often has a different meaning from a signature issued by a third party.

For example:

- A [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued as a self-signature can be used to set preferences and advertise features that apply to the whole certificate, while
- A similar [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued by a third party, which carries a [trust signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-trust-signature) subpacket, acts as a statement by the issuer that they delegate trust to the signed certificate (the issuer thereby uses the remote certificate as a trust root in the *Web of Trust*).

Or:

- Certifying self-signatures (type IDs `0x10` - `0x13`) are used to bind a User ID to a certificate, while
- the same signature type IDs issued by a third party are statements by the signer that they endorse the authenticity of the signed User ID to some degree.

There are further signature types for signatures on data, as well as designated types to bind and revoke subkeys.

## Signatures on components

A typical use-case for a self-signature is to attach a User ID, such as a name and email address to a certificate.
This is done by calculating the signature over the User ID and the public primary key.
The resulting User ID certification (typically type 0x13, potentially type 0x10-0x12) can then be inserted into the certificate, right after the User ID packet.

Other examples for self-signatures are binding signatures for subkeys. To add an OpenPGP subkey to a certificate, a subkey binding signature is calculated over the public primary key, followed by the public subkey.
The resulting subkey binding signature (type 0x18) can then be inserted into the certificate right after the subkey.
If the subkey itself is intended to be used as a **S**igning key, an extra step is required.
To prevent an attacker from being able to "adopt" a victims signing subkey and then being able to claim to be the origin of signatures in fact made by victim, subkey binding signatures for signing subkeys need to include an embedded "back signature" (formally known as [primary key binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-primary-binding)) made by the signing key itself.

Certifications over User IDs can also be used to certify certificates of third-parties.
If Alice is certain that `Bob Baker <bob@example.com>` controls the key `0xB0B`, she can create a User ID certification signature for that identity and send it to Bob.
Bob can then add this signature to his certificate.
TODO: More WoT.

```{note}
The **certify others** key flag is not required in order to issue certifying self-signatures.
This key flag is only necessary to issue valid third-party certifications.
```

### Revocations

One important class of self-signatures are revocations.

A revocation signature is used to retract the statement formed by a prior signature.
A subkey revocation signature revokes a prior subkey binding signature, while a certification revocation revokes a certification signature.
Typical use-cases for revocations are marking certificates or individual subkeys as unusable (for example, when the private key has been compromised or superseded), or marking User IDs as no longer used.

A revocation signature can either be hard or soft. A soft revocation of a certificate invalidates it from the revocation signature's creation time onwards. This means signatures issued before the revocation remain intact. A hard revocation, by contrast, invalidates the certificate retroactively, rendering all issued signatures invalid, regardless of creation time. Soft revocations are typically used whenever a key or User ID is retired or superseded gracefully, while hard revocations can, for example, signal compromise of secret key material.

## Self-signatures: Linking the components of a certificate

So far we've looked at the components in an OpenPGP certificate, but certificates actually contain another set of elements, which bind the components together, and add metadata to them.

Internally, an OpenPGP certificate consists of a sequence of OpenPGP packets. These packets are just stringed together, one after the other. When a certificate is stored in a file[^tpk], it's easy to remove some of these packets, or add new ones.

[^tpk]: When stored in a file, OpenPGP certificates are in a format called [transferable public key](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-transferable-public-keys).

However, the owner of a certificate doesn't want a third party to add subkeys (or add [identity components](identity_components)) to their certificate, pretending that the certificate owner put those components there.

To prevent malicious addition of components, OpenPGP uses cryptographic signatures. These signatures show that components have been added by the owner of the OpenPGP certificate (these linking signatures are issued by the primary key of the certificate).

So while anyone can still unilaterally store unrelated subkeys and [identity components](identity_components) in an OpenPGP certificate dataset, OpenPGP implementations that read this certificate should discard components that don't have a valid cryptographic connection with the certificate.

(Conversely, it's easy for a third party to leave out packets when passing on an OpenPGP certificate. An attacker can, for example, choose to omit revocation packets. The recipient of such a partial copy has no way to notice the omission, without access to a different source for the certificate that contains the revocation packet.)

Note, though, that there are some cases where third parties legitimately add "unbound" packets to certificates (that is: packets that are not signed by the certificate's owner):

- [Third-party certifications](third_party_cert) are traditionally added to the certificate that they make a statement about (this can cause problems in systems that unconditionally accept and include such certifications[^flooding]),
- OpenPGP software may add [unbound identity data](unbound_user_ids), locally.

[^flooding]: Storing third-party identity certifications in the target OpenPGP certificate is convenient for consumers: it is easy to find all relevant certifications in one central location. However, when third parties can unilaterally add certifications, this opens an avenue for denial-of-service attacks by flooding. The SKS network of OpenPGP key servers [allowed and experienced this problem](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html).

(bind_subkey)=
### Binding subkeys to a certificate

Linking a subkey to an OpenPGP certificate is done with a ["Subkey Binding Signature"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-subkey-binding). Such a signature signals that the "primary key wants to be associated with the subkey".

The subkey binding signature also adds metadata.

```{figure} diag/subkey_binding_signature.png

Linking an OpenPGP subkey to the primary key with a binding signature
```

The [Signature packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-packet-tag-2) that binds the subkey to the primary key has the signature type [SubkeyBinding](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-subkey-binding-signature-si).


In order to specify an expiration time for the subkey, a key expiration time subpacket can be included. Note, that the validity of the subkey is bounded by that of the primary key, meaning an expired primary key causes the subkey to be invalidated, no matter the subkey expiration time.

Note, that a subkey cannot be "older" than the primary key. The value of the subkeys creation date MUST be greater than that of the primary key.

### Special case: Binding signing subkeys to a certificate

Binding subkeys with the "signing" key flag is a special case. For the most part, it works the same as binding other types of subkeys, but there is an additional requirement:

When binding a signing subkey to a primary key, it is not sufficient that the "primary key wants to be associated with the subkey." In addition, the subkey must signal that it "wants to be associated with that primary key."

Otherwise, Alice could "adopt" Bob's signing subkey and convincingly claim that she made signatures that were in fact issued by Bob.
This is to prevent an attack where the attacker "adopts" the victims signing subkey as their own in order to claim ownership over documents which were in fact signed by the victim.
Contrary to the `SubkeyBinding` signature, which is issued by the certificate's primary key, the `PrimaryKeyBinding` signature is instead created by the subkey.

```{figure} diag/subkey_binding_signatur_for_signing_sk.png

Linking an OpenPGP signing subkey to the primary key with a binding signature, and an embedded primary key binding signature
```

This additional "Primary Key Binding" Signature is informally called a "back signature" (because the subkey uses the signature to point "back" to the primary key) is an embedded `PrimaryKeyBinding` "back signature" (type 0x19).

The *primary key binding signature* is "embedded" as subpacket data in the *subkey binding signature* that connects the signing subkey to the primary key.

### Binding identities to a certificate

"User ID" identity components are bound to an OpenPGP certificate by issuing a self-signature ("User Attributes" work analogously).

For example, the User ID `Alice Adams <alice@example.org>` may be associated with Alice's certificate `AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6  7F33 00F9 FB0E C457 378C D29F 1026 98B3`.

Alice can link a User ID to her OpenPGP certificate with a cryptographic signature. To link a User ID, a self-signature is created (usually with the signature type [PositiveCertification](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-positive-cert)). This signature is issued by the primary key.

```{figure} diag/user_id_certification.png
---
---
Linking a User ID to an OpenPGP certificate
```

This signature is calculated over the primary key and User ID.


(direct_key_signature)=
### Direct key signature: Adding metadata to the primary key

```{admonition} TODO
:class: warning

explain metadata associated with this signature, and that c-r prefers this over primary user id.
```

### Revocations: Invalidating components of a certificate

```{admonition} TODO
:class: warning

This section only contains notes and still needs to be written
```

Note: certification signatures [can be made irrevocable](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-revocable).

#### Hard vs. soft revocations

A revocation signature may contain a subpacket indicating the reason for revocation. This subpacket contains a code which specifies why the revocation was issued. This code determines, whether the revocation is hard or soft.

A soft revocation is typically used for graceful or planned revocations. A soft revocation can be reverted by re-validating the certificate, User ID or subkey with a fresh binding signature.
A soft revocation invalidates the target certificate beginning with the revocations creation time.

Contrary, a hard revocation cannot be re-validated. Furthermore, a hard-revoked certificate is invalidated retroactively.

A missing revocation reason subpacket is equivalent with a hard revocation reason.

(third_party_cert)=
## Third-party certifications: Making statements about other people's certificates and identities 

```{admonition} TODO
:class: warning

write
```

## Advanced topics

### Certification Recipes

As mentioned above, different signatures are used for different purposes.
In this section, we will try to give guidance on how to create certain signatures by example.

#### Change Algorithm Preferences

In order to change what symmetric, compression, hash or AEAD algorithms are preferred by the key owner, they can issue a direct-key signature (type 0x1F) on the primary key.
This signature should have the following structure:

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly recommended | The primary key is the issuer |
| Key Flags | Hashed | True | False | Carry over key flags from previous self-signature |
| Features | Hashed | True | False | Carry over features from previous self-signature |
| Key Expiration Time | Hashed | True | False | Carry over expiration time from previous self-signature, if present |
| Hash Alg. Pref. | Hashed | False | False | New preferences |
| Comp. Alg. Pref. | Hashed | False | False | New preferences |
| Symm. Alg. Pref. | Hashed | False | False | New preferences |
| AEAD Alg. Pref. | Hashed | False | False | New preferences |

#### Change Expiration Time

The recommended way to change the expiration time of a certificate is by issuing a new `DirectKey` signature (type 0x1F) with an adjusted Key Expiration Time subpacket.
The structure of such a signature is the same as in the section above.
It is also possible to change the expiration date of individual User IDs (see section below) or separate subkeys (see {numref}`bind_subkey`).

#### Add User ID

A signature that binds a User ID to a certificate should have the following structure:

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
| Primary User ID | Hashed | True | False | Optional |
| Signature Expiration Time | Hashed | True | False | Optional |

Self-certifications over User IDs can optionally carry the same subpackets as listed in the previous table (key flags, features, algorithm preferences).
This way, separate capabilities can be assigned to different identities.

#### Remove / Revoke User ID

Since OpenPGP certificates are often distributed by the means of key servers, new signatures on a certificate are often "merged" into existing copies of the certificate locally by the recipient.
This means, that it is not really possible to remove signatures / User IDs from a certificate, as there is no way to communicate the intention of packet deletion to the recipient.

So to mark a User ID as invalid, the user can publish a copy of their certificate with a `CertificationRevocation` (signature type 0x30) attached to the invalidated User ID.
This signature signals that the holder of the certificate no longer wants to be associated with that User ID.

The structure of a certification revocation is as follows:

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |

For User ID revocations, the value of the reason subpacket can either be `0` (no reason specified) or `32`, signaling that the User ID is no longer valid.
The latter would result in a soft revocation, while a reason code of `0` is considered a hard revocation.
Omitting the reason packet altogether is also equivalent to a hard revocation.
It is recommended to issue User ID certifications using a reason code `32` and to do certificate revocations using a direct-key signature.

(binding_subkeys)=
#### Add a Subkey

For the purpose of key freshness, a user might want to add a new subkey to their certificate.


The structure is as follows:

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
| Key Flags | Hashed | True | Strongly Recommended | Determine the usage of the key |
| Key Expiration Time | Hashed | True | False | Specifies the expiration date of the subkey |
| Embedded Signature | Hashed | True | If Key Flags contains **S** | Signing subkeys require embedded `PrimaryKeyBinding` signature |
| Hash Alg. Pref. | Hashed | False | False | Per key preferences |
| Comp. Alg. Pref. | Hashed | False | False | Per key preferences |
| Symm. Alg. Pref. | Hashed | False | False | Per key preferences |
| AEAD Alg. Pref. | Hashed | False | False | Per key preferences |

Optional algorithm preference subpackets can be used to signal per-subkey preferences that deviate from those set in the certificates `DirectKey` signature.

#### Revoke a Subkey

Analogous to User IDs, subkeys can be revoked individually.
This is done by issuing a `SubkeyRevocation` signature (type 0x28) using the primary key.
The structure of such a signature is rather minimal:

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |

In `SubkeyRevocation` signatures, the reason subpacket cannot have value `32`, but instead may be from the range of `0-3`.
Values `1` (key superseded) and `3` (key retired and no longer used) are soft reasons, while `0` (no reason) and `2` (key compromised) are considered hard.

#### Revoke a Certificate

A user might want to revoke their whole certificate, rendering it unusable.
Depending on the circumstances, they might either want to revoke it softly, e.g. in case of migration to a new certificate, or they want to issue a hard revocation, e.g. in case of secret key material compromise. A soft-revoked certificate can be re-validated at a later point in time, by issuing a new certification, while a hard revocation is typically permanent.

The recommended way to revoke a certificate is by issuing a `KeyRevocation` signature (type 0x20).
The structure of a key revocation signature is similar to that of a `CertificationRevocation` signature.

| Subpacket | Area | Critical | Mandatory | Notes |
|-----------|------|----------|-----------|-------|
| Signature Creation Time | Hashed | True | True | Current time |
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |

For `KeyRevocation` signatures, the same constraints as for `SubkeyRevocation` signatures apply to the reason subpacket.

#### Common Subpackets

There are some subpackets that are expected to be included in any type of signature.

* **Signature Creation Time**: Every OpenPGP signature MUST contain a Signature Creation Time subpacket (2) containing the timestamp at which the signature was made. This packet MUST be present in the hashed area of the signature and SHOULD be marked as critical.

* **Issuer Fingerprint**: To be able to verify a signature, the verifier needs to know which (sub-)key was used to issue the signature in the first place. Therefore, every OpenPGP v6 signature SHOULD contain an Issuer Fingerprint subpacket (33) containing the 32 byte fingerprint of the particular component key that was used to create the signature.

```{note}
The issuer key might be a subkey.
```

Since the issuer fingerprint subpacket is self-authenticating, it can either be included as a hashed or unhashed subpacket, but the authors of this book recommend to place it in the hashed area of the signature.

### Potential subpacket conflicts and duplication

Since the hashed and unhashed areas of a signature are just lists of subpackets, in principle they allow duplicates of the same subpacket, which might lead to conflicts.
Therefore, packets in the hashed area take precedence over the unhashed area.
However, there may still be conflicts between packets in the same area, e.g., two conflicting expiration dates, etc.
The [specification recommends](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-notes-on-subpackets) that implementations favor the last occurrence of a conflicting packet in the hashed area.

In some cases, duplicate packets with conflicting content even make sense, e.g., if a signature was made by a version 4 issuer key whose key material was migrated from an older OpenPGP version such as v3.
In this case, either the v3 or v4 key could be used to validate the v4 signature, but since the key ID calculation scheme was changed between v3 and v4, these identifiers would differ.
Therefore, the signature could contain two isuer key ID subpackets with conflicting, but correct values.

```{admonition} TODO
:class: warning

- Key Flags
- Preferences
- Embedded Signature (back sig)
- Trust Signatures (amount, depth)
- Direct key signatures
```