One central (and non-trivial) element of OpenPGP are "OpenPGP certificates" (also often called "OpenPGP keys"). OpenPGP certificates are relatively complex data structures, so it's good to have a clear mental model of them.
The concept of "(cryptographic) keys" plays a central role, when looking at OpenPGP certificates. Confusingly, the term can be used to refer to a number of subtly different things.
First, without additional context, the word "key" can refer either to public, or to private asymmetric key material (or even to symmetric keys, which can be used to encrypt private key material in OpenPGP keys).
Independent of the distinction between private and public keys, in OpenPGP, the term "key" is used to refer to three different layers, all related but distinct:
1. A (bare) ["cryptographic key"](asymmetric_key_pair) (without additional metadata). Those might be the private and/or public parameters that form a key, e.g., in case of an RSA private key, the exponent `d` along with the prime numbers `p` and `q`.
2. An OpenPGP *component key*: Either an "OpenPGP primary key", or an "OpenPGP subkey". A component key is one building block of an OpenPGP certificate. It consists of a cryptographic keypair combined some invariant metadata (e.g. key creation time).
3. An "OpenPGP certificate" (or "OpenPGP key"): Consists of a number of component keys, identity information and additional elements.
All elements of an OpenPGP certificate are structured around one central element: the *OpenPGP primary key*. The primary key acts as a personal CA for the certificate's owner: It can make cryptographic statements about subkeys, identities, expiration, revocation, ...
OpenPGP certificates are typically long-lived and may be changed (typically by their owner), over time. Components can be added and invalidated, over the lifetime of a certificate
OpenPGP component keys consist of an [asymmetric cryptographic keypair](asymmetric_key_pair) and a creation timestamp. These attributes of a component key cannot be changed after creation (in the case of ECDH keys, two additional parameters are part of a component key's constituting data[^ecdh-paramters]).
[^ecdh-paramters]: For [ECDH](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-part-for-ecd) component keys, two additional algorithm parameters are part of the component key's constituting and immutable properties. Those parameters define a hash function and a symmetric encryption algorithm.
Component key representations that include private key material also contain metadata that specifies the password protection scheme for the private key material.
For each OpenPGP component key, an *OpenPGP fingerprint* can be derived from the combination of the public key material and creation timestamp (and ECDH parameters, if applicable).
[^keyid]: In OpenPGP version 4, the rightmost 64 bit were sometimes used as a shorter identifier, called "Key ID".
E.g., an OpenPGP version 4 certificate with the fingerprint `B3D2 7B09 FBA4 1235 2B41 8972 C8B8 6AC4 2455 4239` might be referred to by the 64 bit Key ID `C8B8 6AC4 2455 4239` or styled as `0xC8B86AC424554239`.
Historically, even shorter 32 bit identifiers have sometimes been used, like this: `2455 4239`, or `0x24554239`. You may still see such identifiers in very old documents about PGP. However, 32 bit identifiers have [been unfit for purpose for a long time](https://evil32.com/). At some point, 32 bit identifiers were called "short Key ID", while 64 bit identifiers were called "long Key ID".
In addition to the primary key, modern OpenPGP certificates usually contain a number of "subkeys" (however, it's not technically necessary for a certificate to contain subkeys).
Subkeys have the same structure as the primary key, but they are used in a different role. Subkeys are cryptographically linked with the primary key (more on this below).
:alt: Three component keys. The primary key is shown at the top. It can be used for certification. Below it, linked with arrows, are two more component keys, used as subkeys. They are marked as "for encryption" and "for signing", respectively.
Each component key has a set of ["Key Flags"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#key-flags) that specify which operations that key can perform.
By convention, only the primary key is allowed to perform "certification" operations. All other operations can be configured on either the primary key or a subkey.
It is considered good practice to have separate component keys for each type of operation: to allow only *Certification* operations with the primary key, and to use separate *Signing*, *Encryption* and *Authentication* subkeys (independently: with most algorithms, encryption can't be shared with the other capabilities[^key-flag-sharing]).
[^key-flag-sharing]: With ECC algorithms, it's actually not possible to share encryption functionality with the signing-based functionalities, e.g.: ed25519 used for signing; cv25519 used for encryption.
An OpenPGP certificate can contain any number of [User IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13). Each User ID associates the certificate with an identity.
One User ID in a certificate has the special property of being the [Primary User ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-primary-user-id).
User IDs are associated with preference settings (such as preferred encryption algorithms, more on this below). The preferences associated with the Primary User ID are used by default.
[User attributes](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-attribute-packet-tag-1) are similar to User IDs, but less commonly used.
The OpenPGP standard currently only defines one format to store in User Attributes: an [image](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-the-image-attribute-subpack), "presumably (but not required to be) that of the key owner".
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 claims) 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 (the main part of this linking is done by the primary key of the certificate).
So while anyone can still unilaterally store unrelated subkeys and identity claims in an OpenPGP certificate dataset, OpenPGP implementations that read this file 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 do add packets to certificates, which are not "bound" by the certificate's owner:
- [Third-party certifications](third_party_cert) are traditionally added to the certificate that they make a statement about (which can in some cases cause problems[^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).
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 [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).
Binding subkeys that have the "signing" key flag is a special case:
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."
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).
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.
Some OpenPGP subsystems may add User IDs to a certificate, which are not bound to the primary key by the certificate's owner. This can be useful to store local identity information (e.g., Sequoia's public store attaches "pet-names" to certificates, in this way).
Now that we've established the concepts of the components that OpenPGP certificates consist of, let's look at the internal details of our example certificate.
- The [*"Secret-Key Packet"*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-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) (a self-signature that binds metadata to the primary key).
In the real world, you won't usually encounter an OpenPGP key that is quite this minimal. However, this is technically a valid OpenPGP key (and we'll add more components to it, later in this section).
We'll now decode this OpenPGP data, and inspect the two packets in detail.
To generate the output, we run the Sequoia-PGP tool `sq`, using the `packet dump` subcommand. The output of `sq` is one block of text, but we'll break the output up into sections here, to discuss the content of each packet:
The output starts with the (primary) [Secret-Key Packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-key-packet-formats) (the file `alice.priv-0--SecretKey` contains this packet):
The Secret-Key Packet consists in large part of the actual cryptographic key data. Let's look at the packet field by field:
-`CTB: 0xc5`[^CTB]: The [Packet Tag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-headers) for this packet. The binary representation of this value is `11000101`. 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 Tag's value: "5". This is the value for a Secret-Key Packet, as shown in the list of [Packet Tags](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-tags).
-`length: 0x4b`: The remaining length of this packet.
The packet tag defines the semantics of the remaining data in the packet. We're looking at a Secret-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 follows 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`: "The time that the key was created" (also see [Time Fields](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-time-fields))
-`pk_algo: 0x1b`: "The public-key algorithm of this key" (decimal value 27, see the list of [Public-Key Algorithms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-algorithms))
-`public_len: 0x00000020`: "Octet count for the following public key material"
-`ed25519_public`: [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`)
This concludes the Public Key section of the packet. The remaining data follows the [Secret-Key Packet Format](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-key-packet-formats):
-`s2k_usage: 0x00`: Specified that the secret-key data is not encrypted
-`ed25519_secret`: [Algorithm-specific representation](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-part-for-ed2) of the secret key data (the format is based on the value of `pk_algo`)
[^CTB]: Sequoia uses the term "CTB" (Cipher Type Byte) to refer to the RFC's ["Packet Tag"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-headers)
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 "Secret-Key" Packet contains both the private and the public part of the key.
#### Direct Key Signature
The next packet is a [*"Direct Key Signature"*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-direct-key), which is bound to the primary key (the file `alice.priv-1--Signature` contains this packet).
This packet "binds the information in the Signature subpackets to the key". Each entry under "Signature Packet -> Hashed area" is one Signature subpacket, for example, including information about algorithm preferences (*"Symmetric algo preferences"* and *"Hash preferences"*).
-`CTB: 0xc2`: The Packet Tag 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 Tag’s value: “2”. This is the value for a Signature Packet.
-`length: 0xb6`: The remaining length of this packet.
The packet tag 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 (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 (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 tag, 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 tag). Note that bit 7 of the subpacket tag 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)
-`digest_prefix: 0x6747`: "The left 16 bits of the signed hash value"
-`salt_len, salt`: A random value with [matching size](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#hash-algorithms-registry) for the hash algorithm
-`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
The public certificate uses the packet type "Public-Key Packet" instead of "Secret-Key Packet." The two packet types are very similar. The "Public-Key Packet" leaves out two types of data
In the following examples, we will look at OpenPGP private keys only. The corresponding public certificates are easy to imagine (just leave out the private key material).
From here on, we'll look at the dumps in shorter format (you can see more detail by copying the certificates into the ["Sequoia OpenPGP Packet dumper"](https://dump.sequoia-pgp.org/) and checking the "HexDump" checkbox).
To look into these, we'll make a certificate that has one [User ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#uid). User IDs are *"intended to represent the name and email address of the key holder"*. A certificate can have multiple User IDs associated with it.
* Third, a [*"User ID Packet"*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#uid), which contains the name and email address we used
* Finally, a [*"Positive Certification Signature"*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-positive-cert) (type 0x13), *"Positive certification of a User ID and Public-Key packet"*. This is a cryptographic artifact that "binds the User ID packet and the Key packet together", i.e. it certifies that the owner of the key wants this User ID associated with their key. (Only the person who controls the private part of this key can create this signature packet. The signature serves as proof that the owner of the key has added this User ID to the certificate)