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.
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.
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.
With this command, `sq` generates a set of files, each containing an individual OpenPGP packet extracted from the original full certificate in `alice.pub`:
- 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.
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.
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):
The first fields of a packet are governed by the general [Packet Syntax](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-syntax):
-`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.
**Public-Key packet syntax**
The packet type ID ("6") defines the semantics of the following 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 field 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."
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 data within the signature subpackets with the primary key. Each entry under "Signature Packet -> Hashed area" is one signature subpacket, providing essential information such as algorithm preferences, including *symmetric algorithm preference* and *hash algorithm preferences*.
The first fields of a packet are governed by the general [Packet Syntax](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-syntax):
-`CTB: 0xc2`: This field indicates the Packet type ID for this packet. Bits 7 and 6 show that the packet is in “OpenPGP packet format.” The remaining 6 bits encode the type ID’s value, which is “2” for a Signature packet.
The packet type ID (“2”) defines the semantics of the remaining data in the packet. In this case, as it indicates a [Signature packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#signature-packet), the following data is specific to this packet type.
-`pk_algo: 0x1b`: This specifies the Public-Key algorithm ID, with decimal 27 corresponding to [Ed25519](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms)).
-`hash_algo: 0x0a`: This specifies the hash algorithm ID, with decimal 10 corresponding to [SHA2-512](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-hash-algorithms)).
In OpenPGP Signatures, there are two sets of subpacket data: hashed and unhashed. Hashed subpackets are protected by the digital signature of the packet, while unhashed subpackets are not.
A subpacket data set in an OpenPGP Signature contains a list of zero or more Signature subpackets.
The following subpacket data consists of sets of "subpacket length, subpacket type ID, data." Each subpacket is displayed 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)
Critical here means that the receiver must interpret the subpacket and is expected to fail, otherwise. Non-critical subpackets may be ignored by the receiver.
- Notes: The fingerprint identifies the component key that issued the signature in this packet. In this instance, the value is the primary key fingerprint of the certificate we're looking at.
This next section shows additional components of the Direct Key Signature packet:
-`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) with size [matching 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 (here: 64 bytes of Ed25519 signature)
Refer to [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC for more details.
Let's now look at a subkey in Alice's OpenPGP certificate. A subkey, when linked to an OpenPGP certificate via its primary key, consists of two elements:
We will use the files containing individual packets of Alice's certificate, which we separated above. In this split representation, the encryption subkey is stored in `alice.pub-4--PublicSubkey`, while the associated binding self-signature is stored in `alice.pub-5--Signature`.
This command shows the details for the full series of packets in an OpenPGP certificate (refer to 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 make it easier for ourselves by directly examining individual packets from the files we created with `sq packet split` above.
Notice that the structure of this *Public-Subkey packet* mirrors the primary key's [*Public-Key packet*](public_key) above. However, there are notable differences between the two packets:
- 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 X25519](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms). Notably, though both the primary key and this subkey use a cryptographic mechanism based on Curve25519, the encryption key uses Curve 25519 in a different way: namely, X25519 is a Diffie–Hellman function constructed from Curve25519.
- Accordingly, the public part of the cryptographic key pair is labeled `x25519_public`, as implied by the value (`0x19`) of `pk_algo`. However, the actual data is just 32 bytes of cryptographic key material, without any type information.
The aforementioned subkey packet is disconnected from the OpenPGP certificate to which it belongs. The link between the subkey and the complete OpenPGP certificate is made with a cryptographic signature, generated by primary key of the OpenPGP certificate.
The signature does more than just bind the subkey; it also carries additional metadata about the subkey. This metadata is in the binding signature, and not in the subkey packet, because it may change over time, while the subkey packet itself remains unchanged. This evolving metadata is stored in self-signatures: if the key holder wants to modify the metadata (for example, to change the key's expiration time), a newer version of the same signature type can be issued. The recipient OpenPGP software will recognize that the newer self-signature supersedes the older one, 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 discussed above. Both signatures serve a similar purpose in adding metadata to a component key, particularly as the hashed subpacket data contains much of the metadata elements.
One notable difference is 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` value of this signature derives from the algorithm of the primary key (`0x1b`, corresponding to Ed25519). This signature is issued by the primary key, thus using the signing algorithm of the primary key. (The algorithm used to produce the cryptographic signature in this packet is entirely independent of the `pk_algo` of the key material of this subkey itself, which uses the X25519 mechanism.)
Refer to [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC for details.
User IDs are a mechanism for connecting [identities](identity_components) with an OpenPGP certificate. Typically, a User ID is a string combining a name and an email address.
To understand the internal packet structure of this identity and its connection to the OpenPGP certificate, we'll examine two packets that constitute the identity component. One is the [User ID packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13), located in the file `alice.pub-2--UserID`, which contains identity information. The other is a certifying self-signature, specifically 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) located in the file `alice.pub-3--Signature`. This certification, issued after substantial verification of the identity claim, validates the association between the User ID and the certificate's public key. These packets are snippets from Alice's full OpenPGP certificate.
-`CTB: 0xcd`: This is the packet type ID for this packet. Bits 7 and 6 show that the packet is in “OpenPGP packet format” (not “Legacy packet format”). The remaining 6 bits encode the type ID’s value: “13,” which 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`: This field shows the remaining length of the packet (here: 19 bytes).
-`value`: This comprises 19 bytes of data that contain UTF-8 encoded text. The value corresponds to the string `<alice@example.org>`. With this identity component, Alice asserts usage and control over the specified email address. Note that the email address is enclosed in `<` and `>` characters, in line with the conventions of [RFC 2822](https://www.rfc-editor.org/rfc/rfc2822).
Essentially, a User ID packet is just a string marked as a User ID by the packet type ID.
To bind identities to a certificate with a self-signature, signature types `0x10` - `0x13` can be used. Here, the signature type `0x13` (*positive certification*) is used.
We're again looking at a Signature packet. Its `type` is `0x13` ([corresponding to a *positive certification* signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-types)).
This is a combination of metadata about the User ID itself (designating this User ID as the *primary User ID* of this certificate), algorithm preferences for this identity, and settings that apply to the primary key.
Historically, the self-signature that binds the primary User ID to the certificate also contains subpackets relevant not to the User ID, but to the primary key itself.
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), with changes between version 6 and version 4.
Refer to [Computing Signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-computing-signatures) in the RFC for details.