mirror of
https://codeberg.org/openpgp/notes.git
synced 2024-11-23 08:02:05 +01:00
edit ch17
This commit is contained in:
parent
647b2494f5
commit
3f38d588f5
1 changed files with 39 additions and 29 deletions
|
@ -6,15 +6,15 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|||
(zoom_certificates)=
|
||||
# Zooming in: Packet structure of certificates and keys
|
||||
|
||||
Now that we've established these concepts, and the components that OpenPGP certificates consist of, let's look at the internal details of an example certificate.
|
||||
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
|
||||
|
||||
First, we'll look at a very minimal version of a "public key" variant of [](alice_priv). That is, an OpenPGP certificate (which doesn't contain private key material).
|
||||
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.
|
||||
|
||||
In this section, we use the Sequoia-PGP tool `sq` to handle and transform our example OpenPGP key, and to inspect internal OpenPGP packet data.
|
||||
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", or certificate:
|
||||
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
|
||||
|
@ -23,13 +23,15 @@ $ sq key extract-cert alice.priv > alice.pub
|
|||
(split_alice)=
|
||||
### Splitting the OpenPGP certificate into packets
|
||||
|
||||
One way to produce a very minimal version of Alice's certificate is to split the data in `alice.pub` into its component packets, and join only the relevant ones back together into a new variant.
|
||||
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 of the original full certificate in `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
|
||||
|
@ -50,22 +52,28 @@ alice.pub-9--Signature
|
|||
Overview of the packets in Alice's OpenPGP certificate
|
||||
```
|
||||
|
||||
### Joining packets into an OpenPGP certificate
|
||||
This process allows us to focus on the specific packets within Alice's OpenPGP certificate.
|
||||
|
||||
For our first step, we'll use just the first two of the packets of Alice's certificate, and join them together as a very minimal 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) (a self-signature that binds metadata to the primary key).
|
||||
- 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 be looking at, in the following two sections:
|
||||
This is the shape of the packets we'll explore in the subsequent sections:
|
||||
|
||||
```{figure} diag/pubcert-minimal.png
|
||||
:width: 40%
|
||||
|
@ -83,9 +91,9 @@ This diagram needs adjustments about
|
|||
We could show repeat-copies of the individual packet visualization again, below for each packet-related section.
|
||||
```
|
||||
|
||||
In the real world, you won't usually encounter an OpenPGP certificate that is quite this minimal. However, this is technically a valid OpenPGP certificate (and we'll add more components to it, later in this 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 looks like this:
|
||||
In ASCII-armored representation, this very minimal key appears as follows:
|
||||
|
||||
```text
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
@ -99,18 +107,20 @@ gAIl6FM5SWuQxg12j0S07ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L
|
|||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
We'll now decode this OpenPGP data, and inspect the two packets in detail.
|
||||
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 inspect the internal structure of the OpenPGP data, we run the Sequoia-PGP tool `sq`, using the `packet dump` subcommand. The output of `sq` is one block of text, but to discuss the content of each packet we'll break the output up into sections here:
|
||||
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 now starts 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 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
|
||||
|
@ -132,23 +142,23 @@ Public-Key Packet, new CTB, 2 header bytes + 42 bytes
|
|||
00000020 eb e7 42 e2 ab 47 f4 86 b3 ae 65 3e
|
||||
```
|
||||
|
||||
The Public-Key packet consists in large part of the actual cryptographic key data. Let's look at the packet field by field:
|
||||
The Public-Key packet consists primarily of the cryptographic key data. Let's look at the packet field by field:
|
||||
|
||||
- `CTB: 0xc6`[^CTB]: 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`. 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: "6". This is the value for a Public-Key packet, as shown in the list of [packet type IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-packet-tags).
|
||||
- `length: 0x2a`: The remaining length of this packet.
|
||||
- `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).
|
||||
|
||||
The packet type id defines the semantics of the remaining data in the packet. We're looking at 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).
|
||||
- `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
|
||||
- `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).
|
||||
|
||||
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`: 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)).
|
||||
|
||||
- `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 ID 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" (in this case, the length of the following `ed25519_public` field)
|
||||
- `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`), in this case 32 bytes of Ed25519 public key
|
||||
- `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.
|
||||
|
||||
[^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 previous versions, the RFC called this field "Packet Tag".
|
||||
- `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}
|
||||
|
||||
|
@ -160,9 +170,9 @@ Note that the *Public-Key packet* contains only the public part of the key.
|
|||
(zooming_in_dks)=
|
||||
### 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.pub-1--Signature` contains this packet).
|
||||
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 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 algorithm preference* and *hash algorithm preferences*).
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue