openpgp-notes/book/source/04-certificates.md
2023-10-03 19:14:39 +02:00

38 KiB

(certificates_chapter)=

Certificates

One central (and non-trivial) element of OpenPGP are 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.

Terminology: The various meanings of "key"

Private vs. public keys

First, without additional context, the word "key" can refer either to public, or to private key material.

Layers of "keys," in OpenPGP

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" (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 (bare) 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 plus additional elements, such as identity information. (e.g., OpenPGP "key servers" serve this type of object).

In the following section, we'll look at the two OpenPGP-specific layers (2 and 3).

Structure of OpenPGP certificates

An OpenPGP certificate (or "OpenPGP key") is a collection of an arbitrary number of elements. These elements are:

  • component keys,
  • identity information, and
  • other metadata.

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 key's owner: It can make cryptographic statements about subkeys, identities, expiration times, revocation, ...


An OpenPGP certificate
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

An OpenPGP component key (either the "OpenPGP primary key," or an "OpenPGP subkey") consists mainly of an asymmetric cryptographic keypair:

---
---
A cryptographic keypair

Recall that in many contexts, only the public key material is present:

---
---
Only the public part of a cryptographic keypair

Besides a cryptographic keypair, an OpenPGP component key contains additional metadata (including a creation timestamp):

---
---
An OpenPGP component key

For each OpenPGP component key, an OpenPGP fingerprint can be derived from the combination of the public key material and creation timestamp (plus additional algorithm parameters, for ECDH Keys):

---
---
Each OpenPGP component key has a fingerprint

The fingerprint of our example component OpenPGP key is AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3 1.

Primary key

The "OpenPGP primary key" has the same structure as all other component keys. But it serves a central role:

  • Its fingerprint is used as the unique identifier for the full OpenPGP certificate.
  • In addition, it is used for lifecycle operations, such as adding or invalidating subkeys or identities in a certificate.
:class: note

In the RFC, the OpenPGP primary key is also sometimes referred to as "top-level key." Historically, it has sometimes informally been called "master key."

Subkeys

In addition to the primary key, modern OpenPGP certificates usually contain "subkeys" in addition to the primary key.

Subkeys have the same structure as the primary key, but play a subtly different role in the certificate. Subkeys are cryptographically linked with the primary key (more on this below).

:name: Certificate with Subkeys
: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.
:width: 80%
:align: center

OpenPGP certificates can contain any number of subkeys

As before, a component key consists of a cryptographic keypair combined with additional metadata.

Each component key (this includes the primary key, and all subkeys) has a marker that specifies which operations the component key can perform.

Key Flags: defining what operations a component key can perform

Each component key has "Key Flags" that specify which types of operation the key can perform.

The commonly used flags are:

  • Certification
  • Signing
  • Encryption
  • Authentication

Only the primary key can perform "certification" operations. All other operations can be performed by either the primary key or subkeys.

It is considered good practice to have separate component keys for each type of operation (specifically: to allow only Certification operations for the primary key, and to have separate Signing, Encryption and Authentication subkeys).

(Aside: 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.)

Identity components

User IDs

An OpenPGP certificate can contain any number of User IDs. Each user ID associates the certificate with an identity.

Typically, these identities are composed of a name and an email address.

---
---
OpenPGP certificates can contain any number of User IDs

Primary UserID and its implications

User attributes

User attributes are similar to User IDs, but less commonly used.

Linking the components of an OpenPGP certificate together ("bindings")

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 file2, it's easy to remove some of these packets, or add new ones.

However, as the owner of my certificate, I don't want a third party to add subkeys (or add identity claims) to my certificate, pretending that I put those components there.

To prevent such malicious addition of components, OpenPGP uses cryptographic signatures. These signatures show the cryptographic identity that has linked a component to an OpenPGP certificate (in many cases, the linking is done by the primary key of the certificate in question).

So while anyone can still unilaterally put subkeys and identity claims into a file with my OpenPGP certificate, OpenPGP implementations that read the file are expected to discard components that aren't cryptographically linked to my certificate.

"Binding" subkeys to an OpenPGP certificate

Linking a subkey to an OpenPGP certificate is done with a "Subkey Binding Signature". Such a signature signals that the "primary key wants to be associated with the subkey".

The subkey binding signature also adds metadata.

---
---
Linking an OpenPGP subkey to the primary key with a binding signature
Signature Subpackets
  • (key-) expiration
  • flags
