ch4, zooming in: remove material that involves private key

(All of that should be in ch5)
This commit is contained in:
Heiko Schaefer 2023-10-15 14:10:21 +02:00
parent 2b018c73ee
commit 0965fa4fae
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D

View file

@ -333,78 +333,81 @@ Some OpenPGP subsystems may add User IDs to a certificate, which are not bound t
## Zooming in: Packet structure ## Zooming in: Packet structure
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. 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.
### A very minimal OpenPGP transferable secret key ### A very minimal OpenPGP certificate
We'll start with a very minimal version of [](alice_priv), stored as a *transferable secret key* ([RFC 10.2.](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#transferable-secret-keys)) (that is, including private key material). 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).
Note that the secret key material we're using in this chapter is not password protected. To learn more about encrypting private key material with passwords in OpenPGP, see
{numref}`encrypted_secrets`.
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. 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.
(split_alice)= Starting from [Alice's OpenPGP "private key"](alice_priv), we first produce the corresponding "public key", or certificate:
#### Splitting an OpenPGP key into packets
One way to produce a very minimal version of Alice's key is to split her full key into its component packets, and join only the relevant ones back together into a variant of the key.
```text ```text
$ sq packet split alice.priv $ sq key extract-cert alice.priv > alice.pub
``` ```
With this command, `sq` generates a set of files, each containing an individual OpenPGP packet of the original full key in `alice.priv`: (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.
```text ```text
alice.priv-0--SecretKey $ sq packet split alice.pub
alice.priv-1--Signature ```
alice.priv-2--UserID
alice.priv-3--Signature With this command, `sq` generates a set of files, each containing an individual OpenPGP packet of the original full certificate in `alice.pub`:
alice.priv-4--SecretSubkey
alice.priv-5--Signature ```text
alice.priv-6--SecretSubkey alice.pub-0--PublicKey
alice.priv-7--Signature alice.pub-1--Signature
alice.priv-8--SecretSubkey alice.pub-2--UserID
alice.priv-9--Signature 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
``` ```
```{admonition} VISUAL ```{admonition} VISUAL
:class: warning :class: warning
Show a very abstract diagram of the packets of Alice's OpenPGP key (above): Show a very abstract diagram of the packets of Alice's OpenPGP certificate (above):
- Secret-Key packet - Public-Key packet
- Direct Key Signature - Direct Key Signature
- User ID - User ID
- Certifying self-signature for User ID - Certifying self-signature for User ID
- Secret-Subkey packet - Public-Subkey packet
- Subkey binding signature - Subkey binding signature
- Secret-Subkey packet - Public-Subkey packet
- Subkey binding signature - Subkey binding signature
- Secret-Subkey packet - Public-Subkey packet
- Subkey binding signature - Subkey binding signature
``` ```
#### Joining packets into an OpenPGP key #### Joining packets into an OpenPGP certificate
For our first step, we'll use just the first two of these packets, and join them together as a private key: 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:
```text ```text
$ sq packet join alice.priv-0--SecretKey alice.priv-1--Signature --output alice_minimal.priv $ sq packet join alice.pub-0--PublicKey alice.pub-1--Signature --output alice_minimal.pub
``` ```
#### Inspecting this key #### Inspecting this certificate
This version of Alice's key contains just two packets: This version of Alice's certificate contains just two packets:
- 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 - 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). - 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).
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 be looking at, in the following two sections:
```{figure} diag/key-minimal.png ```{figure} diag/pubcert-minimal.png
:width: 40% :width: 40%
A minimal OpenPGP key, visualized A minimal OpenPGP certificate, visualized
``` ```
```{admonition} VISUAL ```{admonition} VISUAL
@ -417,22 +420,20 @@ This diagram needs adjustments about
We could show repeat-copies of the individual packet visualization again, below for each packet-related section. 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 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). 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 ASCII-armored representation, this very minimal key looks like this: In ASCII-armored representation, this very minimal key looks like this:
```text ```text
-----BEGIN PGP PRIVATE KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3
xUsGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT4A7+GZ xioGZRbqphsAAAAgUyTpQ6+rFfdu1bUSmHlpzRtdEGXr50Liq0f0hrOuZT7CtgYf
tV8R+6qT6CadO7ItciB9/71C3UvpozaBO6XMz/vCtgYfGwoAAAA9BYJlFuqmBYkF GwoAAAA9BYJlFuqmBYkFpI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj
pI+9AwsJBwMVCggCmwECHgEiIQaqoYy7JUaFxYNYMgVj/Te2fzMA+fsOxFc3jNKf /Te2fzMA+fsOxFc3jNKfECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4
ECaYswAAAAoJEKqhjLslRoXFZ0cgouNjgeNr0E9W18g4gAIl6FM5SWuQxg12j0S0 gAIl6FM5SWuQxg12j0S07ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L
7ExCOI5NPRDCrSnAV85mAXOzeIGeiVLPQ40oEal3CX/L+BXIoY2sIEQrLd4TAEEy +BXIoY2sIEQrLd4TAEEy0BA8aQZTPEmMdiOCM1QB+V+BQZAO
0BA8aQZTPEmMdiOCM1QB+V+BQZAO =5nyq
=f0GN -----END PGP PUBLIC KEY BLOCK-----
-----END PGP PRIVATE KEY BLOCK-----
``` ```
We'll now decode this OpenPGP data, and inspect the two packets in detail. We'll now decode this OpenPGP data, and inspect the two packets in detail.
@ -440,15 +441,16 @@ We'll now decode this OpenPGP data, and inspect the two packets in detail.
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 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:
```text ```text
$ sq packet dump --hex alice_minimal.priv $ sq packet dump --hex alice_minimal.pub
``` ```
#### Secret-Key Packet (public_key)=
#### Public-Key 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 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):
```text ```text
Secret-Key Packet, new CTB, 2 header bytes + 75 bytes Public-Key Packet, new CTB, 2 header bytes + 42 bytes
Version: 6 Version: 6
Creation time: 2023-09-29 15:17:58 UTC Creation time: 2023-09-29 15:17:58 UTC
Pk algo: Ed25519 Pk algo: Ed25519
@ -456,12 +458,8 @@ Secret-Key Packet, new CTB, 2 header bytes + 75 bytes
Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3 Fingerprint: AAA18CBB254685C58358320563FD37B67F3300F9FB0EC457378CD29F102698B3
KeyID: AAA18CBB254685C5 KeyID: AAA18CBB254685C5
Secret Key: 00000000 c6 CTB
00000001 2a length
Unencrypted
00000000 c5 CTB
00000001 4b length
00000002 06 version 00000002 06 version
00000003 65 16 ea a6 creation_time 00000003 65 16 ea a6 creation_time
00000007 1b pk_algo 00000007 1b pk_algo
@ -469,18 +467,14 @@ Secret-Key Packet, new CTB, 2 header bytes + 75 bytes
0000000c 53 24 e9 43 ed25519_public 0000000c 53 24 e9 43 ed25519_public
00000010 af ab 15 f7 6e d5 b5 12 98 79 69 cd 1b 5d 10 65 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 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
``` ```
The Secret-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 in large part of the actual cryptographic key data. Let's look at the packet field by field:
- `CTB: 0xc5`[^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 `0xc5` 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 type ID's value: "5". This is the value for a Secret-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). - `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: 0x4b`: The remaining length of this packet. - `length: 0x2a`: 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 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). 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).
- `version: 0x06`: The key material is in version 6 format - `version: 0x06`: The key material is in version 6 format
@ -491,11 +485,6 @@ This means that the next part of the packet follows the structure of [Version 6
- `public_len: 0x00000020`: "Octet count for the following public key material" (in this case, the length of the following `ed25519_public` field) - `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 - `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
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`: This [*S2K usage* value](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-key-encryption-s2k-u) specifies 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 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". [^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".
```{tip} ```{tip}
@ -503,12 +492,12 @@ This concludes the Public Key section of the packet. The remaining data follows
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. 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. Note that the *Public-Key packet* contains only the public part of the key.
(zooming_in_dks)= (zooming_in_dks)=
#### Direct Key Signature #### 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). 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).
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 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*).
@ -631,93 +620,36 @@ The signature is calculated over a hash. The hash, in this case, is calculated o
- A serialized form of the primary key's public data - 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) - A serialized form of this direct key signature packet (up to, but excluding the unhashed area)
### Seen as a very minimal OpenPGP certificate
Let's now look at a "public key" view of the (very minimal) OpenPGP key above. That is, the same data, but without the private key material parts. An OpenPGP user might give such a certificate to a communication partner, or upload it to a key server:
```text
$ sq key extract-cert alice_minimal.priv
-----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-----
```
```text
$ sq packet dump --hex alice_minimal.pub
```
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):
```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
```
Note that the packet is almost identical to the Secret-Key packet seen above.
The packet type ID (called `CTB` in the output) shows the packet type is now [*Public-Key packet*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-public-key-packet-tag-6), instead of *Secret-Key packet*, above. Besides this change, this *Public-Key packet* only leaves out the last section, which contained the private-key related fields `s2k_usage` and `ed25519_secret`.
The following, second packet in the certificate (the Direct Key Signature) is bit-for-bit identical as in the previous section. So we omit showing it again, here.
```{figure} diag/pubcert-minimal.png
:width: 40%
A minimal OpenPGP public certificate, visualized
```
In the following examples, we will only look at OpenPGP keys that include the private key material. The corresponding "certificate" variants, which only contain the public key material, are easy to imagine: like here, their packet type is changed from a Secret-Key to a Public-Key variant, and they leave out the private key material.
(zoom_enc_subkey)= (zoom_enc_subkey)=
### Encryption subkey ### Encryption subkey
Now we'll look at a subkey in Alice's key. An OpenPGP subkey, when it is linked to an OpenPGP certificate (via its primary key), effectively consists of two elements: 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 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). - 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 key, which we split apart above. In this split representation of Alice's key, the encryption subkey happens to be stored in `alice.priv-4--SecretSubkey`, and the associated binding self-signature for the subkey in `alice.priv-5--Signature`. 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} ````{note}
It's common to look at a packet dump for a full OpenPGP key, like this: It's common to look at a packet dump for a full OpenPGP certificate, like this:
```text ```text
$ sq packet dump --hex alice.priv $ 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 key](split_alice)). Finding a particular packet in that list can take a moment. 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. 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.
```` ````
#### Secret-Subkey packet #### Public-Subkey packet
First, we'll look at the *Secret-Subkey packet* that contains the component key data of this subkey: First, we'll look at the *Public-Subkey packet* that contains the component key data of this subkey:
```text ```text
$ sq packet dump --hex alice.priv-4--SecretSubkey $ sq packet dump --hex alice.pub-4--PublicSubkey
Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes Public-Subkey Packet, new CTB, 2 header bytes + 42 bytes
Version: 6 Version: 6
Creation time: 2023-09-29 15:17:58 UTC Creation time: 2023-09-29 15:17:58 UTC
Pk algo: X25519 Pk algo: X25519
@ -725,12 +657,8 @@ Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes
Fingerprint: C0A58384A438E5A14F73712426A4D45DBAEEF4A39E6B30B09D5513F978ACCA94 Fingerprint: C0A58384A438E5A14F73712426A4D45DBAEEF4A39E6B30B09D5513F978ACCA94
KeyID: C0A58384A438E5A1 KeyID: C0A58384A438E5A1
Secret Key: 00000000 ce CTB
00000001 2a length
Unencrypted
00000000 c7 CTB
00000001 4b length
00000002 06 version 00000002 06 version
00000003 65 16 ea a6 creation_time 00000003 65 16 ea a6 creation_time
00000007 19 pk_algo 00000007 19 pk_algo
@ -738,17 +666,13 @@ Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes
0000000c d1 ae 87 d7 x25519_public 0000000c d1 ae 87 d7 x25519_public
00000010 cc 42 af 99 34 c5 c2 5c ca fa b7 4a c8 43 fc 86 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 00000020 35 2a 46 01 f3 cc 00 f5 4a 09 3e 3f
0000002c 00 s2k_usage
0000002d 28 7d cd x25519_secret
00000030 da 26 16 37 8d ea 24 c7 ce e7 70 c7 9b e5 6f 0a
00000040 c9 77 fb bd 23 41 73 c9 57 5a bf 7c 4c
``` ```
Notice that the structure of this *Secret-Subkey packet* is the same as the *Secret-Key Packet* of the primary key, above. Only the content of the two packets differs in some points: 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 7 ([*Secret-Subkey packet*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-subkey-packet-tag-7)). - 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 DiffieHellman function built out of Curve25519). - 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 DiffieHellman function built out of Curve25519).
- Accordingly, both parts of the cryptographic key pair are labeled with the corresponding names `x25519_public` and `x25519_secret` (however, note that this difference only reflects the semantics of the fields, which are implied by the value of `pk_algo`. The actual data in both fields consists of just 32 bytes of cryptographic key material, without any type information.) - 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 #### Subkey binding signature
@ -776,7 +700,7 @@ In addition to its core purpose of making the connection, this signature also co
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. 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 ```text
$ sq packet dump --hex alice.priv-5--Signature $ sq packet dump --hex alice.pub-5--Signature
Signature Packet, new CTB, 2 header bytes + 171 bytes Signature Packet, new CTB, 2 header bytes + 171 bytes
Version: 6 Version: 6
Type: SubkeyBinding Type: SubkeyBinding
@ -865,8 +789,8 @@ write
``` ```
```text ```text
$ sq packet dump --hex alice.priv-6--SecretSubkey $ sq packet dump --hex alice.pub-6--PublicSubkey
Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes Public-Subkey Packet, new CTB, 2 header bytes + 42 bytes
Version: 6 Version: 6
Creation time: 2023-09-29 15:17:58 UTC Creation time: 2023-09-29 15:17:58 UTC
Pk algo: Ed25519 Pk algo: Ed25519
@ -874,12 +798,8 @@ Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes
Fingerprint: D07B24EC91A14DD240AC2D53E6C8A9E054949A41222EA738576ED19CAEA3DC99 Fingerprint: D07B24EC91A14DD240AC2D53E6C8A9E054949A41222EA738576ED19CAEA3DC99
KeyID: D07B24EC91A14DD2 KeyID: D07B24EC91A14DD2
Secret Key: 00000000 ce CTB
00000001 2a length
Unencrypted
00000000 c7 CTB
00000001 4b length
00000002 06 version 00000002 06 version
00000003 65 16 ea a6 creation_time 00000003 65 16 ea a6 creation_time
00000007 1b pk_algo 00000007 1b pk_algo
@ -887,14 +807,10 @@ Secret-Subkey Packet, new CTB, 2 header bytes + 75 bytes
0000000c 33 8c d4 f5 ed25519_public 0000000c 33 8c d4 f5 ed25519_public
00000010 1a 73 39 ef ce d6 0f 21 8d a0 58 a2 3c 3d 44 a8 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 00000020 59 e9 13 1f 12 9c 6f 19 d0 3d 40 a0
0000002c 00 s2k_usage
0000002d 0e cb d1 ed25519_secret
00000030 c9 bc 81 82 aa 77 1f a8 12 a6 2a 74 a4 20 c1 74
00000040 76 f3 86 24 fb a8 25 a5 62 dd d6 a2 91
``` ```
```text ```text
$ sq packet dump --hex alice.priv-7--Signature $ sq packet dump --hex alice.pub-7--Signature
Signature Packet, new CTB, 3 header bytes + 325 bytes Signature Packet, new CTB, 3 header bytes + 325 bytes
Version: 6 Version: 6
Type: SubkeyBinding Type: SubkeyBinding
@ -983,14 +899,14 @@ 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. 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.priv-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.priv-3--Signature` (these packets are an excerpt of Alice's full OpenPGP private key). 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 #### User ID packet
First, let's look at the User ID packet, which encodes an identity that Alice has connected to her OpenPGP certificate: First, let's look at the User ID packet, which encodes an identity that Alice has connected to her OpenPGP certificate:
```text ```text
$ sq packet dump --hex alice.priv-2--UserID $ sq packet dump --hex alice.pub-2--UserID
User ID Packet, new CTB, 2 header bytes + 19 bytes User ID Packet, new CTB, 2 header bytes + 19 bytes
Value: <alice@example.org> Value: <alice@example.org>
@ -1013,7 +929,7 @@ As above, when [linking a subkey](zoom_enc_subkey) to the OpenPGP certificate, a
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. 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 ```text
$ sq packet dump --hex alice.priv-3--Signature $ sq packet dump --hex alice.pub-3--Signature
Signature Packet, new CTB, 2 header bytes + 185 bytes Signature Packet, new CTB, 2 header bytes + 185 bytes
Version: 6 Version: 6
Type: PositiveCertification Type: PositiveCertification