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

(zoom_certificates)=
# Zooming in: Packet structure of certificates and keys

Now that we've established the concepts and  components that make up OpenPGP certificates , let's look at the internal details of an example certificate.

## A very minimal OpenPGP certificate

In this section, we will examine a very minimal version of a "public key" variant of [Alice's OpenPGP key](alice_priv), specifically an OpenPGP certificate that excludes private key material.

To achieve this, we will use the Sequoia-PGP tool `sq` to handle and transform our example OpenPGP key, as well as to inspect internal OpenPGP packet data.

Starting from [Alice's OpenPGP private key](alice_priv), we first produce the corresponding public key/certificate using the following command:

```text
$ sq key extract-cert alice.priv > alice.pub
```

(split_alice)=
### Splitting the OpenPGP certificate into packets

To create a very minimal version of Alice's certificate, we will split the data in `alice.pub` into its component packets and reassemble only the relevant ones back into a new variant.

Execute the following command to achieve this:

```text
$ sq packet split alice.pub
```

With this command, `sq` generates a set of files, each containing an individual OpenPGP packet extracted from the original full certificate in `alice.pub`:

```text
alice.pub-0--PublicKey
alice.pub-1--Signature
alice.pub-2--UserID
alice.pub-3--Signature
alice.pub-4--PublicSubkey
alice.pub-5--Signature
alice.pub-6--PublicSubkey
alice.pub-7--Signature
alice.pub-8--PublicSubkey
alice.pub-9--Signature
```


```{figure} diag/certificate_packet_list.png

Overview of the packets in Alice's OpenPGP certificate 
```

This process allows us to focus on the specific packets within Alice's OpenPGP certificate.

### Assembling packets into an OpenPGP certificate

In this step, we'll merge the first two packets of Alice's certificate to create a very minimal certificate:

Execute the following:

```text
$ sq packet join alice.pub-0--PublicKey alice.pub-1--Signature --output alice_minimal.pub
```

This command combines the contents of `alice.pub-0--PublicKey` and `alice.pub-1--Signature` into a single file named `alice_minimal.pub`.

### Inspecting this certificate

This version of Alice's certificate contains just two packets:

- the [*Public-Key packet*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-packet-formats) for the primary key, and
- a [*Direct Key Signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-direct-key), which is a self-signature that binds metadata to the primary key.

This is the shape of the packets we'll explore in the subsequent sections:

```{figure} diag/pubcert-minimal.png
:width: 40%

A minimal OpenPGP certificate, visualized
```

```{admonition} VISUAL
:class: warning

This diagram needs adjustments about
 - what exactly is signed
 - fix naming of fields?
 
We could show repeat-copies of the individual packet visualization again, below for each packet-related section.
```

In real-world scenarios, OpenPGP certificates are typically far more complex than this minimal example. However, this is indeed a valid OpenPGP certificate. In the following sections, we will introduce more components to this certificate, increasing its complexity and exploring their details.

In ASCII-armored representation, this very minimal key appears as follows:

```text
-----BEGIN PGP PUBLIC KEY BLOCK-----

xioGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT7CtgYf
GwoAAAA9BYJlFuqmBYkFpI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj
/Te2fzMA+fsOxFc3jNKfECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4
gAIl6FM5SWuQxg12j0S07ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L
+BXIoY2sIEQrLd4TAEEy0BA8aQZTPEmMdiOCM1QB+V+BQZAO
=5nyq
-----END PGP PUBLIC KEY BLOCK-----
```

The output of `sq` is presented as a block of text. We will now decode this OpenPGP data and inspect the two packets it contains.

To achieve this, we will use the Sequoia-PGP tool `sq` and run the `packet dump` subcommand:

```text
$ sq packet dump --hex alice_minimal.pub
```

This will allow us to gain a detailed understanding of the packet contents.

(public_key)=
### Public-Key packet

The output begins with a (primary) [Public-Key packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-packet-formats):

```text
Public-Key Packet, new CTB, 2 header bytes + 42 bytes
    Version: 6
    Creation time: 2023-09-29 15:17:58 UTC
    Pk algo: Ed25519
    Pk size: 256 bits
    Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    KeyID: AAA18CBB254685C5

    00000000  c6                                                 CTB
    00000001     2a                                              length
    00000002        06                                           version
    00000003           65 16 ea a6                               creation_time
    00000007                       1b                            pk_algo
    00000008                           00 00 00 20               public_len
    0000000c                                       53 24 e9 43   ed25519_public
    00000010  af ab 15 f7 6e d5 b5 12  98 79 69 cd 1b 5d 10 65
    00000020  eb e7 42 e2 ab 47 f4 86  b3 ae 65 3e
```

The Public-Key packet consists primarily of the cryptographic key data. Let's look at the packet field by field:

- `CTB: 0xc6`[^CTB]: This is the [packet type ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-headers) for this packet. The binary representation of the value `0xc6` is `11000110`. The first two bits show that the packet is in *OpenPGP packet format* (as opposed to in *Legacy packet format*) and the remaining 6 bits encode the type ID value, which is "6." This type ID value corresponds to a Public-Key packet, as listed in the [packet type IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-tags).

- `length: 0x2a`: This indicates the remaining length of this packet. The packet type ID defines the semantics of the remaining data within the packet. In this case, it is a Public-Key packet, which is a kind of [Key Material Packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-key-material-packets).

- `version: 0x06`: The key material is in version 6 format. This means that the next part of the packet adheres to the structure of [Version 6 Public Keys](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-version-6-public-keys).

- `creation_time: 0x6516eaa6`: This field represents the key's creation time. (See also [Time Fields](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-time-fields)).

- `pk_algo: 0x1b`: This corresponds to the key's public-key algorithm ID, which has a decimal value of 27. Refer to the list of [Public-Key Algorithms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms)) for more details.

- `public_len: 0x00000020`: This section specifies the octet count for the subsequent public key material. In this case, it represents the length of the following `ed25519_public` field.

- `ed25519_public`: This is the [algorithm-specific representation](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-part-for-ed2) of the public key material. The format is based on the value of `pk_algo`, which, in this case, is 32 bytes of Ed25519 public key data.

[^CTB]: Sequoia uses the term CTB (Cipher Type Byte) to refer to the RFC's [packet type ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-headers). In earlier RFC versions, this field was known as the "Packet Tag."

```{tip}

The overall structure of OpenPGP packets is described in the [Packet Syntax](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-syntax) chapter of the RFC.
```

Note that the *Public-Key packet* contains only the public part of the key.

(zooming_in_dks)=
### Direct Key Signature

The next packet in the certificate is a [*Direct Key Signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-direct-key), which plays a crucial role in binding specific information to the primary key. This signature is contained within the file `alice.pub-1--Signature`.

This packet binds the information within the signature subpackets with the primary key. Each entry under "Signature Packet -> Hashed area" is one signature subpacket, for example, including information about algorithm preferences (*symmetric algorithm preference* and *hash algorithm preferences*).

```text
Signature Packet, new CTB, 2 header bytes + 182 bytes
    Version: 6
    Type: DirectKey
    Pk algo: Ed25519
    Hash algo: SHA512
    Hashed area:
      Signature creation time: 2023-09-29 15:17:58 UTC (critical)
      Key expiration time: P1095DT62781S (critical)
      Symmetric algo preferences: AES256, AES128
      Hash preferences: SHA512, SHA256
      Key flags: C (critical)
      Features: MDC
      Issuer Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    Unhashed area:
      Issuer: AAA18CBB254685C5
    Digest prefix: 6747
    Level: 0 (signature over data)

    00000000  c2                                                 CTB
    00000001     b6                                              length
    00000002        06                                           version
    00000003           1f                                        type
    00000004              1b                                     pk_algo
    00000005                 0a                                  hash_algo
    00000006                    00 00  00 3d                     hashed_area_len
    0000000a                                 05                  subpacket length
    0000000b                                    82               subpacket tag
    0000000c                                       65 16 ea a6   sig creation time
    00000010  05                                                 subpacket length
    00000011     89                                              subpacket tag
    00000012        05 a4 8f bd                                  key expiry time
    00000016                    03                               subpacket length
    00000017                       0b                            subpacket tag
    00000018                           09 07                     pref sym algos
    0000001a                                 03                  subpacket length
    0000001b                                    15               subpacket tag
    0000001c                                       0a 08         pref hash algos
    0000001e                                             02      subpacket length
    0000001f                                                9b   subpacket tag
    00000020  01                                                 key flags
    00000021     02                                              subpacket length
    00000022        1e                                           subpacket tag
    00000023           01                                        features
    00000024              22                                     subpacket length
    00000025                 21                                  subpacket tag
    00000026                    06                               version
    00000027                       aa  a1 8c bb 25 46 85 c5 83   issuer fp
    00000030  58 32 05 63 fd 37 b6 7f  33 00 f9 fb 0e c4 57 37
    00000040  8c d2 9f 10 26 98 b3
    00000047                       00  00 00 0a                  unhashed_area_len
    0000004b                                    09               subpacket length
    0000004c                                       10            subpacket tag
    0000004d                                          aa a1 8c   issuer
    00000050  bb 25 46 85 c5
    00000055                 67                                  digest_prefix1
    00000056                    47                               digest_prefix2
    00000057                       20                            salt_len
    00000058                           a2 e3 63 81 e3 6b d0 4f   salt
    00000060  56 d7 c8 38 80 02 25 e8  53 39 49 6b 90 c6 0d 76
    00000070  8f 44 b4 ec 4c 42 38 8e
    00000078                           4d 3d 10 c2 ad 29 c0 57   ed25519_sig
    00000080  ce 66 01 73 b3 78 81 9e  89 52 cf 43 8d 28 11 a9
    00000090  77 09 7f cb f8 15 c8 a1  8d ac 20 44 2b 2d de 13
    000000a0  00 41 32 d0 10 3c 69 06  53 3c 49 8c 76 23 82 33
    000000b0  54 01 f9 5f 81 41 90 0e
```

Let’s look at the packet field by field:

- `CTB: 0xc2`: The Packet type ID for this packet. Bits 7 and 6 show that the packet is in “OpenPGP packet format” (as opposed to in “Legacy packet format”). The remaining 6 bits encode the type ID’s value: “2.” This is the value for a Signature packet.
- `length: 0xb6`: The remaining length of this packet.

The packet type ID defines the semantics of the remaining data in the packet. We're looking at a [Signature packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#signature-packet), so the following data is interpreted accordingly.

- `version: 0x06`: This is a version 6 signature (some of the following packet format is specific to this signature version).
- `type: 0x1f`: The [Signature Type](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-types)
- `pk_algo: 0x1b`: Public-key algorithm ID (decimal 27, corresponds to [Ed25519](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms))
- `hash_algo: 0x0a`: Hash algorithm ID (decimal 10, corresponds to [SHA2-512](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-hash-algorithms))
- `hashed_area_len: 0x0000003d`: Length of the following hashed subpacket data

The next part of this packet contains hashed subpacket data. A subpacket data set in an OpenPGP Signature contains a list of zero or more Signature subpackets.

There are two sets of subpacket data in a Signature: hashed, and unhashed. The difference is that the hashed subpackets are protected by the digital signature of this packet, while the unhashed subpackets are not.

The following subpacket data consists of sets of "subpacket length, subpacket type ID, data." We'll show the information for each subpacket as one line, starting with the [subpacket type description](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-subpacket-specifi) (based on the subpacket type ID). Note that bit 7 of the subpacket type ID signals if that subpacket is ["critical"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#section-5.2.3.7-10).

```{note}
Critical here means: the receiver must be able to interpret the subpacket and is expected to fail, otherwise. Non-critical subpackets may be ignored by the receiver.
```

- [Signature creation time](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#signature-creation-subpacket) (subpacket type 2, **critical**): `0x6516eaa6` (also see [Time Fields](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-time-fields))
- [Key expiration time](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#key-expiration-subpacket) (subpacket type 9, **critical**): `0x05a48fbd` (defined as number of seconds after the key creation time)
- [Preferred symmetric ciphers for v1 SEIPD](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#preferred-v1-seipd) (type 11): `0x09 0x07`. (These values [correspond to](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#symmetric-algos): *AES with 256-bit key* and *AES with 128-bit key*)
- [Preferred hash algorithms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#preferred-hashes-subpacket) (subpacket type 21): `0x0a 0x08`. (These values [correspond to](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-hash-algorithms): *SHA2-512* and *SHA2-256*)
- [Key flags](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#key-flags) (subpacket type 27, **critical**): `0x01`. (This value [corresponds](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-key-flags) to the *certifications* key flag)
- [Features](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#features-subpacket) (subpacket type 30): `0x01`. (This value [corresponds](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-features) to: *Symmetrically Encrypted Integrity Protected Data packet version 1*)
- [Issuer fingerprint](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#issuer-fingerprint-subpacket) (subpacket type 33): `aaa18cbb254685c58358320563fd37b67f3300f9fb0ec457378cd29f102698b3` (this is the fingerprint of the component key that issued the signature in this packet. Not that here, the value is the primary key fingerprint of the certificate we're looking at.)

The next part of this packet contains "unhashed subpacket data":

- `unhashed_area_len: 0x0000000a`: Length of the following unhashed subpacket data (value: 10 bytes).

As above, the following subpacket data consists of sets of "subpacket length, subpacket type id, data." In this case, only subpacket follows:

- [Issuer Key ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#issuer-keyid-subpacket) (subpacket type 16): `aaa18cbb254685c5` (this is the shortened version 6 *Key ID* of the fingerprint of this certificate's primary key)

This concludes the unhashed subpacket data.

- `digest_prefix: 0x6747`: "The left 16 bits of the signed hash value"
- `salt_len, salt`: A random [salt value](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-advantages-of-salted-signat) (the size must be [matching for the hash algorithm](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#hash-algorithms-registry))
- `ed25519_sig`: [Algorithm-specific](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-fields-for-ed2) representation of the signature (in this case: 64 bytes of Ed25519 signature)

The signature is calculated over a hash. The hash, in this case, is calculated over the following data (for details, see [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC):

- The signature's salt
- A serialized form of the primary key's public data
- A serialized form of this direct key signature packet (up to, but excluding the unhashed area)


(zoom_enc_subkey)=
## Encryption subkey

Now we'll look at a subkey in Alice's certificate. An OpenPGP subkey, when it is linked to an OpenPGP certificate (via its primary key), consists of two elements:

- a key packet that contains the component key itself, and
- a signature packet that links this component key to the primary key (and thus implicitly to the full OpenPGP certificate).

In this section, we'll use the files that contain individual packets of Alice's certificate, which we split apart above. In this split representation of Alice's certificate, the encryption subkey happens to be stored in `alice.pub-4--PublicSubkey`, and the associated binding self-signature for the subkey in `alice.pub-5--Signature`.

````{note}
It's common to look at a packet dump for a full OpenPGP certificate, like this:

```text
$ sq packet dump --hex alice.pub
```

That command shows the details for the full series of packets in an OpenPGP certificate (recall the list of [packets of Alice's certificate](split_alice)). Finding a particular packet in that list can take a bit of focus and practice though.

In the following sections we're making it a bit easier for ourselves, and directly look at individual packets, from the files we created with `sq packet split`, above.
````

### Public-Subkey packet

First, we'll look at the *Public-Subkey packet* that contains the component key data of this subkey:

```text
$ sq packet dump --hex alice.pub-4--PublicSubkey
Public-Subkey Packet, new CTB, 2 header bytes + 42 bytes
    Version: 6
    Creation time: 2023-09-29 15:17:58 UTC
    Pk algo: X25519
    Pk size: 256 bits
    Fingerprint: C0A58384A438E5A14F73712426A4D45DBAEEF4A39E6B30B09D5513F978ACCA94
    KeyID: C0A58384A438E5A1

  00000000  ce                                                 CTB
  00000001     2a                                              length
  00000002        06                                           version
  00000003           65 16 ea a6                               creation_time
  00000007                       19                            pk_algo
  00000008                           00 00 00 20               public_len
  0000000c                                       d1 ae 87 d7   x25519_public
  00000010  cc 42 af 99 34 c5 c2 5c  ca fa b7 4a c8 43 fc 86
  00000020  35 2a 46 01 f3 cc 00 f5  4a 09 3e 3f
```

Notice that the structure of this *Public-Subkey packet* is the same as the *Public-Key Packet* of the primary key, [above](public_key). Only the content of the two packets differs in some points:

- The packet type ID (`CTB`) in this packet shows type 14 ([*Public-Subkey packet*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-subkey-packet-tag-14)).
- The `pk_algo` value is set to `0x19` (decimal 25), which [corresponds to](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms) X25519. Note that even though both the primary key and this subkey use a cryptographic mechanism based on Curve25519, this encryption key uses Curve 25519 in a different way (X25519 is a Diffie–Hellman function built out of Curve25519).
- Accordingly, the public part of the cryptographic key pair is labeled with the corresponding name: `x25519_public`  (however, note that this difference only reflects the semantics of the field, which is implied by the value of `pk_algo`. The actual data consists of just 32 bytes of cryptographic key material, without any type information.)

### Subkey binding signature

The subkey packet above by itself is disconnected from the OpenPGP certificate that it is a part of. The link between the subkey and the full OpenPGP key is made with a cryptographic signature, which is issued by the OpenPGP key's primary key.

The type of signature that is used for this is called a *subkey binding signature*, because it "binds" (as in "connects") the subkey to the rest of the key.

```{admonition} VISUAL
:class: warning

Add detailed packet diagram analogous to 4.6.1
```

```{admonition} TODO
:class: warning

david points out: "The information on metadata in binding signatures may also make sense in other contexts (direct key signature)?"

Should this text go elsewhere?
- 4.2.3?
- ch 6?
```
In addition to its core purpose of making the connection, this signature also contains additional metadata about the subkey. One reason why this metadata is in a binding signature (and not in the subkey packet) is that it may change over time. The subkey packet itself may not change over time. So metadata about the subkey that can change is stored in self-signatures: if the key holder wants to change some metadata (for example, the key's expiration time), they can issue a newer version of the same kind of signature. Receiving OpenPGP software will then understand that the newer self-signature supersedes the older signature, and that the metadata in the newer signature reflects the most current intent of the key holder.

Note that this subkey binding signature packet is quite similar to the Direct Key Signature we discussed packet above. Both signatures perform the same function in terms of adding metadata to a component key. In particular, the hashed subpacket data contains many of the same pieces of metadata.

```text
$ sq packet dump --hex alice.pub-5--Signature
Signature Packet, new CTB, 2 header bytes + 171 bytes
    Version: 6
    Type: SubkeyBinding
    Pk algo: Ed25519
    Hash algo: SHA512
    Hashed area:
      Signature creation time: 2023-09-29 15:17:58 UTC (critical)
      Key expiration time: P1095DT62781S (critical)
      Key flags: EtEr (critical)
      Issuer Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    Unhashed area:
      Issuer: AAA18CBB254685C5
    Digest prefix: 2289
    Level: 0 (signature over data)

    00000000  c2                                                 CTB
    00000001     ab                                              length
    00000002        06                                           version
    00000003           18                                        type
    00000004              1b                                     pk_algo
    00000005                 0a                                  hash_algo
    00000006                    00 00  00 32                     hashed_area_len
    0000000a                                 05                  subpacket length
    0000000b                                    82               subpacket tag
    0000000c                                       65 16 ea a6   sig creation time
    00000010  05                                                 subpacket length
    00000011     89                                              subpacket tag
    00000012        05 a4 8f bd                                  key expiry time
    00000016                    02                               subpacket length
    00000017                       9b                            subpacket tag
    00000018                           0c                        key flags
    00000019                              22                     subpacket length
    0000001a                                 21                  subpacket tag
    0000001b                                    06               version
    0000001c                                       aa a1 8c bb   issuer fp
    00000020  25 46 85 c5 83 58 32 05  63 fd 37 b6 7f 33 00 f9
    00000030  fb 0e c4 57 37 8c d2 9f  10 26 98 b3
    0000003c                                       00 00 00 0a   unhashed_area_len
    00000040  09                                                 subpacket length
    00000041     10                                              subpacket tag
    00000042        aa a1 8c bb 25 46  85 c5                     issuer
    0000004a                                 22                  digest_prefix1
    0000004b                                    89               digest_prefix2
    0000004c                                       20            salt_len
    0000004d                                          0b 0c 89   salt
    00000050  b5 ab 15 e3 7f e4 4d b9  a7 ef 71 48 14 3b ab 26
    00000060  5f 34 7f 6d 48 2e 9f 78  48 58 6d 9a fb
    0000006d                                          6d b2 db   ed25519_sig
    00000070  2f 97 8e c8 12 fc 57 7f  85 aa d1 59 bc 80 40 0b
    00000080  be 2e f0 e1 23 2d bf 4b  71 7e d0 e4 c0 36 e4 d2
    00000090  cf b2 9f b4 a8 4f 3e 2a  21 89 74 c2 33 55 af ac
    000000a0  41 36 1b 2b 60 09 f2 d9  19 f4 41 12 0b
```

We'll go over this packet dump in less detail, since its structure mirrors the *Direct Key Signature* (described above) very closely.

The first difference is in the `type` field, showing that this signature is of type `0x18` ([Subkey Binding Signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-subkey-binding-signature-si)).

The `pk_algo` of this signature is informed by the algorithm of the primary key (`0x1b`, corresponding to Ed25519). The signature in this packet is issued by the primary key, so by definition it uses the signing algorithm of the primary key (that is: the algorithm used to produce the cryptographic signature in this packet is entire independent of the `pk_algo` of the key material of this subkey itself, which uses the X25519 mechanism).

As shown in the text at the top of this packet dump, the hashed subpacket data contains four pieces of information:

- Signature creation time: `2023-09-29 15:17:58 UTC` (**critical**)
- Key expiration time: `P1095DT62781S` (**critical**)
- Key flags: `EtEr` (**critical**) (encryption for communication, encryption for storage)
- Issuer Fingerprint: `AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3`

The remainder of the packet has the same content as the *Direct Key Signature* above:
- A 16 bit digest prefix
- A salt value
- The cryptographic signature itself

The signature is calculated over a hash. The hash, in this case, is calculated over the following data (for details, see [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC):

- The signature's salt
- A serialized form of the primary key's public data
- A serialized form of the subkey's public data
- A serialized form of this subkey binding signature packet (up to, but excluding the unhashed area)

## Signing subkey

```{admonition} TODO
:class: warning

write 
```

```text
$ sq packet dump --hex alice.pub-6--PublicSubkey
Public-Subkey Packet, new CTB, 2 header bytes + 42 bytes
    Version: 6
    Creation time: 2023-09-29 15:17:58 UTC
    Pk algo: Ed25519
    Pk size: 256 bits
    Fingerprint: D07B24EC91A14DD240AC2D53E6C8A9E054949A41222EA738576ED19CAEA3DC99
    KeyID: D07B24EC91A14DD2

    00000000  ce                                                 CTB
    00000001     2a                                              length
    00000002        06                                           version
    00000003           65 16 ea a6                               creation_time
    00000007                       1b                            pk_algo
    00000008                           00 00 00 20               public_len
    0000000c                                       33 8c d4 f5   ed25519_public
    00000010  1a 73 39 ef ce d6 0f 21  8d a0 58 a2 3c 3d 44 a8
    00000020  59 e9 13 1f 12 9c 6f 19  d0 3d 40 a0
```

```text
$ sq packet dump --hex alice.pub-7--Signature
Signature Packet, new CTB, 3 header bytes + 325 bytes
    Version: 6
    Type: SubkeyBinding
    Pk algo: Ed25519
    Hash algo: SHA512
    Hashed area:
      Signature creation time: 2023-09-29 15:17:58 UTC (critical)
      Key expiration time: P1095DT62781S (critical)
      Key flags: S (critical)
      Embedded signature:  (critical)
        Signature Packet
          Version: 6
          Type: PrimaryKeyBinding
          Pk algo: Ed25519
          Hash algo: SHA512
          Hashed area:
            Signature creation time: 2023-09-29 15:17:58 UTC (critical)
            Issuer Fingerprint: D07B24EC91A14DD240AC2D53E6C8A9E054949A41222EA738576ED19CAEA3DC99
          Digest prefix: 5365
          Level: 0 (signature over data)

      Issuer Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    Unhashed area:
      Issuer: AAA18CBB254685C5
    Digest prefix: 841C
    Level: 0 (signature over data)

    00000000  c2                                                 CTB
    00000001     c0 85                                           length
    00000003           06                                        version
    00000004              18                                     type
    00000005                 1b                                  pk_algo
    00000006                    0a                               hash_algo
    00000007                       00  00 00 cc                  hashed_area_len
    0000000b                                    05               subpacket length
    0000000c                                       82            subpacket tag
    0000000d                                          65 16 ea   sig creation time
    00000010  a6
    00000011     05                                              subpacket length
    00000012        89                                           subpacket tag
    00000013           05 a4 8f bd                               key expiry time
    00000017                       02                            subpacket length
    00000018                           9b                        subpacket tag
    00000019                              02                     key flags
    0000001a                                 99                  subpacket length
    0000001b                                    a0               subpacket tag
    0000001c                                       06 19 1b 0a   embedded sig
    00000020  00 00 00 29 05 82 65 16  ea a6 22 21 06 d0 7b 24
    00000030  ec 91 a1 4d d2 40 ac 2d  53 e6 c8 a9 e0 54 94 9a
    00000040  41 22 2e a7 38 57 6e d1  9c ae a3 dc 99 00 00 00
    00000050  00 53 65 20 42 03 ad 0c  db fc b5 9a 98 a6 15 27
    00000060  e4 11 5e f5 f2 a0 3d bc  ed 8d 94 27 41 09 f6 3c
    00000070  4b f8 8a e5 af 73 e1 7d  54 07 40 3f f3 29 34 c2
    00000080  e7 60 56 a5 e1 43 cb 08  ba 66 fe 8b 26 ce e7 cb
    00000090  a5 3a 46 bb a5 c8 5d e4  6a de ae 49 e1 3e 07 bf
    000000a0  c4 9e 98 14 2f 3e c5 f7  01 3e 3e 4f f6 18 2a ac
    000000b0  bd ed 52 0c
    000000b4              22                                     subpacket length
    000000b5                 21                                  subpacket tag
    000000b6                    06                               version
    000000b7                       aa  a1 8c bb 25 46 85 c5 83   issuer fp
    000000c0  58 32 05 63 fd 37 b6 7f  33 00 f9 fb 0e c4 57 37
    000000d0  8c d2 9f 10 26 98 b3
    000000d7                       00  00 00 0a                  unhashed_area_len
    000000db                                    09               subpacket length
    000000dc                                       10            subpacket tag
    000000dd                                          aa a1 8c   issuer
    000000e0  bb 25 46 85 c5
    000000e5                 84                                  digest_prefix1
    000000e6                    1c                               digest_prefix2
    000000e7                       20                            salt_len
    000000e8                           23 3d b2 49 f3 02 4b 08   salt
    000000f0  93 af ba 08 89 f0 e0 91  0f ab 22 26 aa b3 56 57
    00000100  30 ea 95 29 06 60 6f 00
    00000108                           be 44 a1 95 38 a9 6b 3a   ed25519_sig
    00000110  3e 51 f0 55 09 b1 e2 91  a9 17 86 fa f5 1e 3f d0
    00000120  28 46 3c ce 6e 88 14 37  32 ec 3d fa c6 01 ca e5
    00000130  a9 4b b7 63 94 c3 0d 92  ab dc fa 23 50 71 60 31
    00000140  a6 73 c8 33 5a 9c d9 0a
```

(zooming_in_user_id)=
## Adding an identity component

Now we'll look at an identity that is associated with Alice's certificate.

User IDs are a mechanism for connecting [identities](identity_components) with an OpenPGP certificate. Traditionally, User IDs contain a string that combines a name and an email address.

Like [above](zoom_enc_subkey), to look at the internal packet structure of this identity and its connection the OpenPGP certificate, we'll inspect the two individual packets that constitute the identity component, the [User ID packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13), in the file `alice.pub-2--UserID`, and the certifying self-signature a [Positive certification of a User ID and Public-Key packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-positive-certification-of-a) in `alice.pub-3--Signature` (these packets are an excerpt of Alice's full OpenPGP private key).

### User ID packet

First, let's look at the User ID packet, which encodes an identity that Alice has connected to her OpenPGP certificate:

```text
$ sq packet dump --hex alice.pub-2--UserID
User ID Packet, new CTB, 2 header bytes + 19 bytes
    Value: <alice@example.org>

    00000000  cd                                                 CTB
    00000001     13                                              length
    00000002        3c 61 6c 69 63 65  40 65 78 61 6d 70 6c 65   value
    00000010  2e 6f 72 67 3e
```

- `CTB: 0xcd`: The Packet type ID for this packet. Bits 7 and 6 show that the packet is in “OpenPGP packet format” (as opposed to in “Legacy packet format”). The remaining 6 bits encode the type ID’s value: “13.” This is the value for a [User ID packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13).
- `length: 0x13`: The remaining length of this packet (here: 19 bytes).
- `value`: 19 bytes of data that contain UTF-8 encoded text. The value corresponds to the string `<alice@example.org>`. With this identity component, Alice states that she uses (and has control of) this email address. Note that the email address is enclosed in `<` and `>` characters, following [RFC 2822](https://www.rfc-editor.org/rfc/rfc2822) conventions.

So, a User ID packet is really just a string, marked as a User ID by the packet type id.

### Linking the User ID with a certification self-signature

As above, when [linking a subkey](zoom_enc_subkey) to the OpenPGP certificate, a self-signature is used to connect this new component to the certificate.

To bind identities to a certificate with a self-signature, one of the signature types `0x10` - `0x13` can be used. Here, the signature type `0x13` (*positive certification*) is used.

```text
$ sq packet dump --hex alice.pub-3--Signature
Signature Packet, new CTB, 2 header bytes + 185 bytes
    Version: 6
    Type: PositiveCertification
    Pk algo: Ed25519
    Hash algo: SHA512
    Hashed area:
      Signature creation time: 2023-09-29 15:17:58 UTC (critical)
      Key expiration time: P1095DT62781S (critical)
      Symmetric algo preferences: AES256, AES128
      Hash preferences: SHA512, SHA256
      Primary User ID: true (critical)
      Key flags: C (critical)
      Features: MDC
      Issuer Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    Unhashed area:
      Issuer: AAA18CBB254685C5
    Digest prefix: DBB8
    Level: 0 (signature over data)

    00000000  c2                                                 CTB
    00000001     b9                                              length
    00000002        06                                           version
    00000003           13                                        type
    00000004              1b                                     pk_algo
    00000005                 0a                                  hash_algo
    00000006                    00 00  00 40                     hashed_area_len
    0000000a                                 05                  subpacket length
    0000000b                                    82               subpacket tag
    0000000c                                       65 16 ea a6   sig creation time
    00000010  05                                                 subpacket length
    00000011     89                                              subpacket tag
    00000012        05 a4 8f bd                                  key expiry time
    00000016                    03                               subpacket length
    00000017                       0b                            subpacket tag
    00000018                           09 07                     pref sym algos
    0000001a                                 03                  subpacket length
    0000001b                                    15               subpacket tag
    0000001c                                       0a 08         pref hash algos
    0000001e                                             02      subpacket length
    0000001f                                                99   subpacket tag
    00000020  01                                                 primary user id
    00000021     02                                              subpacket length
    00000022        9b                                           subpacket tag
    00000023           01                                        key flags
    00000024              02                                     subpacket length
    00000025                 1e                                  subpacket tag
    00000026                    01                               features
    00000027                       22                            subpacket length
    00000028                           21                        subpacket tag
    00000029                              06                     version
    0000002a                                 aa a1 8c bb 25 46   issuer fp
    00000030  85 c5 83 58 32 05 63 fd  37 b6 7f 33 00 f9 fb 0e
    00000040  c4 57 37 8c d2 9f 10 26  98 b3
    0000004a                                 00 00 00 0a         unhashed_area_len
    0000004e                                             09      subpacket length
    0000004f                                                10   subpacket tag
    00000050  aa a1 8c bb 25 46 85 c5                            issuer
    00000058                           db                        digest_prefix1
    00000059                              b8                     digest_prefix2
    0000005a                                 20                  salt_len
    0000005b                                    8a 2d 6f da 67   salt
    00000060  35 bc 5d 04 77 b4 9d 67  a8 6e c5 d6 88 53 5f e2
    00000070  ef f9 66 08 bf c2 e0 db  c0 56 0d
    0000007b                                    eb d4 2c a5 19   ed25519_sig
    00000080  01 0f ba 26 d0 82 a2 cf  5c eb 7a a9 72 d9 f3 b2
    00000090  66 07 8b b2 ba 3d b7 89  e4 76 04 6e 35 24 2b 27
    000000a0  29 83 be 91 9c 78 6a cc  b4 d5 69 47 76 2c 29 d6
    000000b0  54 bf 43 19 04 ff 53 98  c0 d5 0b 
```


We'll go over this packet dump in less detail, since its structure closely mirrors the [Direct Key Signature](zooming_in_dks) discussed above.

We're again looking at a Signature packet. Its `type` is `0x13` ([corresponding](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-types) to a *positive certification* signature).

The public key algorithm and hash function used for this signature are Ed25519 and SHA512.

As shown in the text at the top of this packet dump, the hashed subpacket data contains the following metadata:

- Signature creation time: `2023-09-29 15:17:58 UTC` (**critical**)
- Key expiration time: `P1095DT62781S` (**critical**)
- Symmetric algo preferences: `AES256, AES128`
- Hash preferences: `SHA512, SHA256`
- Primary User ID: `true` (**critical**)
- Key flags: `C` (**critical**)
- Features: `MDC`
- Issuer Fingerprint: `AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3`

This is a combination of metadata about the User ID itself (including defining this User ID as the *primary User ID* of this certificate), algorithm preferences that are associated with this identity, and settings that apply to the primary key.

````{note}
For historical reasons, the self-signature that binds the primary User ID to the certificate also contains subpackets that apply not to the User ID, but to the primary key itself.

Setting key expiration time and key flags on the primary User ID self-signature is one mechanism to configure the primary key.

The interaction between metadata on direct key signatures and User ID binding self-signatures [is subtle](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-notes-on-self-signatures), and there are changes between version 6 and version 4.


```{admonition} TODO
:class: warning

- link to a section that goes into more depth about "#name-notes-on-self-signatures"?
```

````

Followed, again, by the (informational) unhashed subpacket area.

And finally, a salt value for the signature and the signature itself.

The signature is calculated over a hash. The hash, in this case, is calculated over the following data (for details, see [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC):

- The signature's salt
- A serialized form of the primary key's public data
- A serialized form of the User ID
- A serialized form of this self-signature packet (up to, but excluding the unhashed area)

## Certifications (Third Party Signatures)

## Revocations