Binding signing subkeys

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 additional "Primary Key Binding Signature" is informally called a "back signature" (because the subkey uses the signature to point "back" to the primary key).

Self-certification of identity claims

OpenPGP certificates often contain identity markers. Typically, in the form of "User ID"s (however, User Attributes are analogous for the purpose of this section).

For example, above, we saw the User ID Alice Adams <alice@example.org> associated with Alice's key 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 signature of the type PositiveCertification is created. The signature is issued using the primary (secret) key.

---
---
Linking a User ID to an OpenPGP certificate

Third party (identity) certifications

Revocations

Note: certification signatures can be made irrevocable.

Hard vs. soft revocations

Advanced topics

Certificate Management / Evolution of a certificate over time

Minimized versions, merging, effective "append only" semantics, ...

Merging

  • How to merge two copies of the same certificate?
  • Canonicalization

How to generate "minimized" certificate?

When are certificates valid?

  • Full certificate: Primary revoked/key expired/binding signature expired,
  • Subkey: Revoked/key expired/binding signature expired
  • User ID: revoked, binding expired, ...

Best Practices regarding Key Freshness

  • Expiry
  • Subkey rotation

Metadata Leak of Social Graph

Adding unbound User IDs to a certificate

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).

Zooming in: Package structure

To use OpenPGP, we need "(OpenPGP) keys."

There is an ongoing effort to establish new terminology around "keys." In particular, to use the term "certificate" instead of "(OpenPGP) public key."

Note: there is also the related, but distinct, concept of cryptographic "keys". OpenPGP certificates/keys contain one or more cryptographic key(s), among many other components.

An OpenPGP certificate/key consists of a number of elements, many of them optional. OpenPGP certificates/keys always make use of Public-key cryptography (asymmetric cryptography).

As a consequence, some elements of OpenPGP certificates/keys represent "private" (sometimes referred to as "secret") key material, while other elements represent "public" key material. Yet other elements contain metadata, and finally there are elements that serve as glue ("binding") between the various other elements of a certificate.

To hand out copies of one's OpenPGP key to third parties, implementations can generate a "certificate" / "public key" representation (Transferable Public Keys in the RFC), which consists of all the elements of the certificate, except for the private key material (and the optional S2K configuration).

The counterpart is called Transferable Secret Keys in the RFC. That is, an OpenPGP certificate that includes private key material.

A minimal OpenPGP key

A minimal OpenPGP key consists of the Secret-Key Packet for the primary key, and a self-certification (the Direct Key Signature).

Seen as a private OpenPGP key

A minimal version of Alice's private key (in ASCII-armored representation) looks like this:

-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6  7F33 00F9 FB0E C457 378C D29F 1026 98B3

xUsGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT4A7+GZ
tV8R+6qT6CadO7ItciB9/71C3UvpozaBO6XMz/vCtgYfGwoAAAA9BYJlFuqmBYkF
pI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj/Te2fzMA+fsOxFc3jNKf
ECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4gAIl6FM5SWuQxg12j0S0
7ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L+BXIoY2sIEQrLd4TAEEy
0BA8aQZTPEmMdiOCM1QB+V+BQZAO
=f0GN
-----END PGP PRIVATE KEY BLOCK-----

If we decode this OpenPGP data, we see that the key is made up of a sequence of two packets:

$ sq packet dump --hex alice_minimal.priv
Secret-Key Packet, new CTB, 2 header bytes + 75 bytes
Version: 6
Creation time: 2023-09-29 15:17:58 UTC
Pk algo: Ed25519
Pk size: 256 bits
Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
KeyID: AAA18CBB254685C5

    Secret Key:

        Unencrypted

    00000000  c5                                                 CTB
    00000001     4b                                              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
    0000002c                                       00            s2k_usage
    0000002d                                          ef e1 99   ed25519_secret
    00000030  b5 5f 11 fb aa 93 e8 26  9d 3b b2 2d 72 20 7d ff
    00000040  bd 42 dd 4b e9 a3 36 81  3b a5 cc cf fb

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
  • First, a "Secret-Key Packet", which contains the actual cryptographic key data. Note: the "Secret-Key" Packet contains both the private and the public part of the key. We also see in the output that this packet is "Unencrypted" (i.e. not password-protected).
  • Second, a "Direct Key Signature" (type 0x1F), "Signature directly on a key". This packet "binds the information in the Signature subpackets to the key". Each entry under "Signature Packet -> Hashed area" is one Signature subpacket, including for example information about algorithm preferences ("Symmetric algo preferences" and "Hash preferences").
---
---
A minimal OpenPGP key, visualized

Seen as a public certificate

Let's compare this with the same certificate seen as an armored OpenPGP certificate (that is, a "public key" variant of the key above, but without the private key material. An OpenPGP user might give such a certificate to a communication partner, so that the remote party could send encrypted messages to the user):

-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6  7F33 00F9 FB0E C457 378C D29F 1026 98B3

xioGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT7CtgYf
GwoAAAA9BYJlFuqmBYkFpI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj
/Te2fzMA+fsOxFc3jNKfECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4
gAIl6FM5SWuQxg12j0S07ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L
+BXIoY2sIEQrLd4TAEEy0BA8aQZTPEmMdiOCM1QB+V+BQZAO
=5nyq
-----END PGP PUBLIC KEY BLOCK-----
$ sq packet dump --hex alice_minimal.pub
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

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

Note that the two OpenPGP artifacts (OpenPGP certificate and OpenPGP private key) are almost identical.

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

  • the private key material (visualized in red), and
  • s2k configuration data, if any (this example doesn't have any). s2k is used when the secret key material is password-protected.
---
---
A minimal OpenPGP public certificate, visualized

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).

User IDs

User IDs are a mechanism for attaching identities to an OpenPGP certificate. Typically, a User ID will contain a name and an email address.

To look into these, we'll make a certificate that has one User ID. 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.

Let's look into the details of this key:

-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6  7F33 00F9 FB0E C457 378C D29F 1026 98B3
Comment: <alice@example.org>

xUsGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT4A7+GZ
tV8R+6qT6CadO7ItciB9/71C3UvpozaBO6XMz/vCtgYfGwoAAAA9BYJlFuqmBYkF
pI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj/Te2fzMA+fsOxFc3jNKf
ECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4gAIl6FM5SWuQxg12j0S0
7ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L+BXIoY2sIEQrLd4TAEEy
0BA8aQZTPEmMdiOCM1QB+V+BQZAOzRM8YWxpY2VAZXhhbXBsZS5vcmc+wrkGExsK
AAAAQAWCZRbqpgWJBaSPvQMLCQcDFQoIApkBApsBAh4BIiEGqqGMuyVGhcWDWDIF
Y/03tn8zAPn7DsRXN4zSnxAmmLMAAAAKCRCqoYy7JUaFxdu4IIotb9pnNbxdBHe0
nWeobsXWiFNf4u/5Zgi/wuDbwFYN69QspRkBD7om0IKiz1zreqly2fOyZgeLsro9
t4nkdgRuNSQrJymDvpGceGrMtNVpR3YsKdZUv0MZBP9TmMDVCw==
=bgQM
-----END PGP PRIVATE KEY BLOCK-----
$ sq packet dump --hex alice_userid.priv
Secret-Key Packet, new CTB, 2 header bytes + 75 bytes
    Version: 6
    Creation time: 2023-09-29 15:17:58 UTC
    Pk algo: Ed25519
    Pk size: 256 bits
    Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
    KeyID: AAA18CBB254685C5

    Secret Key:

        Unencrypted

    00000000  c5                                                 CTB
    00000001     4b                                              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
    0000002c                                       00            s2k_usage
    0000002d                                          ef e1 99   ed25519_secret
    00000030  b5 5f 11 fb aa 93 e8 26  9d 3b b2 2d 72 20 7d ff
    00000040  bd 42 dd 4b e9 a3 36 81  3b a5 cc cf fb

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

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

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 

Instead of two packets, as before, we see four packets in this certificate:

  • First, a "Secret-Key Packet,"
  • then a "Signature Packet" (these two packets are the same as above).
  • Third, a "User ID Packet", which contains the name and email address we used
  • Finally, a "Positive Certification Signature" (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)

Subkeys

From here on, we'll look at the dumps in shorter format (you can see more detail by copying the certificates into the web-dumper at https://dump.sequoia-pgp.org/ and checking the "HexDump" checkbox).

Certifications (Third Party Signatures)

Revocations


  1. 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. At some point, 32 bit identifiers were called "short Key ID", while 64 bit identifiers were called "long Key ID". ↩︎

  2. When an OpenPGP certificate is stored as a file, it's in a format that is called transferable public key in the RFC ↩︎