From 6d633424556efdd9997e2429d3b84ae81179883d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 14 Dec 2023 12:33:39 +0100 Subject: [PATCH 01/80] Fix glossary entry of Packet --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 76d7fed..b9e75ca 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -369,7 +369,7 @@ Owner See {term}`Certificate Holder`. Packet - An element in an {term}`OpenPGP Certificate`, which represents {term}`components` or {term}`signatures`. + An element in an {term}`OpenPGP Certificate` or {term}`message`. Packet Header A section of variable length at the beginning of a {term}`Packet`, which encodes for example the {term}`Packet Type ID`. See the relevant [section in the RFC](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-packet-headers), which explains this section in more detail. From 01e18a835b1bf069ede360c874c7aed5cf82927d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 14 Dec 2023 12:35:23 +0100 Subject: [PATCH 02/80] Differentiate inline-signed messages between one-pass-signed and prefix-signed messages --- book/source/glossary.md | 7 ++++++- book/source/signing_data.md | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index b9e75ca..01fc23f 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -313,7 +313,10 @@ Notation Tag Part of a {term}`Notation` name. One-pass Signature Packet - One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. See [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig) for more details. + One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. See [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig) for more details. + +One-pass-signed Message + A {term}`OpenPGP Message` signed using one or more {term}`One-pass signatures`. OpenPGP Certificate An OpenPGP certificate contains public key material, identity claims and third party certifications (but no private key material) @@ -405,6 +408,8 @@ Preferred AEAD Ciphersuites Subpacket See [RFC 5.2.3.15](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-aead-ciphersuites) +Prefixed-Signed Message + An {term}`OpenPGP Message` with one or more prefixed {term}`signature packets`. Primary Component Key See {term}`OpenPGP Primary Key`. diff --git a/book/source/signing_data.md b/book/source/signing_data.md index ca174b3..7979400 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -54,7 +54,12 @@ This method is commonly used for signing or encrypting emails. Most email softwa #### Structure -An {term}`inline-signed` {term}`OpenPGP message` consists of three segments: +There are two different constructions available to generate inline-signed messages: + +* {term}`One-pass-signed messages` are signed using one ore more {term}`one-pass signatures` +* {term}`Prefixed-signed messages` have the actual signature(s) prefixed to the {term}`OpenPGP message`. + +A {term}`one-pass-signed` {term}`OpenPGP message` consists of three segments: 1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation in one pass. @@ -62,6 +67,8 @@ An {term}`inline-signed` {term}`OpenPGP message` consists of t 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. +Less commonly used are {term}`prefixed-signed messages`, where the {term}`signature packet(s)` are simply prepended to the message. + #### Creation To produce an {term}`inline signature`, the {term}`signer` processes the entirety of the data by reading from an input file and writing into an output {term}`OpenPGP message` file. As the data is processed, the {term}`signer` simultaneously calculates a {term}`cryptographic signature`. This procedure results in the appending of a {term}`data signature packet` to the output {term}`OpenPGP message` file, where it can be efficiently stored. From a174779c1dde225b620cae47c6d298717e7084fb Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 14 Dec 2023 12:38:55 +0100 Subject: [PATCH 03/80] Fix typo --- book/source/signing_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 7979400..6ae7953 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -56,7 +56,7 @@ This method is commonly used for signing or encrypting emails. Most email softwa There are two different constructions available to generate inline-signed messages: -* {term}`One-pass-signed messages` are signed using one ore more {term}`one-pass signatures` +* {term}`One-pass-signed messages` are signed using one or more {term}`one-pass signatures` * {term}`Prefixed-signed messages` have the actual signature(s) prefixed to the {term}`OpenPGP message`. A {term}`one-pass-signed` {term}`OpenPGP message` consists of three segments: From 819d5e686875ac4f9c4aa94c997b9f3f908e71ee Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Mon, 18 Dec 2023 19:07:19 +0100 Subject: [PATCH 04/80] Adjust glossary link I think this sentence is more about the higher level concept of "data signatures" than about signature packets. --- book/source/signing_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 6ae7953..d5eafe4 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -26,7 +26,7 @@ Note that {term}`data signatures` are distinct from [](/signing_ {term}`Data signatures` are generated by {term}`hashing` the message content along with the {term}`metadata` in the {term}`OpenPGP signature packet`, and calculating a {term}`cryptographic signature` over that {term}`hash`. The resulting {term}`cryptographic signature` is stored in the {term}`signature packet`. -{term}`Data signature packets` manifest in three distinct forms, which will be detailed in the subsequent section. +{term}`Data signatures` manifest in three distinct forms, which will be detailed in the subsequent section. (forms-of-data-signatures)= ## Forms of OpenPGP data signatures From 16c6d0c265d660c22e11487e8e066cd0515ebb45 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Mon, 18 Dec 2023 19:36:48 +0100 Subject: [PATCH 05/80] Complete unfinished sentence --- book/source/signing_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index d5eafe4..76436b8 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -75,7 +75,7 @@ To produce an {term}`inline signature`, the {term}`signer` processes the entiret For efficient {term}`verification`, an application must understand how to handle the {term}`literal data` prior to its reading. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. These {term}`packets` include essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. This setup enables the verifier to process the data correctly and efficiently. -Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificates before processing the entirety of the - potentially large - signed data, and . +Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. #### Verification From 7ef91f4d057c047c4127eabdd03e14ac3a5b1381 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Mon, 18 Dec 2023 18:28:46 +0100 Subject: [PATCH 06/80] Structure: separate sections for One-pass-signed and Prefixed-signed messages --- book/source/signing_data.md | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 76436b8..b9a43fb 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -52,12 +52,16 @@ An {term}`inline signature` joins the signed data and its corresponding {term}`d This method is commonly used for signing or encrypting emails. Most email software capable of handling OpenPGP communications typically uses {term}`inline signatures`. -#### Structure +OpenPGP defines two different forms of inline-signed messages: -There are two different constructions available to generate inline-signed messages: +1. **{term}`One-pass-signed messages`** are signed using one or more {term}`one-pass signatures` +2. **{term}`Prefixed-signed messages`** have the actual signature(s) prefixed to the {term}`OpenPGP message`. -* {term}`One-pass-signed messages` are signed using one or more {term}`one-pass signatures` -* {term}`Prefixed-signed messages` have the actual signature(s) prefixed to the {term}`OpenPGP message`. +While the latter is conceptually slightly simpler, it has no strong benefits over {term}`one-pass-signed messages` and is rarely used. + +#### One-pass-signed message + +##### Structure A {term}`one-pass-signed` {term}`OpenPGP message` consists of three segments: @@ -67,9 +71,7 @@ A {term}`one-pass-signed` {term}`OpenPGP message` consi 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. -Less commonly used are {term}`prefixed-signed messages`, where the {term}`signature packet(s)` are simply prepended to the message. - -#### Creation +##### Creation To produce an {term}`inline signature`, the {term}`signer` processes the entirety of the data by reading from an input file and writing into an output {term}`OpenPGP message` file. As the data is processed, the {term}`signer` simultaneously calculates a {term}`cryptographic signature`. This procedure results in the appending of a {term}`data signature packet` to the output {term}`OpenPGP message` file, where it can be efficiently stored. @@ -77,7 +79,7 @@ For efficient {term}`verification`, an application must understand how to handle Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. -#### Verification +##### Verification {term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: @@ -89,6 +91,21 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. +#### Prefixed-signed message + +A {term}`prefixed-signed message` serves the same function as a {term}`one-pass-signed message`. However, this form is less commonly used. +In a {term}`prefixed-signed message`, the {term}`signature packet(s)` are simply prepended to the message. + +Especially for longer messages, it takes a bit more work to generate an inline signed OpenPGP message in this format. + +##### Structure + +1. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. + +2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. + +Note that the signature packet(s) is/are stored ahead of the message itself, in this format. For verification, this is equally convenient as the one-pass signed message form. However, to create this form, the data must be processed twice: one time reading it to calculate the cryptographic signature, and one time to copy the data into the OpenPGP message after the signature packet(s). + (cleartext-signature)= ### Cleartext signatures From 3d89f0124672a0a5bb7a1a0ad05f4b3cafc6d08c Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Mon, 18 Dec 2023 18:54:11 +0100 Subject: [PATCH 07/80] Add note: a one-pass signature packet is not a type of signature --- book/source/signing_data.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index b9a43fb..c505dc6 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -71,6 +71,12 @@ A {term}`one-pass-signed` {term}`OpenPGP message` consi 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. +```{note} +Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. + +Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. +``` + ##### Creation To produce an {term}`inline signature`, the {term}`signer` processes the entirety of the data by reading from an input file and writing into an output {term}`OpenPGP message` file. As the data is processed, the {term}`signer` simultaneously calculates a {term}`cryptographic signature`. This procedure results in the appending of a {term}`data signature packet` to the output {term}`OpenPGP message` file, where it can be efficiently stored. From e9a21f1d2da435ece88a9b36d96b1b2b11f6edd4 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Mon, 18 Dec 2023 19:39:23 +0100 Subject: [PATCH 08/80] Partially flatten section hierarchy for less depth --- book/source/signing_data.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index c505dc6..eaf7177 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -39,14 +39,14 @@ Note that {term}`data signatures` are distinct from [](/signing_ [^sign-modes-gpg]: These three forms of {term}`signature` application align with GnuPG's `--detach-sign`, `--sign`, and `--clearsign` command options. -### Detached signatures +## Detached signatures A {term}`detached signature` is produced by calculating an {term}`OpenPGP signature` over the data intended for signing. The original data remains unchanged, and the {term}`OpenPGP signature` is stored as a standalone file. A {term}`detached signature` file can be distributed alongside or independent of the original data. The {term}`authenticity` and integrity of the original data file can be {term}`verified` by using the {term}`detached signature` file. This {term}`signature` format is especially useful for signing software releases and other files where it is imperative that the content remains unaltered during the signing process. (inline-signature)= -### Inline signatures +## Inline signatures An {term}`inline signature` joins the signed data and its corresponding {term}`data signature` into a single {term}`OpenPGP message`. @@ -59,9 +59,9 @@ OpenPGP defines two different forms of inline-signed messages: While the latter is conceptually slightly simpler, it has no strong benefits over {term}`one-pass-signed messages` and is rarely used. -#### One-pass-signed message +### One-pass-signed message -##### Structure +#### Structure A {term}`one-pass-signed` {term}`OpenPGP message` consists of three segments: @@ -77,7 +77,7 @@ Despite its name, a {term}`one-pass signature packet` is not a type of {term}`si Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. ``` -##### Creation +#### Creation To produce an {term}`inline signature`, the {term}`signer` processes the entirety of the data by reading from an input file and writing into an output {term}`OpenPGP message` file. As the data is processed, the {term}`signer` simultaneously calculates a {term}`cryptographic signature`. This procedure results in the appending of a {term}`data signature packet` to the output {term}`OpenPGP message` file, where it can be efficiently stored. @@ -85,7 +85,7 @@ For efficient {term}`verification`, an application must understand how to handle Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. -##### Verification +#### Verification {term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: @@ -97,14 +97,14 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. -#### Prefixed-signed message +### Prefixed-signed message A {term}`prefixed-signed message` serves the same function as a {term}`one-pass-signed message`. However, this form is less commonly used. In a {term}`prefixed-signed message`, the {term}`signature packet(s)` are simply prepended to the message. Especially for longer messages, it takes a bit more work to generate an inline signed OpenPGP message in this format. -##### Structure +#### Structure 1. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. @@ -113,14 +113,14 @@ Especially for longer messages, it takes a bit more work to generate an inline s Note that the signature packet(s) is/are stored ahead of the message itself, in this format. For verification, this is equally convenient as the one-pass signed message form. However, to create this form, the data must be processed twice: one time reading it to calculate the cryptographic signature, and one time to copy the data into the OpenPGP message after the signature packet(s). (cleartext-signature)= -### Cleartext signatures +## Cleartext signatures The *{term}`Cleartext Signature Framework`* (CSF) in OpenPGP accomplishes two primary objectives: - maintaining the message in a human-readable cleartext format, accessible without OpenPGP-specific software - incorporating an {term}`OpenPGP signature` for {term}`authentication` by users with OpenPGP-compatible software -#### Example +### Example The following is a detailed example of a {numref}`cleartext` signature: @@ -141,7 +141,7 @@ r13/eqMN8kfCDw== This {term}`signature` consists of two parts: a message ("hello world") and an ASCII-armored {term}`OpenPGP signature`. The message is immediately comprehensible to a human reader, while the {term}`signature` block allows for the message's {term}`authenticity` {term}`verification` via OpenPGP software. -#### Use case +### Use case {term}`Cleartext signatures` combine the advantages of both {term}`detached` and {term}`inline signatures`: @@ -153,7 +153,7 @@ These features are particularly beneficial in scenarios where signed messages ar [^arch-certifications]: An illustrative example is the workflow adopted by Arch Linux to {term}`certify` {term}`User IDs` of new packagers. This process relies on [cleartext signed statements from existing packagers](https://gitlab.archlinux.org/archlinux/archlinux-keyring/-/blob/master/.gitlab/issue_templates/New%20Packager%20Key.md?ref_type=heads&plain=1#L33-46). These signed statements are stored as attachments in an issue tracking system for later inspection. The advantage of this approach lies in the convenience of having the message and signature in a single file, which simplifies manual handling. Based on the vouches in these {term}`cleartext signed` messages and an [email confirmation from the new packager](https://gitlab.archlinux.org/archlinux/archlinux-keyring/-/wikis/workflows/verify-a-packager-key), the main key operators can issue {term}`OpenPGP third-party certifications`. -#### Text transformations for cleartext signatures +### Text transformations for cleartext signatures The {term}`cleartext signature framework` includes specific text normalization procedures to ensure the integrity and clarity of the message: @@ -161,7 +161,7 @@ The {term}`cleartext signature framework` includes specific text normalization p - **Normalization of line endings**: Consistent with the approach for any other [text signature](data-signature-types), a {term}`cleartext signature` is calculated on the text with normalized line endings (``). This ensures that the {term}`signature` remains valid regardless of the text format of the receiving {term}`implementation`. -#### Pitfalls +### Pitfalls Despite their widespread adoption, {term}`cleartext signatures` have their limitations and are sometimes viewed as a "legacy method"[^csf-gnupg]. The {term}`RFC` details the [pitfalls of cleartext signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-issues-with-the-cleartext-s), such as incompatibility with semantically meaningful whitespace, challenges with large messages, and security vulnerabilities related to misleading Hash header manipulations. Given these issues, safer alternatives like {term}`inline` and {term}`detached signature` forms are advised. From b2199d95c5bf2080bbf81a61152b9df17a8366e9 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 19 Dec 2023 11:01:15 +0100 Subject: [PATCH 09/80] Adjust styling of "One-pass signed" to use only one dash, and "Prefixed Signed" accordingly (This mirrors section 10.3 in c-r) --- book/source/glossary.md | 4 ++-- book/source/signing_data.md | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 01fc23f..d07f4dc 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -315,7 +315,7 @@ Notation Tag One-pass Signature Packet One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. See [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig) for more details. -One-pass-signed Message +One-pass signed Message A {term}`OpenPGP Message` signed using one or more {term}`One-pass signatures`. OpenPGP Certificate @@ -408,7 +408,7 @@ Preferred AEAD Ciphersuites Subpacket See [RFC 5.2.3.15](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-aead-ciphersuites) -Prefixed-Signed Message +Prefixed signed Message An {term}`OpenPGP Message` with one or more prefixed {term}`signature packets`. Primary Component Key diff --git a/book/source/signing_data.md b/book/source/signing_data.md index eaf7177..bdb21a7 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -54,16 +54,16 @@ This method is commonly used for signing or encrypting emails. Most email softwa OpenPGP defines two different forms of inline-signed messages: -1. **{term}`One-pass-signed messages`** are signed using one or more {term}`one-pass signatures` -2. **{term}`Prefixed-signed messages`** have the actual signature(s) prefixed to the {term}`OpenPGP message`. +1. **{term}`One-pass signed messages`** are signed using one or more {term}`one-pass signatures` +2. **{term}`Prefixed signed messages`** have the actual signature(s) prefixed to the {term}`OpenPGP message`. -While the latter is conceptually slightly simpler, it has no strong benefits over {term}`one-pass-signed messages` and is rarely used. +While {term}`prefixed signed messages` are conceptually slightly simpler, they have no strong benefits over {term}`one-pass signed messages` and are rarely used. -### One-pass-signed message +### One-pass signed message #### Structure -A {term}`one-pass-signed` {term}`OpenPGP message` consists of three segments: +A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: 1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation in one pass. @@ -97,10 +97,10 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. -### Prefixed-signed message +### Prefixed signed message -A {term}`prefixed-signed message` serves the same function as a {term}`one-pass-signed message`. However, this form is less commonly used. -In a {term}`prefixed-signed message`, the {term}`signature packet(s)` are simply prepended to the message. +A {term}`prefixed signed message` serves the same function as a {term}`one-pass signed message`. However, this form is less commonly used. +In a {term}`prefixed signed message`, the {term}`signature packet(s)` are simply prepended to the message. Especially for longer messages, it takes a bit more work to generate an inline signed OpenPGP message in this format. From 864ed59a645611089d90514fe1e3d4c92ade1457 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 19 Dec 2023 13:27:04 +0100 Subject: [PATCH 10/80] Edits for clarity --- book/source/signing_data.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index bdb21a7..b844be7 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -52,15 +52,17 @@ An {term}`inline signature` joins the signed data and its corresponding {term}`d This method is commonly used for signing or encrypting emails. Most email software capable of handling OpenPGP communications typically uses {term}`inline signatures`. -OpenPGP defines two different forms of inline-signed messages: +OpenPGP defines two variant forms of inline-signed messages: -1. **{term}`One-pass signed messages`** are signed using one or more {term}`one-pass signatures` -2. **{term}`Prefixed signed messages`** have the actual signature(s) prefixed to the {term}`OpenPGP message`. +1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce this format in one pass. +2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. -While {term}`prefixed signed messages` are conceptually slightly simpler, they have no strong benefits over {term}`one-pass signed messages` and are rarely used. +[^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. ### One-pass signed message +This is the commonly used format for inline signed messages. + #### Structure A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: @@ -90,7 +92,7 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin {term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: 1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. - + 2. **Processing the {term}`literal data packet`**: This step involves {term}`hashing` the literal data, preparing it for {term}`signature` {term}`verification`. 3. **{term}`Verifying` {term}`signature packets`**: Located at the end of the message, these {term}`packets` are checked against the previously calculated {term}`hash digest`. @@ -99,18 +101,24 @@ Important to note, the {term}`signer`'s {term}`public key`, ### Prefixed signed message -A {term}`prefixed signed message` serves the same function as a {term}`one-pass signed message`. However, this form is less commonly used. -In a {term}`prefixed signed message`, the {term}`signature packet(s)` are simply prepended to the message. - -Especially for longer messages, it takes a bit more work to generate an inline signed OpenPGP message in this format. +A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. This inline signature format serves the same function as a {term}`one-pass signed message`. For the verifier, the two formats are equally convenient. However, on the signer's side, it takes more computational work to generate a {term}`prefixed signed message`. #### Structure -1. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. +In this format, the signature packets are stored ahead of the message itself: + +1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. 2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. -Note that the signature packet(s) is/are stored ahead of the message itself, in this format. For verification, this is equally convenient as the one-pass signed message form. However, to create this form, the data must be processed twice: one time reading it to calculate the cryptographic signature, and one time to copy the data into the OpenPGP message after the signature packet(s). +Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. + +For verification, this is equally convenient as the one-pass signed message form. + +However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: + +- once reading it to calculate the cryptographic signature, and +- once more to store the data in the generated OpenPGP message, after the signature packet(s). (cleartext-signature)= ## Cleartext signatures From cf765f0b446c09ccfcaac4de9c668d55326e6f13 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 19 Dec 2023 13:37:05 +0100 Subject: [PATCH 11/80] Add link target headers --- book/source/signing_data.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index b844be7..3fe97eb 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -59,6 +59,7 @@ OpenPGP defines two variant forms of inline-signed messages: [^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. +(one-pass-signature)= ### One-pass signed message This is the commonly used format for inline signed messages. @@ -99,6 +100,7 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. +(prefixed-signature)= ### Prefixed signed message A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. This inline signature format serves the same function as a {term}`one-pass signed message`. For the verifier, the two formats are equally convenient. However, on the signer's side, it takes more computational work to generate a {term}`prefixed signed message`. From 99e2ea7cdd89d389c6c66eea3aa86a3db0ab1180 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 19 Dec 2023 15:45:07 +0100 Subject: [PATCH 12/80] Expand glossary entries for inline signatures forms. --- book/source/glossary.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index d07f4dc..e804683 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -224,7 +224,14 @@ Initial Introducer An {term}`OpenPGP Certificate` explicitly {term}`delegated` to from a {term}`Trust Anchor`. Inline Signature - A {term}`Data Signature` which exists encapsulated alongside the data it was created for in an OpenPGP container. See [](forms-of-data-signatures). + An [inline signature](inline-signature) is a type of {term}`OpenPGP message` which stores a {term}`Data Signature` alongside the message it signs. Both the message and the signature are stored in a shared OpenPGP container. + + The standard defines two variant formats for inline signatures: + + - {term}`One-pass signed Message`: This format is now commonly used. + - {term}`Prefixed signed Message`: This is a historical format. It is still supported, but rarely used. + + For more context, see [](forms-of-data-signatures). Issuer An entity, that created an {term}`OpenPGP Signature Packet` using an {term}`Transferable Secret Key`. @@ -316,7 +323,9 @@ One-pass Signature Packet One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. See [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig) for more details. One-pass signed Message - A {term}`OpenPGP Message` signed using one or more {term}`One-pass signatures`. + The commonly used form of an OpenPGP {term}`Inline Signature`. It combines an {term}`OpenPGP Message` with {term}`signature packets` and accompanying auxiliary {term}`One-pass signatures`. + + For details see [](one-pass-signature). OpenPGP Certificate An OpenPGP certificate contains public key material, identity claims and third party certifications (but no private key material) @@ -409,7 +418,9 @@ Preferred AEAD Ciphersuites Subpacket See [RFC 5.2.3.15](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-aead-ciphersuites) Prefixed signed Message - An {term}`OpenPGP Message` with one or more prefixed {term}`signature packets`. + A type of {term}`Inline Signature`. This form of {term}`Inline Signature` is historical and now rarely used. Superseded by {term}`One-pass signed Message`. + + For details see [](prefixed-signature). Primary Component Key See {term}`OpenPGP Primary Key`. From b338286947bf385e38bd227b6279210a386955c8 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 19 Dec 2023 17:25:12 +0100 Subject: [PATCH 13/80] Clarify the reason for OPS sigs more and tweak the text structure --- book/source/signing_data.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 3fe97eb..24e2c75 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -41,7 +41,7 @@ Note that {term}`data signatures` are distinct from [](/signing_ ## Detached signatures -A {term}`detached signature` is produced by calculating an {term}`OpenPGP signature` over the data intended for signing. The original data remains unchanged, and the {term}`OpenPGP signature` is stored as a standalone file. A {term}`detached signature` file can be distributed alongside or independent of the original data. The {term}`authenticity` and integrity of the original data file can be {term}`verified` by using the {term}`detached signature` file. +A {term}`detached signature` is produced by calculating an {term}`OpenPGP signature` over the data intended for signing. The original data remains unchanged, and the {term}`OpenPGP signature` is stored separately, e.g. as a standalone file. A {term}`detached signature` file can be distributed alongside or independent of the original data. The {term}`authenticity` and integrity of the original data file can be {term}`verified` by using the {term}`detached signature` file. This {term}`signature` format is especially useful for signing software releases and other files where it is imperative that the content remains unaltered during the signing process. @@ -54,7 +54,7 @@ This method is commonly used for signing or encrypting emails. Most email softwa OpenPGP defines two variant forms of inline-signed messages: -1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce this format in one pass. +1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier verify this format in one pass. 2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. [^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. @@ -68,7 +68,7 @@ This is the commonly used format for inline signed messages. A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: -1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation in one pass. +1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. 2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. @@ -77,14 +77,20 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi ```{note} Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. -Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. +Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. + +The position of the signature packet within the OpenPGP message is important for efficient data processing. The plaintext data might be large in size, and memory might be constrained. +The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit the data to be signed while calculating the signature. The signature itself is therefore appended to the data. +The verifier on the other hand needs to know the hash algorithm used to calculate the signature before starting the verification process. As a consequence, either the producer would need to pass the plaintext data twice, once to calculate the signature and a second time to emit the signed data (the result is a prefixed-signed message), or the verifier needs to process (and cache) the whole OpenPGP message to reach the signature packets at the end in order to determine the hash algorithm, to then re-process the whole message, verifying the signature. + +The one-pass signature solves this issue, by allowing both the creation and verification of a signed message in a single pass. ``` #### Creation -To produce an {term}`inline signature`, the {term}`signer` processes the entirety of the data by reading from an input file and writing into an output {term}`OpenPGP message` file. As the data is processed, the {term}`signer` simultaneously calculates a {term}`cryptographic signature`. This procedure results in the appending of a {term}`data signature packet` to the output {term}`OpenPGP message` file, where it can be efficiently stored. +To produce an {term}`inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the plaintext data, emitting it as a {term}`literal data` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. -For efficient {term}`verification`, an application must understand how to handle the {term}`literal data` prior to its reading. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. These {term}`packets` include essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. This setup enables the verifier to process the data correctly and efficiently. +For efficient {term}`verification`, an application must understand how to handle the {term}`literal data` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in only a single pass. Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. @@ -103,7 +109,7 @@ Important to note, the {term}`signer`'s {term}`public key`, (prefixed-signature)= ### Prefixed signed message -A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. This inline signature format serves the same function as a {term}`one-pass signed message`. For the verifier, the two formats are equally convenient. However, on the signer's side, it takes more computational work to generate a {term}`prefixed signed message`. +A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass-signed and prefixed-signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. #### Structure From 23d97d691266e0447809584292379581cedfbc3d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 19 Dec 2023 18:34:22 +0100 Subject: [PATCH 14/80] Incorporate diagram of OPS-signed message --- book/assets/drawio/ops-signed-message.drawio | 74 ++++++++++++++++++++ book/assets/drawio/ops-signed-message.svg | 3 + book/source/signing_data.md | 7 ++ 3 files changed, 84 insertions(+) create mode 100644 book/assets/drawio/ops-signed-message.drawio create mode 100644 book/assets/drawio/ops-signed-message.svg diff --git a/book/assets/drawio/ops-signed-message.drawio b/book/assets/drawio/ops-signed-message.drawio new file mode 100644 index 0000000..bedff83 --- /dev/null +++ b/book/assets/drawio/ops-signed-message.drawio @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/book/assets/drawio/ops-signed-message.svg b/book/assets/drawio/ops-signed-message.svg new file mode 100644 index 0000000..1079fa3 --- /dev/null +++ b/book/assets/drawio/ops-signed-message.svg @@ -0,0 +1,3 @@ + + +
One-Pass-Signature
Hash: SHA512
Fingerprint: 0xB0B0
One-Pass-Signature...
Literal Data
"Hello World!"
Literal Data...
Signature
Hash: SHA512
Issuer: B0B0
Signature...
One-Pass-Signature
Hash: SHA384
Fingerprint: 0xB0B1
One-Pass-Signature...
Signature
Hash: SHA512
Issuer: B0B1
Signature...
"Hello World!" is hashed
"Hello World!" is hashed
SHA512 Hash
SHA512 Hash
SHA384 Hash
SHA384 Hash
Text is not SVG - cannot display
\ No newline at end of file diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 24e2c75..43cf0ed 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -74,6 +74,13 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. +```{figure} plain_svg/ops-signed-message.svg +:name: fig-ops-signed-message +:alt: Depicts the structure of a one-pass-signed message. + +The structure of a one-pass signed message. +``` + ```{note} Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. From 70b6bd2f439dc1bde82bcaf495df707676f562b3 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 19 Dec 2023 18:53:53 +0100 Subject: [PATCH 15/80] Fix diagrams --- book/assets/drawio/ops-signed-message.drawio | 38 ++++++++++---------- book/assets/drawio/ops-signed-message.svg | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/book/assets/drawio/ops-signed-message.drawio b/book/assets/drawio/ops-signed-message.drawio index bedff83..deaec9a 100644 --- a/book/assets/drawio/ops-signed-message.drawio +++ b/book/assets/drawio/ops-signed-message.drawio @@ -1,30 +1,30 @@ - + - + - + - + - + - + - + - + - + @@ -32,40 +32,40 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/book/assets/drawio/ops-signed-message.svg b/book/assets/drawio/ops-signed-message.svg index 1079fa3..da6b370 100644 --- a/book/assets/drawio/ops-signed-message.svg +++ b/book/assets/drawio/ops-signed-message.svg @@ -1,3 +1,3 @@ -
One-Pass-Signature
Hash: SHA512
Fingerprint: 0xB0B0
One-Pass-Signature...
Literal Data
"Hello World!"
Literal Data...
Signature
Hash: SHA512
Issuer: B0B0
Signature...
One-Pass-Signature
Hash: SHA384
Fingerprint: 0xB0B1
One-Pass-Signature...
Signature
Hash: SHA512
Issuer: B0B1
Signature...
"Hello World!" is hashed
"Hello World!" is hashed
SHA512 Hash
SHA512 Hash
SHA384 Hash
SHA384 Hash
Text is not SVG - cannot display
\ No newline at end of file +
One-Pass-Signature
Hash: SHA512
Fingerprint: 0xB0B0
One-Pass-Signature...
Literal Data
"Hello World!"
Literal Data...
Signature
Hash: SHA512
Issuer: B0B0
Signature...
One-Pass-Signature
Hash: SHA384
Fingerprint: 0xB0B1
One-Pass-Signature...
Signature
Hash: SHA384
Issuer: B0B1
Signature...
"Hello World!" is hashed
"Hello World!" is hashed
SHA512 Hash
SHA512 Hash
SHA384 Hash
SHA384 Hash
Text is not SVG - cannot display
\ No newline at end of file From edc2c8322ddbb4b8000145e12f3f260c52c715b2 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 19 Dec 2023 18:54:05 +0100 Subject: [PATCH 16/80] Add diagram for prefixed-signed message --- .../drawio/prefixed-signed-message.drawio | 63 +++++++++++++++++++ .../assets/drawio/prefixed-signed-message.svg | 3 + book/source/signing_data.md | 9 ++- 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 book/assets/drawio/prefixed-signed-message.drawio create mode 100644 book/assets/drawio/prefixed-signed-message.svg diff --git a/book/assets/drawio/prefixed-signed-message.drawio b/book/assets/drawio/prefixed-signed-message.drawio new file mode 100644 index 0000000..aea991e --- /dev/null +++ b/book/assets/drawio/prefixed-signed-message.drawio @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/book/assets/drawio/prefixed-signed-message.svg b/book/assets/drawio/prefixed-signed-message.svg new file mode 100644 index 0000000..1ee49bf --- /dev/null +++ b/book/assets/drawio/prefixed-signed-message.svg @@ -0,0 +1,3 @@ + + +
Literal Data
"Hello World!"
Literal Data...
Signature
Hash: SHA384
Issuer: B0B0
Signature...
Signature
Hash: SHA512
Issuer: B0B1
Signature...
"Hello World!" is hashed
"Hello World!" is hashed
SHA512 Hash
SHA512 Hash
SHA384 Hash
SHA384 Hash
Text is not SVG - cannot display
\ No newline at end of file diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 43cf0ed..4921348 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -76,7 +76,7 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi ```{figure} plain_svg/ops-signed-message.svg :name: fig-ops-signed-message -:alt: Depicts the structure of a one-pass-signed message. +:alt: Depicts the structure of a one-pass-signed message. Two one-pass-signatures lead the literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass-signatures is inspected in order to initiate the hashing procedure. The structure of a one-pass signed message. ``` @@ -126,6 +126,13 @@ In this format, the signature packets are stored ahead of the message itself: 2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. +```{figure} plain_svg/prefixed-signed-message.svg +:name: fig-prefixed-signed-message +:alt: Depicts the structure of a prefixed-signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. + +Structure of a prefixed-signed message. +``` + Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. For verification, this is equally convenient as the one-pass signed message form. From 8b02a7a474754afadc6ff275bb12561c0b7ec7fa Mon Sep 17 00:00:00 2001 From: "Tammi L. Coles" Date: Wed, 20 Dec 2023 09:42:36 +0000 Subject: [PATCH 17/80] Edits for KO attack section Reviewed-on: https://codeberg.org/openpgp/notes/pulls/254 Co-authored-by: Tammi L. Coles Co-committed-by: Tammi L. Coles --- book/source/adv/private_keys.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/book/source/adv/private_keys.md b/book/source/adv/private_keys.md index 319a914..a277d2d 100644 --- a/book/source/adv/private_keys.md +++ b/book/source/adv/private_keys.md @@ -67,15 +67,17 @@ In addition to key management, a keystore often involves various supplementary f OpenPGP is subject to specific vulnerabilities known as key overwriting (KO) attacks. These attacks exploit weaknesses in how encrypted private keys or their metadata are handled, potentially leading to the leakage of secret data when the key is used. The core issue lies in OpenPGP's handling of Secret-Key packets, where corruption of the non-encrypted fields can cause the unaltered private key material to be used with altered parameters. This mismatch can result in private key leakage. -Importantly, KO attacks are particularly relevant when an attacker is responsible for storing a user's encrypted private key. By altering the algorithm field in the Secret-Key packet, the attacker may cause the user to perform a cryptographic operation with a different algorithm. E.g., performing a DSA operation with ECC private key material. By observing the output of that attacker-corrupted operation, the attacker can recover the user's unencrypted private key material, even though the attacker had no direct access to it. +Importantly, KO attacks are particularly relevant in scenarios where an attacker has control over the storage of a user's encrypted private key. By manipulating the algorithm field in the Secret-Key packet, the attacker may lead the user to perform a cryptographic operation with a different algorithm. For example, the user might unknowingly perform a DSA operation with ECC private key material. Although the attacker does not have direct access to the encrypted private key material, the attacker can deduce and recover the user's unencrypted private key material by observing the output of this compromised operation. ### Mitigation -Understanding KO attacks is crucial due to their potential to compromise the integrity and confidentiality of encrypted communications, and the risk of complete private key material compromise. KO attacks highlight the necessity for robust key validation procedures and the dangers of storing keys in insecure environments. OpenPGP application developers should consider if this attack class is a concern in their applications. +Understanding KO attacks is crucial due to their potential to compromise the integrity and confidentiality of encrypted communications, and the risk of complete private key material compromise. KO attacks highlight the necessity for robust key validation procedures and the dangers of storing keys in insecure environments. OpenPGP application developers should conduct a risk assessment to determine the relevance of KO attacks to their applications. -Private keys that are protected with [S2K usage mode 253 (AEAD)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption), are not vulnerable to KO attacks. This mode ensures the integrity of the private key by using its unencrypted fields (including the algorithm field) as the *authentication tag* for integrity verification in the decryption process. When an attacker alters the unencrypted part of the packet, then decryption of the private key material will fail, and the user is prevented from e.g. accidentally using the key material with an altered attacker-controlled algorithm. +Private keys secured with [S2K usage mode 253 (AEAD)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption) are safeguarded against KO attacks. This mode ensures the integrity of the private key by using its unencrypted fields, including the algorithm field, as the *authentication tag* for integrity verification in the decryption process. -Note that while S2K usage mode 253 (AEAD) has been introduced in the OpenPGP version 6 specification, it can also be applied to OpenPGP version 4 key material (also see {ref}`migration-s2k`). +When an attacker alters the unencrypted part of the Secret-Key packet, then decryption of the private key material will fail. This effectively prevents the user from unknowingly using the key material with an altered attacker-controlled algorithm. + +Note that while S2K usage mode 253 (AEAD) has been introduced in the OpenPGP version 6 specification, it can also be applied to OpenPGP version 4 key material (see {ref}`migration-s2k`). #### Resources From 0ba4461f3b25dfb5751bbc54af079919fc01bd53 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 11:58:20 +0100 Subject: [PATCH 18/80] Normalize dash styling (Mirroring styling in c-r) --- book/source/signing_data.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 4921348..16e93fc 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -54,7 +54,7 @@ This method is commonly used for signing or encrypting emails. Most email softwa OpenPGP defines two variant forms of inline-signed messages: -1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier verify this format in one pass. +1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier can verify this format in one pass. 2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. [^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. @@ -76,7 +76,7 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi ```{figure} plain_svg/ops-signed-message.svg :name: fig-ops-signed-message -:alt: Depicts the structure of a one-pass-signed message. Two one-pass-signatures lead the literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass-signatures is inspected in order to initiate the hashing procedure. +:alt: Depicts the structure of a one-pass signed message. Two one-pass signatures lead the literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass signatures is inspected in order to initiate the hashing procedure. The structure of a one-pass signed message. ``` @@ -88,7 +88,7 @@ Instead, it's a type of auxiliary packet that can be used in conjunction with {t The position of the signature packet within the OpenPGP message is important for efficient data processing. The plaintext data might be large in size, and memory might be constrained. The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit the data to be signed while calculating the signature. The signature itself is therefore appended to the data. -The verifier on the other hand needs to know the hash algorithm used to calculate the signature before starting the verification process. As a consequence, either the producer would need to pass the plaintext data twice, once to calculate the signature and a second time to emit the signed data (the result is a prefixed-signed message), or the verifier needs to process (and cache) the whole OpenPGP message to reach the signature packets at the end in order to determine the hash algorithm, to then re-process the whole message, verifying the signature. +The verifier on the other hand needs to know the hash algorithm used to calculate the signature before starting the verification process. As a consequence, either the producer would need to pass the plaintext data twice, once to calculate the signature and a second time to emit the signed data (the result is a prefixed signed message), or the verifier needs to process (and cache) the whole OpenPGP message to reach the signature packets at the end in order to determine the hash algorithm, to then re-process the whole message, verifying the signature. The one-pass signature solves this issue, by allowing both the creation and verification of a signed message in a single pass. ``` @@ -116,7 +116,7 @@ Important to note, the {term}`signer`'s {term}`public key`, (prefixed-signature)= ### Prefixed signed message -A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass-signed and prefixed-signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. +A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. #### Structure @@ -128,9 +128,9 @@ In this format, the signature packets are stored ahead of the message itself: ```{figure} plain_svg/prefixed-signed-message.svg :name: fig-prefixed-signed-message -:alt: Depicts the structure of a prefixed-signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. +:alt: Depicts the structure of a prefixed signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. -Structure of a prefixed-signed message. +Structure of a prefixed signed message. ``` Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. From ad68dc83dad204f318b0feacec2ca25d9b5b0d24 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 14:28:08 +0100 Subject: [PATCH 19/80] Additional elaboration on one-pass signature packet --- book/source/signing_data.md | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 16e93fc..15b137b 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -85,14 +85,28 @@ The structure of a one-pass signed message. Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. - -The position of the signature packet within the OpenPGP message is important for efficient data processing. The plaintext data might be large in size, and memory might be constrained. -The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit the data to be signed while calculating the signature. The signature itself is therefore appended to the data. -The verifier on the other hand needs to know the hash algorithm used to calculate the signature before starting the verification process. As a consequence, either the producer would need to pass the plaintext data twice, once to calculate the signature and a second time to emit the signed data (the result is a prefixed signed message), or the verifier needs to process (and cache) the whole OpenPGP message to reach the signature packets at the end in order to determine the hash algorithm, to then re-process the whole message, verifying the signature. - -The one-pass signature solves this issue, by allowing both the creation and verification of a signed message in a single pass. ``` +#### The function of the one-pass signature packet + +To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when plaintext data is large and exceeds available memory in size. + +The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. + +The verifier, on the other hand, needs some information from the signature packet in order to perform the signature verification process. In particular, the verifier needs to know which hash algorithm was used to calculate the signature, in order to perform the same hashing operation on the message data. + +As a consequence, without a {term}`one-pass signature packet`, either: +- the producer would need to process the signed data twice: + - once to calculate the signature, and + - a second time to emit the signed data (the result is a prefixed signed message), or +- the verifier would need to process the OpenPGP message twice: + - once to read the signature packets at the end in order to determine the hash algorithm, and + - a second time to process the body of the message, and calculate the hash verifying the signature. + +The one-pass signature packet solves this issue, by allowing both the creation and verification of a signed message in a single pass. It effectively contains a copy of the data in a signature packet, but without the cryptographic signature data. + +The signer can easily emit this metadata before processing the full message, and for the verifier, this metadata enables processing of the message body. Both signer and verifier can efficiently generate or check a one-pass signed message. + #### Creation To produce an {term}`inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the plaintext data, emitting it as a {term}`literal data` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. From 7d756c77ee527dc83c71a6b828059adb98e42eef Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 15:20:21 +0100 Subject: [PATCH 20/80] Shift away from "plaintext" term for the signed data Talking about "plaintext" seems potentially confusing, especially when signing an encrypted message. --- book/source/signing_data.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 15b137b..a7ac8e1 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -35,7 +35,7 @@ Note that {term}`data signatures` are distinct from [](/signing_ - **{term}`Detached`**: The OpenPGP signature exists as a separate entity, independent of the signed data. - **{term}`Inline`**: Both the original data and its corresponding {term}`OpenPGP signature` are encapsulated within an {term}`OpenPGP message`. -- **{term}`Cleartext signature`**: A plaintext message and its {term}`OpenPGP signature` coexist in a combined text format, preserving the readability of the original message. +- **{term}`Cleartext signature`**: A plain text message and its {term}`OpenPGP signature` coexist in a combined text format, preserving the readability of the original message. [^sign-modes-gpg]: These three forms of {term}`signature` application align with GnuPG's `--detach-sign`, `--sign`, and `--clearsign` command options. @@ -89,7 +89,7 @@ Instead, it's a type of auxiliary packet that can be used in conjunction with {t #### The function of the one-pass signature packet -To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when plaintext data is large and exceeds available memory in size. +To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when signed data is large and exceeds available memory in size. The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. @@ -109,7 +109,7 @@ The signer can easily emit this metadata before processing the full message, and #### Creation -To produce an {term}`inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the plaintext data, emitting it as a {term}`literal data` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. +To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed data, emitting it as a {term}`literal data` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. For efficient {term}`verification`, an application must understand how to handle the {term}`literal data` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in only a single pass. From 7bd0e5599ec1fd57de1e51433ed67c58bf322250 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 18:09:36 +0100 Subject: [PATCH 21/80] Add glossary entries about OpenPGP messages, to generalize the data signatures chapter --- book/source/glossary.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index e804683..28eec83 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -112,6 +112,9 @@ Component Component Key See {term}`OpenPGP Component Key`. +Compressed Data Packet + A {term}`packet` that contains compressed data. It represents a "compressed message". The uncompressed data in turn consists of an {term}`OpenPGP message`, made up of a series of {term}`packets`. + Compression See {term}`Data Compression`. @@ -293,7 +296,7 @@ Life-cycle Management See [](self-signatures). Literal Data Packet - A {term}`packet` in a {term}`Data Signature` which contains data, that has been signed using a {term}`cryptographic signature`. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. + A {term}`packet` which contains a payload of data. It represents a "literal message". A literal data packet can for example store data that has been signed using a {term}`cryptographic signature`. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. MAC See {term}`Message Authentication Code`. @@ -333,6 +336,9 @@ OpenPGP Certificate OpenPGP Component Key An {term}`OpenPGP Primary Key` or {term}`OpenPGP Subkey`. For an in-depth discussion see [](component-keys). +OpenPGP data + Any data in OpenPGP format, represented as a series of OpenPGP packets. The data could for example represent an {term}`OpenPGP Certificate`, or an {term}`OpenPGP Signature Packet` combined with plaintext or encrypted data. + OpenPGP Fingerprint An OpenPGP Fingerprint is a shorthand representation of an {term}`OpenPGP Component Key`. Fingerprints effectively act as unique identifiers. See [](fingerprint). @@ -345,7 +351,14 @@ OpenPGP Key Used either for an {term}`OpenPGP Certificate` (containing public key material and metadata), or for an {term}`OpenPGP Private Key`. See [](/certificates) for an in-depth discussion. OpenPGP Message - A data structure, which contains OpenPGP components such as {term}`OpenPGP Certificate` or {term}`OpenPGP Signature Packet` and plaintext or encrypted data. + A series of OpenPGP packets that represents one of the following formats: + + - an encrypted message + - a signed message + - a {term}`compressed message` + - a {term}`literal message` + + Also see [RFC 10.3](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages). OpenPGP Public Key See {term}`OpenPGP Certificate`. From c4d1d05be92b01c8e15127278b62c15ccdfa36d4 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 19:55:05 +0100 Subject: [PATCH 22/80] Generalize the text: the data that gets signed in an OpenPGP message, not necessarily a literal data packet --- book/source/signing_data.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/book/source/signing_data.md b/book/source/signing_data.md index a7ac8e1..3c0a866 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -70,13 +70,13 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi 1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. -2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed could for example consist of a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. ```{figure} plain_svg/ops-signed-message.svg :name: fig-ops-signed-message -:alt: Depicts the structure of a one-pass signed message. Two one-pass signatures lead the literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass signatures is inspected in order to initiate the hashing procedure. +:alt: Depicts the structure of a one-pass signed message. Two one-pass signatures lead a literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass signatures is inspected in order to initiate the hashing procedure. The structure of a one-pass signed message. ``` @@ -109,9 +109,9 @@ The signer can easily emit this metadata before processing the full message, and #### Creation -To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed data, emitting it as a {term}`literal data` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. +To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed message, emitting it as a series of one or more {term}`packets` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. -For efficient {term}`verification`, an application must understand how to handle the {term}`literal data` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in only a single pass. +For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. @@ -121,7 +121,7 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin 1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. -2. **Processing the {term}`literal data packet`**: This step involves {term}`hashing` the literal data, preparing it for {term}`signature` {term}`verification`. +2. **Processing the {term}`OpenPGP message`**: This step involves {term}`hashing` its data, preparing it for {term}`signature` {term}`verification`. 3. **{term}`Verifying` {term}`signature packets`**: Located at the end of the message, these {term}`packets` are checked against the previously calculated {term}`hash digest`. @@ -138,7 +138,7 @@ In this format, the signature packets are stored ahead of the message itself: 1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. -2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. ```{figure} plain_svg/prefixed-signed-message.svg :name: fig-prefixed-signed-message From 0c41b6c67b6ea5209db3c981f43da459a38df378 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:20:50 +0100 Subject: [PATCH 23/80] Clarify asymmetric cryptography and its use in OpenPGP --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 76d7fed..fe3f25a 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -20,7 +20,7 @@ Algorithm Preferences See [](recipe-algorithm-preferences). Asymmetric Cryptography - Asymmetric cryptography is used in OpenPGP. For a more detailed discussion see [](public-key-cryptography). + Asymmetric cryptography (also known as public-key cryptography) is used in OpenPGP to send messages without using a prior shared secret. For a more detailed discussion see [](public-key-cryptography). Authenticated Encryption With Associated Data Short AEAD, refers to an encryption scheme that ensures confidentiality of a message. Additionally, additional data, which is not confidential, may be associated with the message. From 090e4d8f5029fbf5e56779cfb5f36737cc2a8b34 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:21:21 +0100 Subject: [PATCH 24/80] AEAD: Clarify integrity properties --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index fe3f25a..577b19b 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -23,7 +23,7 @@ Asymmetric Cryptography Asymmetric cryptography (also known as public-key cryptography) is used in OpenPGP to send messages without using a prior shared secret. For a more detailed discussion see [](public-key-cryptography). Authenticated Encryption With Associated Data - Short AEAD, refers to an encryption scheme that ensures confidentiality of a message. Additionally, additional data, which is not confidential, may be associated with the message. + Short AEAD, refers to an encryption scheme that ensures confidentiality of a message. Additionally, additional data, which is not confidential, may be associated with the message, ensuring integrity of both the confidential part of the message, as well as the additional data. See Wikipedia on [Authenticated Encryption](https://en.wikipedia.org/wiki/Authenticated_encryption). From b0363a09458d1b7c4b1f5b701f655f83afed8f5e Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:21:47 +0100 Subject: [PATCH 25/80] Clarify authentication key flag --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 577b19b..304fd70 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -32,7 +32,7 @@ Authentication The term "authentication" here is semantically different from the one used in {term}`Authentication Key Flag`. Authentication Key Flag - A {term}`Key Flag`, which indicates that a {term}`Component Key` can be used to confirm control over {term}`private key material` against a remote system. The term "authentication" here is semantically different from {term}`Authentication`. See [](key-flags). + A {term}`Key Flag`, which indicates that a {term}`Component Key` can be used to confirm control over {term}`private key material` against a remote system. This is typically done to perform an authorative action, like logging into a system. The term "authentication" here is semantically different from {term}`Authentication`. See [](key-flags). Authentication Tag See {term}`Message Authentication Code`. From 020665947f708f62b4a823e85649cb4394881a79 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:22:13 +0100 Subject: [PATCH 26/80] Add that the holder is typically the owner of a cert --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 304fd70..e8ba2b5 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -69,7 +69,7 @@ Certificate Authority See {term}`Certification Authority` Certificate Holder - A person or other entity, that holds an {term}`Transferable Secret Key` and thus is able to modify the accompanying {term}`OpenPGP Certificate`. + A person or other entity, that holds an {term}`Transferable Secret Key` and thus is able to modify the accompanying {term}`OpenPGP Certificate`. Typically this is the owner of {term}`OpenPGP key`. Certification A certification, in OpenPGP, is a signature that makes a statement about an {term}`identity` in a {term}`certificate`, or an entire {term}`certificate`. From dabd87e1978b9228202dacf9c159985edd43eb0c Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:22:29 +0100 Subject: [PATCH 27/80] Upper case --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index e8ba2b5..44d2ecf 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -90,7 +90,7 @@ Certification Revocation Signature Packet Certification Signature See {term}`Certification`. -Certifying Self-signature +Certifying Self-Signature An {term}`OpenPGP Signature Packet` by the {term}`Certificate Holder` on an {term}`Identity Component` of their own {term}`Certificate`. Certifying Signature From 140a5fae5c4874b2f219b924bb26d5be5d7fd564 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:22:42 +0100 Subject: [PATCH 28/80] Add entry for Compressed Data Packet --- book/source/glossary.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index 44d2ecf..7e14be2 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -112,6 +112,9 @@ Component Component Key See {term}`OpenPGP Component Key`. +Compressed Data Packet + A packet containing a compressed {term}`OpenPGP Message` (typically a {term}`Literal Data Packet`). + Compression See {term}`Data Compression`. From f0e49b52a4108c27c0ebe21b7115e4712643cc12 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:23:15 +0100 Subject: [PATCH 29/80] Creation Time: Clarify that it also applies to signatures --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 7e14be2..d653c0b 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -119,7 +119,7 @@ Compression See {term}`Data Compression`. Creation Time - The point in time at which e.g. an {term}`OpenPGP Certificate`, or one of its {term}`component` is created. + The point in time at which e.g. an {term}`OpenPGP Signature`, an {term}`OpenPGP Certificate`, or one of its {term}`component` is created. Creator See {term}`Issuer`. From 15e0b23f1682fd6056435498b10eb7a8ba4f2363 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:23:40 +0100 Subject: [PATCH 30/80] Clarify criticality some more --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index d653c0b..cd3b105 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -125,7 +125,7 @@ Creator See {term}`Issuer`. Criticality Flag - A flag on {term}`Subpacket`s, that defines their criticality, which is used for validation. See [](criticality-of-subpackets). + A flag on {term}`Subpacket`s, that can mark them as critical or non-critical, which is has an influence on signature validation. See [](criticality-of-subpackets). Cryptographic Key A {term}`symmetric` or {term}`asymmetric` cryptographic key is used for signing and encryption operations. See [](cryptography). From 68082c2fcefdeb9aa630a87528f6c4b72a427479 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:24:22 +0100 Subject: [PATCH 31/80] Clarify that a cryptographic signature is 'raw' --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index cd3b105..9e838db 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -131,7 +131,7 @@ Cryptographic Key A {term}`symmetric` or {term}`asymmetric` cryptographic key is used for signing and encryption operations. See [](cryptography). Cryptographic Signature - A raw cryptographic signature is a sequence of bytes created by a {term}`Cryptographic Key`. + A raw cryptographic signature is an algorithm-specific sequence of bytes created by a {term}`Cryptographic Key`. CTB See {term}`Cipher Type Byte`. From 2302f51fb29c18be2f9d57e0e4425fb181dc6b55 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:25:08 +0100 Subject: [PATCH 32/80] Detached signatures may not always be (for) files --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 9e838db..a2eb895 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -154,7 +154,7 @@ Delegation This kind of delegation involves {term}`certifications` that include the {term}`trust signature` subpacket. Detached Signature - A {term}`Data Signature` which exists as a separate file to the file it was created for. See [](forms-of-data-signatures). + A {term}`Data Signature` which exists separately to the data it was created for. See [](forms-of-data-signatures). Direct Key Signature A {term}`Signature` that sets preferences and advertises {term}`features` applicable to an entire {term}`Certificate`. See [](direct-key-signature). From 7445a15bfa7f876cb8f18e24fd69a1957e0934c1 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:25:42 +0100 Subject: [PATCH 33/80] Clarify Direct-Key Sig is both a signature packet as well as a type --- book/source/glossary.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index a2eb895..7f75c07 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -157,7 +157,9 @@ Detached Signature A {term}`Data Signature` which exists separately to the data it was created for. See [](forms-of-data-signatures). Direct Key Signature - A {term}`Signature` that sets preferences and advertises {term}`features` applicable to an entire {term}`Certificate`. See [](direct-key-signature). + Describes both a {term}`Signature Type ID`, as well as an according {term}`OpenPGP Signature` over a {term}`Primary Key`. + + Issued as a {term}`Self-Signature` it sets preferences and advertises {term}`features` applicable to an entire {term}`Certificate`. See [](direct-key-signature). Embedded Signature Subpacket An {term}`OpenPGP Signature Subpacket` which contains a complete {term}`OpenPGP Signature Packet`. From d385a916fa12d9d5d31775f4a15dcab4d7baf6e1 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:25:59 +0100 Subject: [PATCH 34/80] Add entry for Encrypted Data --- book/source/glossary.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index 7f75c07..dc23a57 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -166,6 +166,11 @@ Embedded Signature Subpacket See [RFC 5.2.3.34](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-embedded-signature) +Encrypted Data + Data that is encrypted. + + See [](/encryption.html). + Encryption Key Flag A {term}`Key Flag`, indicating that a {term}`Component Key` can be used for encrypting data. See [](key-flags). From 6edb9f5b52453f34cdd7db68d1970973ff49ff9e Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:26:14 +0100 Subject: [PATCH 35/80] Clarify there are two encryption key flags --- book/source/glossary.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index dc23a57..7ba86b8 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -174,6 +174,8 @@ Encrypted Data Encryption Key Flag A {term}`Key Flag`, indicating that a {term}`Component Key` can be used for encrypting data. See [](key-flags). + There are two distinct encryption key flags, indicating that the key can encrypt communications, or data in long-term storage respectively. + Expiration A mechanism by which a {term}`Component` is invalidated due to the {term}`Expiration Time` of its {term}`binding signature` being older than the {term}`Reference Time` by which it is validated. From 9df63ba00aead94667ff7fd37bfd4adf88711952 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:26:34 +0100 Subject: [PATCH 36/80] s/A/An --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 7ba86b8..5994e9e 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -183,7 +183,7 @@ Expiration Time The time of expiry of an {term}`OpenPGP Signature Packet`. Features Subpacket - A {term}`OpenPGP Signature Subpacket`, which denotes advanced OpenPGP features an {term}`implementation` supports. + An {term}`OpenPGP Signature Subpacket`, which denotes advanced OpenPGP features an {term}`implementation` supports. For an in-depth view on these {term}`subpackets` see [](zoom-dks). From 5a4b3add35d65d8eb5e9c8a419092062d338949a Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:26:53 +0100 Subject: [PATCH 37/80] Add alias 'Hash Value' --- book/source/glossary.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index 5994e9e..2a6baa6 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -208,6 +208,9 @@ Hash Digest Hash Function A function used to map data of arbitrary size to fixed-size values (see {term}`Hash Digest`). +Hash Value + See {term}`Hash Digest`. + Hashed Area An area in an {term}`OpenPGP Signature Packet` containing {term}`OpenPGP Signature Subpacket`s, that is covered by the {term}`Hash Digest` a {term}`Cryptographic Signature` is created for. See [](subpacket-areas). From c5dbc29f5159ae882e79ba80032509497f99d828 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:27:28 +0100 Subject: [PATCH 38/80] Identities are not only certified by third-parties --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 2a6baa6..58900f2 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -221,7 +221,7 @@ Hybrid Cryptosystem A cryptographic system that employs both {term}`Asymmetric Cryptography` and {term}`Symmetric Cryptography`. See [](hybrid-cryptosystems). Identity - An identity of a {term}`Certificate Holder`. It is represented by an {term}`Identity Component`, which may be certified using {term}`third-party identity certifications`, or by a {term}`Notation`. + An identity of a {term}`Certificate Holder`. It is represented by an {term}`Identity Component`, which may be certified using {term}`identity certifications`, or by a {term}`Notation`. Identity Certification An {term}`OpenPGP Signature Packet` on an {term}`Identity Component` which {term}`certifies` its {term}`authenticity`. From 0f53a1e8a6ec9d9d68c71ae848a34944a98c23b9 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:27:47 +0100 Subject: [PATCH 39/80] s/a/an --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 58900f2..f87bd6c 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -242,7 +242,7 @@ Inline Signature A {term}`Data Signature` which exists encapsulated alongside the data it was created for in an OpenPGP container. See [](forms-of-data-signatures). Issuer - An entity, that created an {term}`OpenPGP Signature Packet` using an {term}`Transferable Secret Key`. + An entity, that created an {term}`OpenPGP Signature Packet` using a {term}`Transferable Secret Key`. Issuer Fingerprint Subpacket A {term}`Subpacket` specifying the {term}`Fingerprint` of an {term}`Issuer Key`. From 0737cefd2f462c5eed20cd93b3861516669b19f3 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:28:05 +0100 Subject: [PATCH 40/80] Key Expiration Time is not for Signatures --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index f87bd6c..40846dc 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -268,7 +268,7 @@ Key - {term}`OpenPGP key` (which in turn refers to either an {term}`OpenPGP Certificate` or a {term}`Transferable Secret Key` Key Expiration Time Subpacket - An {term}`OpenPGP Signature Subpacket Type` which defines the {term}`Expiration Time` for an {term}`OpenPGP Signature Packet` on a {term}`key`. + An {term}`OpenPGP Signature Subpacket Type` which defines the {term}`Expiration Time` for a {term}`key`. See [RFC 5.2.3.13](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-expiration-time) From 0e24b045ffca5095397a5750578d8476790fc95a Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:28:22 +0100 Subject: [PATCH 41/80] Key Servers are services --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 40846dc..0b55967 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -292,7 +292,7 @@ Key Revocation Signature Packet A {term}`Revocation Self-signature` for an entire {term}`OpenPGP Certificate`. Key Server - A piece of software available over the network, which provides access to {term}`OpenPGP Certificates` e.g., by searching for an {term}`OpenPGP Fingerprint` or {term}`User ID`, via the `HKP` and/ or `HKPS` protocols. + A service available over the network, which provides access to {term}`OpenPGP Certificates` e.g., by searching for an {term}`OpenPGP Fingerprint` or {term}`User ID`, via the `HKP` and/ or `HKPS` protocols. Several implementations such as [hagrid](https://gitlab.com/keys.openpgp.org/hagrid/), or [hockeypuck](https://github.com/hockeypuck/hockeypuck) exist. Life-cycle Management From 9bc2927f0fee863f8d9b4ca14fa721e2dae98ce3 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:28:43 +0100 Subject: [PATCH 42/80] Literal Data Packets are not Signautre Packets --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 0b55967..c501965 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -301,7 +301,7 @@ Life-cycle Management See [](self-signatures). Literal Data Packet - A {term}`packet` in a {term}`Data Signature` which contains data, that has been signed using a {term}`cryptographic signature`. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. + A packet which contains the plaintext data of an encrypted and/or signed message. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. MAC See {term}`Message Authentication Code`. From bc7f63c4e2a2bf0dae6a3451b2081c5928261893 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:28:58 +0100 Subject: [PATCH 43/80] Clarify meta-introducer --- book/source/glossary.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index c501965..f48826e 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -315,6 +315,8 @@ Message Authentication Code Meta-Introducer An {term}`OpenPGP Certificate` with a {term}`Trust Depth` greater than one. + A meta-introducer can introduce other (meta-) introducers. + Metadata Data related to preferences of an {term}`OpenPGP Certificate` or its {term}`Certificate Holder`, that can be found in {term}`signature` {term}`packets`. See [](metadata-in-certificates). From 78a8677a54deee7bf8c5a50348860780e1177c21 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:29:29 +0100 Subject: [PATCH 44/80] An OpenPGP message does not contain certificates, but literal, encrypted, compressed or signed data --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index f48826e..0a0f1cd 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -350,7 +350,7 @@ OpenPGP Key Used either for an {term}`OpenPGP Certificate` (containing public key material and metadata), or for an {term}`OpenPGP Private Key`. See [](/certificates) for an in-depth discussion. OpenPGP Message - A data structure, which contains OpenPGP components such as {term}`OpenPGP Certificate` or {term}`OpenPGP Signature Packet` and plaintext or encrypted data. + A data structure, which contains OpenPGP packets, such as {term}`literal`, {term}`compressed`, {term}`encrypted` or {term}`signed` data. OpenPGP Public Key See {term}`OpenPGP Certificate`. From 920ab3c9b93a462d233754ef5efafc3a91f83a75 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:30:10 +0100 Subject: [PATCH 45/80] Packets are not exclusively used for Certificates --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 0a0f1cd..73e0382 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -386,7 +386,7 @@ Owner See {term}`Certificate Holder`. Packet - An element in an {term}`OpenPGP Certificate`, which represents {term}`components` or {term}`signatures`. + An element in an {term}`OpenPGP Certificate` or {term}`OpenPGP Message`. Packet Header A section of variable length at the beginning of a {term}`Packet`, which encodes for example the {term}`Packet Type ID`. See the relevant [section in the RFC](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-packet-headers), which explains this section in more detail. From ec1278628d6fd33fadf53689f276543dc04f6846 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:30:46 +0100 Subject: [PATCH 46/80] Clarify preferences are for certificates or subkeys --- book/source/glossary.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 73e0382..f95fb15 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -403,22 +403,22 @@ Positive Certification See [](bind-identity). Preferred Compression Algorithms Subpacket - An {term}`OpenPGP Signature Subpacket Type` which defines the preferred {term}`compression algorithms` for an {term}`OpenPGP Signature Packet`. This defines which {term}`algorithms` the {term}`key holder` prefers to use. + An {term}`OpenPGP Signature Subpacket Type` which defines the preferred {term}`compression algorithms` for an {term}`OpenPGP Certificate` or {term}`Component Key`. This defines which {term}`algorithms` the {term}`key holder` prefers to receive. See [RFC 5.2.3.17](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-compression-algor). Preferred Hash Algorithms Subpacket - An {term}`OpenPGP Signature Subpacket Type` which defines the preferred {term}`hash algorithm` for an {term}`OpenPGP Signature Packet`. This defines which algorithms the {term}`key holder` prefers to receive. + An {term}`OpenPGP Signature Subpacket Type` which defines the preferred {term}`hash algorithm` for an {term}`OpenPGP Certificate` or {term}`Component Key`. This defines which algorithms the {term}`key holder` prefers to receive. See [RFC 5.2.3.16](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-hash-algorithms). Preferred Symmetric Ciphers for v1 SEIPD Subpacket - An {term}`OpenPGP Signature Subpacket Type` which defines the preferred version 1 {term}`SEIPD` algorithms for an {term}`OpenPGP Signature Packet`. This defines which algorithms the {term}`key holder` prefers to receive and implicitly signifies the supported algorithms of the {term}`key holder`'s {term}`implementation`. + An {term}`OpenPGP Signature Subpacket Type` which defines the preferred version 1 {term}`SEIPD` algorithms for an {term}`OpenPGP Certificate` or {term}`Component Key`. This defines which algorithms the {term}`key holder` prefers to receive and implicitly signifies the supported algorithms of the {term}`key holder`'s {term}`implementation`. See [RFC 5.2.3.14](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-symmetric-ciphers). Preferred AEAD Ciphersuites Subpacket - An {term}`OpenPGP Signature Subpacket Type` which defines the preferred version 2 {term}`SEIPD` algorithms for an {term}`OpenPGP Signature Packet`. This defines which algorithms the {term}`key holder` prefers to receive and implicitly signifies the supported algorithms of the {term}`key holder`'s {term}`implementation`. + An {term}`OpenPGP Signature Subpacket Type` which defines the preferred version 2 {term}`SEIPD` algorithms for an {term}`OpenPGP Certificate` or {term}`Component Key`. This defines which algorithms the {term}`key holder` prefers to receive and implicitly signifies the supported algorithms of the {term}`key holder`'s {term}`implementation`. See [RFC 5.2.3.15](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-preferred-aead-ciphersuites) From ecaa4a1299ad06bb01af85d7983132c4e6af9b42 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:31:04 +0100 Subject: [PATCH 47/80] Reference time is for certificate or signature evaluation --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index f95fb15..71fe528 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -478,7 +478,7 @@ Reason For Revocation Subpacket See [RFC 5.2.3.31](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) Reference Time - A point in time at which an {term}`OpenPGP Certificate` is evaluated. + A point in time at which an {term}`OpenPGP Certificate` or {term}`OpenPGP Signature` is evaluated. Regular Expression Subpacket An {term}`OpenPGP Signature Subpacket` which allows for limiting {term}`delegations` to {term}`identities` matching a regular expression. From 08fedd32d8a3f8a21e043f399b0464ded4c03e26 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:31:28 +0100 Subject: [PATCH 48/80] Third-party identity certifications certify identity claims --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 71fe528..08794e4 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -626,7 +626,7 @@ Text Signature A {term}`signature packet` with the {term}`Signature Type ID` `0x01`, which is used for textual data. Third-party Identity Certification - {term}`Certification` by third-parties to confirm ownership of an {term}`OpenPGP Certificate` by a {term}`Certificate Holder`. See [](third-party-identity-certifications). + {term}`Certification` by third-parties to confirm ownership of an {term}`OpenPGP Certificate` ({term}`Identity Claim`) by a {term}`Certificate Holder`. See [](third-party-identity-certifications). Third-party Signature A {term}`Signature` by a third-party on a {term}`Component` of a {term}`Certificate`. From d3cdbd43668b1f4481aa8271701b673f07e031a8 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:31:47 +0100 Subject: [PATCH 49/80] Clarify User-Attributes contain complex data --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 08794e4..a422284 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -684,7 +684,7 @@ Unhashed Subpacket A {term}`Signature Subpacket` residing in the {term}`Unhashed Area` of a {term}`Signature Packet`. User Attribute - An {term}`Identity Component`, which may hold a single JPEG image. See [](user-attributes). + An {term}`Identity Component`, which may hold complex attribute data, e.g. a single JPEG image. See [](user-attributes). User ID An {term}`Identity Component`, which describes an {term}`Identity` of a {term}`Certificate Holder`. See [](user-ids). From e4b5c4d64b00782ab24e69cb58ad7cc853ae16c0 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:32:08 +0100 Subject: [PATCH 50/80] Remove specifics from Cryptographic Key --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index a422284..f2812b9 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -128,7 +128,7 @@ Criticality Flag A flag on {term}`Subpacket`s, that can mark them as critical or non-critical, which is has an influence on signature validation. See [](criticality-of-subpackets). Cryptographic Key - A {term}`symmetric` or {term}`asymmetric` cryptographic key is used for signing and encryption operations. See [](cryptography). + A {term}`symmetric` or {term}`asymmetric` cryptographic key. See [](cryptography). Cryptographic Signature A raw cryptographic signature is an algorithm-specific sequence of bytes created by a {term}`Cryptographic Key`. From ebc7530cdb3f82c9906dbc1d501adf6268417ae7 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 21 Dec 2023 15:33:07 +0100 Subject: [PATCH 51/80] Fix link --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index f2812b9..d1bad65 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -169,7 +169,7 @@ Embedded Signature Subpacket Encrypted Data Data that is encrypted. - See [](/encryption.html). + See [](/encryption). Encryption Key Flag A {term}`Key Flag`, indicating that a {term}`Component Key` can be used for encrypting data. See [](key-flags). From 6820d60661ae096963c6ecacc1921b909625d93b Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:02:28 +0100 Subject: [PATCH 52/80] Identity certifications can be both self-signatures or third-party --- book/source/glossary.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/book/source/glossary.md b/book/source/glossary.md index d1bad65..e84c2ec 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -225,6 +225,10 @@ Identity Identity Certification An {term}`OpenPGP Signature Packet` on an {term}`Identity Component` which {term}`certifies` its {term}`authenticity`. + + Identity certifications can be issued either: + - by the certificate holder, as a {term}`self-signature`, or + - by a third party, as a {term}`third-party identity certifications`. Identity Claim A {term}`Certificate Holder` may use {term}`Identity Components` or {term}`Notations` to state a claim about their {term}`Identity`. From cf169edaf68d3f8da71810bcd6077f5236c538be Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:06:02 +0100 Subject: [PATCH 53/80] Add link --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index e84c2ec..4e8363e 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -305,7 +305,7 @@ Life-cycle Management See [](self-signatures). Literal Data Packet - A packet which contains the plaintext data of an encrypted and/or signed message. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. + A {term}`packet` which contains the plaintext data of an encrypted and/or signed message. See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit) for more details. MAC See {term}`Message Authentication Code`. From 54bb1927c1781062e8743683ee039a595defb885 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:14:09 +0100 Subject: [PATCH 54/80] Link "Trusted introducer" from "Meta Introducer" --- book/source/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 4e8363e..66b8adc 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -317,9 +317,9 @@ Message Authentication Code A piece of information used for integrity and {term}`authenticity` verification of a message. See [](message-authentication-code). Meta-Introducer - An {term}`OpenPGP Certificate` with a {term}`Trust Depth` greater than one. + An {term}`OpenPGP Certificate` that acts as a {term}`Trusted introducer` and has a {term}`Trust Depth` greater than one. - A meta-introducer can introduce other (meta-) introducers. + A meta-introducer can introduce other (meta-) {term}`introducers`. Metadata Data related to preferences of an {term}`OpenPGP Certificate` or its {term}`Certificate Holder`, that can be found in {term}`signature` {term}`packets`. See [](metadata-in-certificates). From e0c99b21a15cf63e36cd422af94800477a39cff0 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:16:04 +0100 Subject: [PATCH 55/80] Adjust styling of "Meta Introducer" to the RFC (no dash) --- book/source/glossary.md | 4 ++-- book/source/signing_components.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 66b8adc..d3e07e5 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -316,10 +316,10 @@ Master Key Message Authentication Code A piece of information used for integrity and {term}`authenticity` verification of a message. See [](message-authentication-code). -Meta-Introducer +Meta Introducer An {term}`OpenPGP Certificate` that acts as a {term}`Trusted introducer` and has a {term}`Trust Depth` greater than one. - A meta-introducer can introduce other (meta-) {term}`introducers`. + A meta introducer can introduce other (meta-) {term}`introducers`. Metadata Data related to preferences of an {term}`OpenPGP Certificate` or its {term}`Certificate Holder`, that can be found in {term}`signature` {term}`packets`. See [](metadata-in-certificates). diff --git a/book/source/signing_components.md b/book/source/signing_components.md index 0e24ed9..c7d4286 100644 --- a/book/source/signing_components.md +++ b/book/source/signing_components.md @@ -241,7 +241,7 @@ OpenPGP uses [*trust signature*](https://www.ietf.org/archive/id/draft-ietf-open (trust-level)= #### Trust depth/level -The "{term}`trust depth`" (or {term}`level`) in OpenPGP signifies the extent of transitive {term}`delegation` within the {term}`authentication` process. It determines how far a {term}`delegation` can be extended from the original {term}`trusted introducer` to subsequent intermediaries. Essentially, a {term}`certificate` with a {term}`trust depth` of more than one acts as a "{term}`meta-introducer`," facilitating {term}`authentication` decisions across multiple levels in the network. +The "{term}`trust depth`" (or {term}`level`) in OpenPGP signifies the extent of transitive {term}`delegation` within the {term}`authentication` process. It determines how far a {term}`delegation` can be extended from the original {term}`trusted introducer` to subsequent intermediaries. Essentially, a {term}`certificate` with a {term}`trust depth` of more than one acts as a "{term}`meta introducer`," facilitating {term}`authentication` decisions across multiple levels in the network. A {term}`trust depth` of 1 means relying on {term}`certifications` made directly by the {term}`trusted introducer`. The user's OpenPGP software will accept {term}`certifications` made directly by the {term}`introducer` for {term}`authenticating` identities. From c6a020d8f7935608691d724bf64be8981a06a5f6 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:31:00 +0100 Subject: [PATCH 56/80] Normalize link syntax --- book/source/glossary.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index d3e07e5..ae47e74 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -49,12 +49,12 @@ Binary Signature Binding The process of creating a {term}`Binding Signature` for a {term}`Component`, or the resulting {term}`Binding Signature`. - See {ref}`binding-signatures` for more. + See [](binding-signatures) for more. Binding Signature A {term}`self-signature` on a {term}`component` which associates that {term}`component` to the issuing {term}`component key` in a {term}`certificate`. - See {ref}`binding-signatures` for more. + See [](binding-signatures) for more. CA See {term}`Certification Authority`. @@ -670,7 +670,7 @@ Trust Signature Trusted introducer OpenPGP users can choose to rely on {term}`certifications` issued by a third party. The remote party of such a {term}`delegation` is called a "trusted introducer". - See {ref}`delegation` for more details. + See [](delegation) for more details. TSK See {term}`Transferable Secret Key`. From 8865cbf0e116aec4e01e15195acb6da89ccb07a5 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 15:40:05 +0100 Subject: [PATCH 57/80] Expand on "Authentication Key Flag" --- book/source/glossary.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index ae47e74..c0a3bd5 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -32,7 +32,9 @@ Authentication The term "authentication" here is semantically different from the one used in {term}`Authentication Key Flag`. Authentication Key Flag - A {term}`Key Flag`, which indicates that a {term}`Component Key` can be used to confirm control over {term}`private key material` against a remote system. This is typically done to perform an authorative action, like logging into a system. The term "authentication" here is semantically different from {term}`Authentication`. See [](key-flags). + A {term}`Key Flag` which indicates that a {term}`Component Key` can be used to prove control over {term}`private key material` with a challenge-response mechanism. This is typically done to log into a remote system, often using the OpenSSH protocol. + + Note that the term "authentication" is used in a different context here than {term}`Authentication` of {term}`identity claims` that are associated with a {term}`certificate`. See [](key-flags). Authentication Tag See {term}`Message Authentication Code`. From ffa24596a4e77f25a27df3c12c7fcb350a00ccde Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 20 Dec 2023 10:55:51 +0100 Subject: [PATCH 58/80] Optimize away additional glossary hop --- book/source/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index c0a3bd5..40c2fa3 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -574,7 +574,7 @@ Signature Type See {term}`OpenPGP Signature Type`. Signature Type ID - A numerical identifier for a {term}`Signature Type`. + A numerical identifier for a {term}`Signature Type`. Signature Verification In cryptography the mechanism of verification relates to a process in which a claim (i.e., a {term}`signature`) is tested (i.e., using the relevant {term}`components` of a {term}`certificate`). From ecf0bc1c7b49fa8976d2671a80b6a0d21ac3940d Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 22 Dec 2023 19:39:04 +0100 Subject: [PATCH 59/80] Move technical details about inline signatures into the "advanced" chapter --- book/source/adv/signing_data.md | 113 +++++++++++++++++++++++++++++++- book/source/signing_data.md | 104 +---------------------------- 2 files changed, 112 insertions(+), 105 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index f031233..d89250e 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -5,6 +5,115 @@ SPDX-License-Identifier: CC-BY-SA-4.0 # Advanced material: Signatures over data +(adv-inline-signature)= +## Internals of inline signed messages + +Inline-signed messages are one of the forms of [OpenPGP data signatures](forms-of-data-signatures). An {term}`inline-signed message ` joins the signed data and its corresponding {term}`data signature` into a single {term}`OpenPGP message`. + +OpenPGP defines two variant forms of inline-signed messages: + +1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier can verify this format in one pass. +2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. + +[^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. + +(one-pass-signature)= +### One-pass signed message + +This is the commonly used format for inline signed messages. + +#### Structure + +A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: + +1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. + +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed could, for example, consist of a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. + +3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. + +```{figure} ../plain_svg/ops-signed-message.svg +:name: fig-ops-signed-message +:alt: Depicts the structure of a one-pass signed message. Two one-pass signatures lead a literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass signatures is inspected in order to initiate the hashing procedure. + +The structure of a one-pass signed message. +``` + +```{note} +Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. + +Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. +``` + +#### The function of the one-pass signature packet + +To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when signed data is large and exceeds available memory in size. + +The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. + +The verifier, on the other hand, needs some information from the signature packet in order to perform the signature verification process. In particular, the verifier needs to know which hash algorithm was used to calculate the signature, in order to perform the same hashing operation on the message data. + +As a consequence, without a {term}`one-pass signature packet`, either: +- the producer would need to process the signed data twice: + - once to calculate the signature, and + - a second time to emit the signed data (the result is a prefixed signed message), or +- the verifier would need to process the OpenPGP message twice: + - once to read the signature packets at the end in order to determine the hash algorithm, and + - a second time to process the body of the message, and calculate the hash verifying the signature. + +The one-pass signature packet solves this issue, by allowing both the creation and verification of a signed message in a single pass. It effectively contains a copy of the data in a signature packet, but without the cryptographic signature data. + +The signer can easily emit this metadata before processing the full message, and for the verifier, this metadata enables processing of the message body. Both signer and verifier can efficiently generate or check a one-pass signed message. + +#### Creation + +To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed message, emitting it as a series of one or more {term}`packets` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. + +For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. + +Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. + +#### Verification + +{term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: + +1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. + +2. **Processing the {term}`OpenPGP message`**: This step involves {term}`hashing` its data, preparing it for {term}`signature` {term}`verification`. + +3. **{term}`Verifying` {term}`signature packets`**: Located at the end of the message, these {term}`packets` are checked against the previously calculated {term}`hash digest`. + +Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. + +(prefixed-signature)= +### Prefixed signed message + +A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. + +#### Structure + +In this format, the signature packets are stored ahead of the message itself: + +1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. + +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. + +```{figure} ../plain_svg/prefixed-signed-message.svg +:name: fig-prefixed-signed-message +:alt: Depicts the structure of a prefixed signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. + +Structure of a prefixed signed message. +``` + +Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. + +For verification, this is equally convenient as the one-pass signed message form. + +However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: + +- once reading it to calculate the cryptographic signature, and +- once more to store the data in the generated OpenPGP message, after the signature packet(s). + ## Nesting of one-pass signatures Signing a message using the one-pass mechanism involves prepending a *One-Pass-Signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content. @@ -16,9 +125,9 @@ One-Pass-Signatures are nested, meaning the outermost One-Pass-Signature packet ``` When a message is signed, the signature is always calculated over the contents of the literal data packet, not the literal data packet itself. -This means, that if a message, which is compressed using a compressed data packet is wrapped using a one-pass-signature, the signature is still being calculated over the plaintext inside the literal data packet. +This means that if a message, which is compressed using a compressed data packet is wrapped using a one-pass-signature, the signature is still being calculated over the plaintext inside the literal data packet. -There is one exception though. +There is one exception, though. ```{note} Of course there is. ``` diff --git a/book/source/signing_data.md b/book/source/signing_data.md index 3c0a866..a9817ec 100644 --- a/book/source/signing_data.md +++ b/book/source/signing_data.md @@ -52,109 +52,7 @@ An {term}`inline signature` joins the signed data and its corresponding {term}`d This method is commonly used for signing or encrypting emails. Most email software capable of handling OpenPGP communications typically uses {term}`inline signatures`. -OpenPGP defines two variant forms of inline-signed messages: - -1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier can verify this format in one pass. -2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. - -[^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. - -(one-pass-signature)= -### One-pass signed message - -This is the commonly used format for inline signed messages. - -#### Structure - -A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: - -1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. - -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed could for example consist of a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. - -3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. - -```{figure} plain_svg/ops-signed-message.svg -:name: fig-ops-signed-message -:alt: Depicts the structure of a one-pass signed message. Two one-pass signatures lead a literal data packet, followed by two signature packets. Arrows show, how the hash-algorithm field of the one-pass signatures is inspected in order to initiate the hashing procedure. - -The structure of a one-pass signed message. -``` - -```{note} -Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. - -Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. -``` - -#### The function of the one-pass signature packet - -To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when signed data is large and exceeds available memory in size. - -The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. - -The verifier, on the other hand, needs some information from the signature packet in order to perform the signature verification process. In particular, the verifier needs to know which hash algorithm was used to calculate the signature, in order to perform the same hashing operation on the message data. - -As a consequence, without a {term}`one-pass signature packet`, either: -- the producer would need to process the signed data twice: - - once to calculate the signature, and - - a second time to emit the signed data (the result is a prefixed signed message), or -- the verifier would need to process the OpenPGP message twice: - - once to read the signature packets at the end in order to determine the hash algorithm, and - - a second time to process the body of the message, and calculate the hash verifying the signature. - -The one-pass signature packet solves this issue, by allowing both the creation and verification of a signed message in a single pass. It effectively contains a copy of the data in a signature packet, but without the cryptographic signature data. - -The signer can easily emit this metadata before processing the full message, and for the verifier, this metadata enables processing of the message body. Both signer and verifier can efficiently generate or check a one-pass signed message. - -#### Creation - -To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed message, emitting it as a series of one or more {term}`packets` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. - -For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. - -Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. - -#### Verification - -{term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: - -1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. - -2. **Processing the {term}`OpenPGP message`**: This step involves {term}`hashing` its data, preparing it for {term}`signature` {term}`verification`. - -3. **{term}`Verifying` {term}`signature packets`**: Located at the end of the message, these {term}`packets` are checked against the previously calculated {term}`hash digest`. - -Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. - -(prefixed-signature)= -### Prefixed signed message - -A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. - -#### Structure - -In this format, the signature packets are stored ahead of the message itself: - -1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. - -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. - -```{figure} plain_svg/prefixed-signed-message.svg -:name: fig-prefixed-signed-message -:alt: Depicts the structure of a prefixed signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. - -Structure of a prefixed signed message. -``` - -Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. - -For verification, this is equally convenient as the one-pass signed message form. - -However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: - -- once reading it to calculate the cryptographic signature, and -- once more to store the data in the generated OpenPGP message, after the signature packet(s). +For more details and internals, see [](adv-inline-signature). (cleartext-signature)= ## Cleartext signatures From 2444e6cc931247b56a3f666447ab88be80a25f75 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sat, 23 Dec 2023 04:01:07 +0100 Subject: [PATCH 60/80] Adjust styling of "one-pass" in the nesting section --- book/source/adv/signing_data.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index d89250e..2f65f87 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -116,16 +116,16 @@ However, when a signer creates a {term}`prefixed signed message`, the signed dat ## Nesting of one-pass signatures -Signing a message using the one-pass mechanism involves prepending a *One-Pass-Signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content. +Signing a message using the one-pass mechanism involves prepending a *one-pass signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content. An OpenPGP message can contain multiple signatures added that way. ```{note} -One-Pass-Signatures are nested, meaning the outermost One-Pass-Signature packet corresponds to the outermost signature packet. +One-pass signatures are nested, meaning the outermost one-pass signature packet corresponds to the outermost signature packet. ``` When a message is signed, the signature is always calculated over the contents of the literal data packet, not the literal data packet itself. -This means that if a message, which is compressed using a compressed data packet is wrapped using a one-pass-signature, the signature is still being calculated over the plaintext inside the literal data packet. +This means that if a message, which is compressed using a compressed data packet is wrapped using a one-pass signature, the signature is still being calculated over the plaintext inside the literal data packet. There is one exception, though. ```{note} @@ -137,20 +137,20 @@ If this flag is set to `0`, it indicates that further OPSs will follow this pack [^nested-flag]: See [description of the nested flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1). -This mechanism enables attested signatures, where the signer signs an already one-pass-signed message including the already contained signature. +This mechanism enables attested signatures, where the signer signs an already one-pass signed message including the already contained signature. As a practical example, consider the following notation: * `LIT("Hello World")` represents a literal data packet with the content `Hello World`. * `COMP(XYZ)` represents a compressed data packet over some other packet `XYZ`. -* `OPS₁` represents a one-pass-signature packet with the nested flag set to `1`. Analogous, `OPS₀` has the nested flag set to `0`. +* `OPS₁` represents a one-pass signature packet with the nested flag set to `1`. Analogous, `OPS₀` has the nested flag set to `0`. * `SIG` represents a signature packet. -A normal, one-pass-signed message looks like this: +A normal, one-pass signed message looks like this: `OPS₁ LIT("Hello World") SIG` Here, the signature is calculated over the plaintext `Hello World`, as is it in a message that has the following form: `OPS₁ COMP(LIT("Hello World")) SIG`. -A message, where multiple one-pass-signatures are calculated over the same plaintext looks the following: +A message, where multiple one-pass signatures are calculated over the same plaintext looks the following: `OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG` All three signatures are calculated over the same plaintext `Hello World`. From 7b4031dc0a5b6d12038f710c2e7fda215b959023 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sat, 23 Dec 2023 19:09:17 +0100 Subject: [PATCH 61/80] Move "nesting" section up into the OPS section --- book/source/adv/signing_data.md | 60 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 2f65f87..b8e9ad6 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -85,36 +85,7 @@ Strictly speaking, knowing just the hash algorithm would be sufficient to begin Important to note, the {term}`signer`'s {term}`public key`, critical for the final {term}`verification` step, is not embedded in the message. Verifiers must acquire this {term}`key` externally (e.g., from a {term}`key server`) to authenticate the {term}`signature` successfully. -(prefixed-signature)= -### Prefixed signed message - -A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. - -#### Structure - -In this format, the signature packets are stored ahead of the message itself: - -1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. - -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. - -```{figure} ../plain_svg/prefixed-signed-message.svg -:name: fig-prefixed-signed-message -:alt: Depicts the structure of a prefixed signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. - -Structure of a prefixed signed message. -``` - -Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. - -For verification, this is equally convenient as the one-pass signed message form. - -However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: - -- once reading it to calculate the cryptographic signature, and -- once more to store the data in the generated OpenPGP message, after the signature packet(s). - -## Nesting of one-pass signatures +#### Nesting of one-pass signatures Signing a message using the one-pass mechanism involves prepending a *one-pass signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content. @@ -159,3 +130,32 @@ Now, a message, where the signer attests an already signed message has the follo `OPS₁ OPS₁ LIT("Hello World") SIG SIG` While the inner signature is calculated over the usual plaintext `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. + +(prefixed-signature)= +### Prefixed signed message + +A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. + +#### Structure + +In this format, the signature packets are stored ahead of the message itself: + +1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. + +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. + +```{figure} ../plain_svg/prefixed-signed-message.svg +:name: fig-prefixed-signed-message +:alt: Depicts the structure of a prefixed signed message. As an example, two signature packets lead a literal data packet. Arrows show, how the signatures hash algorithm field is inspected to start the hashing procedure. + +Structure of a prefixed signed message. +``` + +Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. + +For verification, this is equally convenient as the one-pass signed message form. + +However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: + +- once reading it to calculate the cryptographic signature, and +- once more to store the data in the generated OpenPGP message, after the signature packet(s). From 2b879ce908f881f1bd107abeda57d74fa75f2a47 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sun, 24 Dec 2023 17:12:43 +0100 Subject: [PATCH 62/80] Install python-sphinx-sitemap --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index af41435..419bbac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /book # fix EPUB rendering: https://github.com/sphinx-doc/sphinx/issues/11598 RUN \ pacman -Sy --needed --noconfirm archlinux-keyring \ - && pacman -Syu --needed --noconfirm inkscape make noto-fonts patch python-myst-parser python-sphinx python-sphinxext-opengraph ttf-montserrat \ + && pacman -Syu --needed --noconfirm inkscape make noto-fonts patch python-myst-parser python-sphinx python-sphinxext-opengraph python-sphinx-sitemap ttf-montserrat \ && patch -Np1 -d /usr/lib/python3.11/site-packages/ -i /book/patches/sphinx-11766.patch \ && make epub html From 4c40c10799f1ad3b05600df792b0cd7ffe70a53c Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sun, 24 Dec 2023 13:01:44 +0100 Subject: [PATCH 63/80] Use sphinx_sitemap --- book/source/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/book/source/conf.py b/book/source/conf.py index 63de928..dd3cfd3 100644 --- a/book/source/conf.py +++ b/book/source/conf.py @@ -28,6 +28,7 @@ description = 'The essential OpenPGP guide for application developers. Learn the extensions = [ 'myst_parser', 'sphinxext.opengraph', + 'sphinx_sitemap', ] source_suffix = ['.md', '.rst'] @@ -82,6 +83,7 @@ html_css_files = [ ('html/css/custom.css', {'priority': 1000}) ] +html_baseurl = 'https://openpgp.dev/book/' html_favicon = '_static/html/img/favicon.ico' html_logo = '_static/html/img/logo.svg' html_show_sphinx = False @@ -108,3 +110,5 @@ ogp_custom_meta_tags = [ f'', ] +# sphinx sitemap https://sphinx-sitemap.readthedocs.io/en/latest/advanced-configuration.html +sitemap_url_scheme = "{link}" From 415ac4e3f0a71e485f0190899caee094f55baea6 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sun, 24 Dec 2023 17:24:10 +0100 Subject: [PATCH 64/80] Install python-sphinx-sitemap (for links and epub CI jobs) --- .woodpecker/epub.yml | 2 +- .woodpecker/links.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.woodpecker/epub.yml b/.woodpecker/epub.yml index f792022..57dad7b 100644 --- a/.woodpecker/epub.yml +++ b/.woodpecker/epub.yml @@ -18,7 +18,7 @@ steps: image: archlinux:latest commands: - pacman -Sy --needed --noconfirm archlinux-keyring - - pacman -Syu --needed --noconfirm epubcheck inkscape noto-fonts make patch python-myst-parser python-sphinx python-sphinxext-opengraph ttf-montserrat + - pacman -Syu --needed --noconfirm epubcheck inkscape noto-fonts make patch python-myst-parser python-sphinx python-sphinxext-opengraph python-sphinx-sitemap ttf-montserrat # fix sphinx: https://github.com/sphinx-doc/sphinx/issues/11598 - patch -Np1 -d /usr/lib/python3.11/site-packages/ -i "$(pwd)/book/patches/sphinx-11766.patch" - make -C book epub-check diff --git a/.woodpecker/links.yml b/.woodpecker/links.yml index 415b142..add8878 100644 --- a/.woodpecker/links.yml +++ b/.woodpecker/links.yml @@ -19,5 +19,5 @@ steps: image: archlinux:latest commands: - pacman -Sy --needed --noconfirm archlinux-keyring - - pacman -Syu --needed --noconfirm inkscape lychee make noto-fonts python-myst-parser python-sphinx python-sphinxext-opengraph ttf-montserrat + - pacman -Syu --needed --noconfirm inkscape lychee make noto-fonts python-myst-parser python-sphinx python-sphinxext-opengraph python-sphinx-sitemap ttf-montserrat - make -C book html-linkcheck From 7e0fff2c30cc2137002d944ae1fd1a73d2e84cbe Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 26 Dec 2023 22:09:41 +0100 Subject: [PATCH 65/80] adjust the logo files --- book/source/_static/html/img/logo.png | Bin 8641 -> 12112 bytes book/source/_static/html/img/logo.svg | 76 ++++++++++++++------------ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/book/source/_static/html/img/logo.png b/book/source/_static/html/img/logo.png index 4d3a395610499daeba959c774d77d69b3bf6ec28..7060b5586483e6bc2e50f299a2e5c35c77388136 100644 GIT binary patch literal 12112 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 Pel*us*H^1iaftqZ6ML~< literal 8641 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 diff --git a/book/source/_static/html/img/logo.svg b/book/source/_static/html/img/logo.svg index b888225..bc31b55 100644 --- a/book/source/_static/html/img/logo.svg +++ b/book/source/_static/html/img/logo.svg @@ -1,12 +1,12 @@ + inkscape:label="OpenPGP signature packet"> From 59832e220bb10a3d658890b7822489b60cb7e27d Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 26 Dec 2023 17:15:31 +0100 Subject: [PATCH 66/80] Edits for clarity; normalize "inline signed". Inline signed: without dash, to correspond with "one-pass signed". C-R seems inconsistent about this styling. --- book/source/adv/signing_data.md | 54 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index b8e9ad6..5411dfb 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -8,11 +8,11 @@ SPDX-License-Identifier: CC-BY-SA-4.0 (adv-inline-signature)= ## Internals of inline signed messages -Inline-signed messages are one of the forms of [OpenPGP data signatures](forms-of-data-signatures). An {term}`inline-signed message ` joins the signed data and its corresponding {term}`data signature` into a single {term}`OpenPGP message`. +Inline signed messages are one of the forms of [OpenPGP data signatures](forms-of-data-signatures). An {term}`inline signed message ` joins the signed data and its corresponding {term}`data signature` into a single {term}`OpenPGP message`. -OpenPGP defines two variant forms of inline-signed messages: +OpenPGP defines two variant forms of inline signed messages: -1. **{term}`One-pass signed messages`** This is the commonly used format for inline-signed messages. A signer can produce and a verifier can verify this format in one pass. +1. **{term}`One-pass signed messages`** This is the commonly used format for inline signed messages. A signer can produce and a verifier can verify this format in one pass. 2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. [^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. @@ -28,7 +28,7 @@ A {term}`one-pass signed` {term}`OpenPGP message` consi 1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed could, for example, consist of a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. +2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed will typically consist of either a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. 3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. @@ -42,40 +42,46 @@ The structure of a one-pass signed message. ```{note} Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. -Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`. Its use allows storing the {term}`signature packets` after the message body. +Instead, it's a type of auxiliary packet that can be used in conjunction with {term}`signature packets`, to enable efficient generation and checking of inline signed messages. + +The structure of a {term}`one-pass signature packet` closely mirrors an {term}`OpenPGP signature packet`. However, it does not contain a cryptographic signature. ``` #### The function of the one-pass signature packet -To understand the purpose of this packet, consider that without it, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off for efficient data processing. In particular when signed data is large and exceeds available memory in size. +The purpose of this packet is efficient handling of inline signed messages in *stream processing* mode. This is particularly important when the signed message is large and exceeds available memory in size. -The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. +Without this packet, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off: -The verifier, on the other hand, needs some information from the signature packet in order to perform the signature verification process. In particular, the verifier needs to know which hash algorithm was used to calculate the signature, in order to perform the same hashing operation on the message data. +- The producer of a signed OpenPGP message wants to streamline the signature calculation process in such a way that allows to emit a copy of the signed data while calculating the cryptographic signature. On the signer's side, the signature packet is therefore easy to store after the signed data. +- The verifier, on the other hand, needs some information from the signature packet to perform the signature verification process. In particular, the verifier needs to know which hash algorithm was used to calculate the signature, to perform the same hashing operation on the message data. As a consequence, without a {term}`one-pass signature packet`, either: -- the producer would need to process the signed data twice: - - once to calculate the signature, and - - a second time to emit the signed data (the result is a prefixed signed message), or -- the verifier would need to process the OpenPGP message twice: - - once to read the signature packets at the end in order to determine the hash algorithm, and + +- The producer would need to process the input data twice: + - once to calculate the cryptographic signature, and + - a second time to emit the signed data (this format result is a [](prefixed-signature)), or +- The verifier would need to process the OpenPGP message twice: + - once to read the signature packets at the end to determine the hash algorithm, and - a second time to process the body of the message, and calculate the hash verifying the signature. -The one-pass signature packet solves this issue, by allowing both the creation and verification of a signed message in a single pass. It effectively contains a copy of the data in a signature packet, but without the cryptographic signature data. +The one-pass signature packet solves this issue by allowing both the *creation* and *verification* of a signed message in a single pass. The one-pass signature packet effectively contains an advance copy of the data in the signature packet, but without the cryptographic signature data. -The signer can easily emit this metadata before processing the full message, and for the verifier, this metadata enables processing of the message body. Both signer and verifier can efficiently generate or check a one-pass signed message. +The signer can easily emit the metadata in the one-pass signature packet before processing the full message. For the verifier, availability of this metadata at the start of the signed message enables processing of the message body. + +Even in stream processing mode, signers can efficiently generate one-pass signed messages, and verifiers can efficiently check them. #### Creation To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed message, emitting it as a series of one or more {term}`packets` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. -For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline-signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. +For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. #### Verification -{term}`Inline-signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: +{term}`Inline signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: 1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. @@ -87,24 +93,24 @@ Important to note, the {term}`signer`'s {term}`public key`, #### Nesting of one-pass signatures -Signing a message using the one-pass mechanism involves prepending a *one-pass signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content. +A {term}`one-pass signed message` can contain multiple signatures. -An OpenPGP message can contain multiple signatures added that way. +There are two subtly different use cases for this: + +- Multiple signers can issue cryptographic signatures that can be stored in one shared (and thus space-efficient) inline signed message. In this case, each signer makes a cryptographic statement about just the signed message. The individual signatures are independent of each other. +- Alternatively, a later signer can sign not just the input message, but also include a previous signature in their signature. In this case, the second signer notarizes the previous signer's signature combined with the signed message. ```{note} -One-pass signatures are nested, meaning the outermost one-pass signature packet corresponds to the outermost signature packet. +One-pass signatures are nested. The outermost one-pass signature packet corresponds to the outermost signature packet. ``` -When a message is signed, the signature is always calculated over the contents of the literal data packet, not the literal data packet itself. -This means that if a message, which is compressed using a compressed data packet is wrapped using a one-pass signature, the signature is still being calculated over the plaintext inside the literal data packet. - There is one exception, though. ```{note} Of course there is. ``` The OPS packet has a "nested" flag[^nested-flag], which can either be `1` or `0`. -If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS. +If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS. [^nested-flag]: See [description of the nested flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1). From 99ea7856cd6fd3945e370264e8989a6742ecb03f Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 26 Dec 2023 22:18:52 +0100 Subject: [PATCH 67/80] Link to one-pass signature packet section from glossary --- book/source/adv/signing_data.md | 1 + book/source/glossary.md | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 5411dfb..85fcbea 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -47,6 +47,7 @@ Instead, it's a type of auxiliary packet that can be used in conjunction with {t The structure of a {term}`one-pass signature packet` closely mirrors an {term}`OpenPGP signature packet`. However, it does not contain a cryptographic signature. ``` +(one-pass-signature-packet)= #### The function of the one-pass signature packet The purpose of this packet is efficient handling of inline signed messages in *stream processing* mode. This is particularly important when the signed message is large and exceeds available memory in size. diff --git a/book/source/glossary.md b/book/source/glossary.md index e93d2bc..6b6be3e 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -347,7 +347,10 @@ Notation Tag Part of a {term}`Notation` name. One-pass Signature Packet - One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. See [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig) for more details. + One or more {term}`packets` before the actual data in a {term}`Data Signature` which contain information to allow a receiving {term}`implementation` to create {term}`hashes` required for signature verification. + + See [](one-pass-signature-packet). + Also see [RFC 5.4](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig). One-pass signed Message The commonly used form of an OpenPGP {term}`Inline Signature`. It combines an {term}`OpenPGP Message` with {term}`signature packets` and accompanying auxiliary {term}`One-pass signatures`. From 468f38da6db1e4800e356f600482995abc87f8d9 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 27 Dec 2023 03:30:55 +0100 Subject: [PATCH 68/80] Move verification-related text to the right section --- book/source/adv/signing_data.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 85fcbea..e899a77 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -76,13 +76,13 @@ Even in stream processing mode, signers can efficiently generate one-pass signed To produce a {term}`one-pass inline signature`, the {term}`signer` decides on a hash algorithm and emits a {term}`one-pass signature packet` into the destination {term}`OpenPGP message`. This contains essential information such as the {term}`fingerprint` of the {term}`signing key` and the {term}`hash` algorithm used for computing the {term}`signature`'s {term}`hash digest`. The signer then processes the entirety of the signed message, emitting it as a series of one or more {term}`packets` into the message as well. Once the data is processed, the {term}`signer` calculates a {term}`cryptographic signature` using the calculated hash value. Lastly, the result is emitted as a {term}`data signature packet` to the output message, and the whole packet sequence can be efficiently stored or transmitted. -For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. - -Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may, for example, involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. - #### Verification -{term}`Inline signed` messages enable efficient {term}`verification` in *one pass*, structured as follows: +For efficient {term}`verification`, an application must understand how to handle the {term}`OpenPGP message` prior to reading from it. This requirement is addressed by the {term}`one-pass signature packets` located at the beginning of {term}`inline signed` messages. This setup enables the verifier to process the data correctly and efficiently in a single pass. + +Strictly speaking, knowing just the hash algorithm would be sufficient to begin the verification process. However, having efficient access to the signer's fingerprint or key ID upfront allows OpenPGP software to fetch the signer's certificate(s) before processing the entirety of the - potentially large - signed data. This may involve downloading the certificate from a keyserver. In case fetching the signer's certificate(s) fails, or requires additional input from the user, it is better to signal the user about this before processing the data. + +{term}`one-pass inline signed messages` enable efficient {term}`verification` in *one pass*, structured as follows: 1. **Initiation with {term}`one-pass signature packets`**: These {term}`packets` begin the {term}`verification` process. They include the {term}`signer`'s {term}`key ID`/{term}`fingerprint`, essential for identifying the appropriate {term}`public key` for signature {term}`validation`. From d9443963917e37c2764bf4e1751a22d6df282875 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 27 Dec 2023 03:36:58 +0100 Subject: [PATCH 69/80] Add a separate section about hashing of inline signature payload --- book/source/adv/signing_data.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index e899a77..4082a64 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -166,3 +166,17 @@ However, when a signer creates a {term}`prefixed signed message`, the signed dat - once reading it to calculate the cryptographic signature, and - once more to store the data in the generated OpenPGP message, after the signature packet(s). + +(hashing-inline-data)= +### Hashing the signed payload of an inline signature + +When inline signing a message, the hash for the signed content is calculated over just the raw payload contained in a literal data packet. No metadata of the literal data packet is included in the signed hash. Even if a compressed data packet wraps the literal data packet, the inline signature is still calculated over the uncompressed content of the literal data packet. + +The calculation of inline data signatures is unusual in two regards: + +- Most OpenPGP signature calculations include packet metadata, but for literal data packets, only the payload is hashed. +- Packets are usually hashed without transforming the packet content for hashing. Decompressing the content of a compressed data packet for hashing is an exception to this pattern. + +However, this approach means that detached signatures and inline signatures are calculated on exactly the same data. + +One format can be transformed into the other, after the fact, without requiring the private key material of the signer. A compression layer can be inserted or removed without disturbing the validity of an existing signature. From eec47a64013100d1547e041ab1030a3115f008a1 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 27 Dec 2023 03:40:21 +0100 Subject: [PATCH 70/80] Simplify "nesting" section --- book/source/adv/signing_data.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 4082a64..6a75d40 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -96,25 +96,19 @@ Important to note, the {term}`signer`'s {term}`public key`, A {term}`one-pass signed message` can contain multiple signatures. -There are two subtly different use cases for this: - -- Multiple signers can issue cryptographic signatures that can be stored in one shared (and thus space-efficient) inline signed message. In this case, each signer makes a cryptographic statement about just the signed message. The individual signatures are independent of each other. -- Alternatively, a later signer can sign not just the input message, but also include a previous signature in their signature. In this case, the second signer notarizes the previous signer's signature combined with the signed message. - ```{note} One-pass signatures are nested. The outermost one-pass signature packet corresponds to the outermost signature packet. ``` -There is one exception, though. -```{note} -Of course there is. -``` +There are two subtly different use cases for inline signatures that contain multiple signatures: + +- Multiple signers can issue cryptographic signatures that can be stored in one shared (and thus space-efficient) inline signed message. In this case, each signer makes a cryptographic statement about just the signed message. The individual signatures are independent of each other. +- Alternatively, a later signer can sign not just the input message, but also include a previous signature in their signature. In this case, the second signer attests the previous signer's signature combined with the signed message. + +To specify which of these two functions a signature performs, the {term}`one-pass signature packet` has a ["nested" flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1), with a value of either `1` or `0`. -The OPS packet has a "nested" flag[^nested-flag], which can either be `1` or `0`. If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS. -[^nested-flag]: See [description of the nested flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1). - This mechanism enables attested signatures, where the signer signs an already one-pass signed message including the already contained signature. As a practical example, consider the following notation: From fda7264f10b12026fb2c3be41ae2d1e881bd56b1 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 27 Dec 2023 03:50:43 +0100 Subject: [PATCH 71/80] Move away from using "plaintext" to refer to signed data --- book/source/adv/signing_data.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 6a75d40..6eff25c 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -107,7 +107,7 @@ There are two subtly different use cases for inline signatures that contain mult To specify which of these two functions a signature performs, the {term}`one-pass signature packet` has a ["nested" flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1), with a value of either `1` or `0`. -If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS. +If the "nested" flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same message payload data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the usual message payload data, but wrapped inside any OPS+Signature combinations that follow this OPS. This mechanism enables attested signatures, where the signer signs an already one-pass signed message including the already contained signature. @@ -120,17 +120,17 @@ As a practical example, consider the following notation: A normal, one-pass signed message looks like this: `OPS₁ LIT("Hello World") SIG` -Here, the signature is calculated over the plaintext `Hello World`, as is it in a message that has the following form: `OPS₁ COMP(LIT("Hello World")) SIG`. +Here, the signature is calculated over the payload `Hello World`. The signature doesn't change if the signed message is instead stored as: `OPS₁ COMP(LIT("Hello World")) SIG` (also see [](hashing-inline-data)). -A message, where multiple one-pass signatures are calculated over the same plaintext looks the following: +A message, where multiple one-pass signatures are calculated over the same payload looks the following: `OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG` -All three signatures are calculated over the same plaintext `Hello World`. +All three signatures are calculated over the same payload `Hello World`. Now, a message, where the signer attests an already signed message has the following format: `OPS₁ OPS₁ LIT("Hello World") SIG SIG` -While the inner signature is calculated over the usual plaintext `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. +While the inner signature is calculated over the usual payload `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. (prefixed-signature)= ### Prefixed signed message From 7774b7a07a003d004f699a7869c98c99c572d83c Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 27 Dec 2023 20:57:04 +0100 Subject: [PATCH 72/80] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 740de1a..6311518 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The "Notes on OpenPGP" project aims to produce accessible documentation for the A book for application developers who want to integrate OpenPGP functionality into their software. -This book serves a standalone introduction to the concepts of OpenPGP. It also introduces readers to the [OpenPGP RFC](https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/). +This book serves as a standalone introduction to the concepts of OpenPGP. It also introduces readers to the [OpenPGP RFC](https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/). ## Rendered versions of this text From 6f3956c3a661983f4cbdb75e6af6f59ebca507f1 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 28 Dec 2023 02:32:34 +0100 Subject: [PATCH 73/80] Attempt to clarify and structure "nesting" section, some more --- book/source/adv/signing_data.md | 45 ++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 6eff25c..9cc7f8d 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -94,22 +94,35 @@ Important to note, the {term}`signer`'s {term}`public key`, #### Nesting of one-pass signatures -A {term}`one-pass signed message` can contain multiple signatures. +A {term}`one-pass signed message` can actually contain multiple, nested, signatures. -```{note} -One-pass signatures are nested. The outermost one-pass signature packet corresponds to the outermost signature packet. -``` +Formally, this is the case because in the [OpenPGP message grammar](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) when an input OpenPGP message is one-pass signed, the resulting sequence of packets is in turn also considered an OpenPGP message. -There are two subtly different use cases for inline signatures that contain multiple signatures: +Thus, this signed message can be one-pass signed yet again. This construction means that all signature packet pairs bracket the innermost message, and the outermost one-pass signature packet corresponds to the outermost signature packet. -- Multiple signers can issue cryptographic signatures that can be stored in one shared (and thus space-efficient) inline signed message. In this case, each signer makes a cryptographic statement about just the signed message. The individual signatures are independent of each other. -- Alternatively, a later signer can sign not just the input message, but also include a previous signature in their signature. In this case, the second signer attests the previous signer's signature combined with the signed message. +##### Two semantics of nested signatures -To specify which of these two functions a signature performs, the {term}`one-pass signature packet` has a ["nested" flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1), with a value of either `1` or `0`. +There are two different use cases and semantics for nested one-pass signatures: -If the "nested" flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same message payload data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the usual message payload data, but wrapped inside any OPS+Signature combinations that follow this OPS. +- Multiple signers issue independent cryptographic signatures that are stored in one shared (and thus space-efficient) inline signed message. In this case, each signer makes a cryptographic statement about just the signed message. The signatures are independent of each other. +- Alternatively, a signer can sign not just the input message, but also include previous signatures in their signature. In this case, the signer makes a cryptographic statement about the pre-existing signature(s) combined with the signed message. This means that the new signer attests the previous signature(s)[^but-why]. -This mechanism enables attested signatures, where the signer signs an already one-pass signed message including the already contained signature. +[^but-why]: It's unclear to the authors of this text if any real-world use case for signatures that notarize inner signatures exists. + +##### How to pick one + +When nesting one-pass signatures, the default expectation would be that each enclosing signature makes a statement about the complete message it contains, including any one-pass signatures within the inner message. + +Issuers of signatures can choose the semantics of their signature, using the ["nested" flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1) in the {term}`one-pass signature packet`. The "nested" flag has a value of either `1` or `0`. + +Meaning of the "nested" flag: + +- `0` means that the one-pass signature that this signature encloses is *not* signed/attested. The new signature doesn't make a cryptographic statement about the directly enclosed signature. If the directly enclosed one-pass signature also has its "nested" flag set to `0`, the enclosing signature also doesn't include the subsequent inner signature in its hashing, and so on. +- `1` means that this one-pass signature makes a cryptographic statement about the full message that it encloses, including all enclosed signatures, if any. + +A typical pattern of use is to set the "nested" flag to `1` on the innermost signature and to `0` on all enclosing signatures. With this pattern, all signatures are independent of each other. Each signature makes a statement about just the innermost message payload (which is stored in a literal data packet). + +##### Examples As a practical example, consider the following notation: * `LIT("Hello World")` represents a literal data packet with the content `Hello World`. @@ -122,15 +135,11 @@ A normal, one-pass signed message looks like this: Here, the signature is calculated over the payload `Hello World`. The signature doesn't change if the signed message is instead stored as: `OPS₁ COMP(LIT("Hello World")) SIG` (also see [](hashing-inline-data)). -A message, where multiple one-pass signatures are calculated over the same payload looks the following: -`OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG` +A message, where multiple independent one-pass signatures are calculated over the same payload looks the following: +`OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG` - all three signatures are calculated over the same payload `Hello World`. -All three signatures are calculated over the same payload `Hello World`. - -Now, a message, where the signer attests an already signed message has the following format: -`OPS₁ OPS₁ LIT("Hello World") SIG SIG` - -While the inner signature is calculated over the usual payload `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. +By contrast, a message, where the signer attests an already signed message has the following format: +`OPS₁ OPS₁ LIT("Hello World") SIG SIG`. While the inner signature is calculated over the usual payload `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. (prefixed-signature)= ### Prefixed signed message From fcab56b6667eee12a34ac9cd1260093c0c960377 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 28 Dec 2023 02:51:56 +0100 Subject: [PATCH 74/80] Fix some link markup, minor edits. --- book/source/adv/signing_data.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 9cc7f8d..2c88dbf 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -13,9 +13,9 @@ Inline signed messages are one of the forms of [OpenPGP data signatures](forms-o OpenPGP defines two variant forms of inline signed messages: 1. **{term}`One-pass signed messages`** This is the commonly used format for inline signed messages. A signer can produce and a verifier can verify this format in one pass. -2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it has no strong benefits and is now rarely used. +2. **{term}`Prefixed signed messages`** This format predates[^inline-signature-formats] {term}`one-pass signed messages` and is conceptually slightly simpler. However, it is now rarely used and can be considered a legacy format. -[^inline-signature-formats]: One-pass signing was first specified in RFC 2440. The format was not supported in PGP 2.6.x. +[^inline-signature-formats]: One-pass signing was [first specified in RFC 2440](https://www.rfc-editor.org/rfc/rfc2440.html#section-5.4). The format was not supported in PGP 2.6.x. For one discussion of the feature in the lead-up to the standardization of RFC 2440, see [here](https://mailarchive.ietf.org/arch/msg/openpgp/U4Qg3Z9bj-RDgpwW5nmRNetOZKY/). (one-pass-signature)= ### One-pass signed message @@ -26,11 +26,11 @@ This is the commonly used format for inline signed messages. A {term}`one-pass signed` {term}`OpenPGP message` consists of three segments: -1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. +1. **{term}`One-pass signature packets`**: These one or more {term}`packets` precede the signed data and enable {term}`signature` computation (both creation and verification) in a single pass. -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. The message that gets signed will typically consist of either a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. +2. **{term}`OpenPGP message`**: This contains the original payload data (e.g., the body of a message), which is signed without additional interpretation or conversion. Internally, a signed [message](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-openpgp-messages) consists of one or more OpenPGP packets. This payload is typically stored as either a {term}`Literal Data Packet`, or a {term}`Compressed Data Packet`. -3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. +3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the signed data. ```{figure} ../plain_svg/ops-signed-message.svg :name: fig-ops-signed-message From 096efc363577c35f71b9514dafd336afaf1c129f Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 28 Dec 2023 04:13:27 +0100 Subject: [PATCH 75/80] Add some more context to prefixed signed format --- book/source/adv/signing_data.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 2c88dbf..57408a0 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -146,6 +146,8 @@ By contrast, a message, where the signer attests an already signed message has t A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. +This is a legacy format. Not all modern implementations support. However, for example, GnuPG 2.4.x can validate messages with this signature format. + #### Structure In this format, the signature packets are stored ahead of the message itself: @@ -163,7 +165,13 @@ Structure of a prefixed signed message. Compared to a {term}`one-pass signed message`, there are no {term}`one-pass signature packets` in this format, and the (otherwise equivalent) {term}`signature packet(s)` are stored ahead of the signed data. -For verification, this is equally convenient as the one-pass signed message form. +```{note} +Even when a prefixed signed message contains multiple signature packets, each signature packet contains an independent signature of just the message payload. Signatures do not include subsequent signatures in their hashes, every signature is only over the raw payload data of the message. +``` + +#### Format is inefficient for the signer + +For verification, this format is equally convenient as the one-pass signed message form. However, when a signer creates a {term}`prefixed signed message`, the signed data must be processed twice: From cc7d58253651904f1676aefbdf16a1dcadd65855 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 29 Dec 2023 12:42:03 +0100 Subject: [PATCH 76/80] Update TSK.svg from skvis --- book/assets/inkscape/TSK.svg | 1859 +++++++++++++++++----------------- 1 file changed, 905 insertions(+), 954 deletions(-) diff --git a/book/assets/inkscape/TSK.svg b/book/assets/inkscape/TSK.svg index 0ef8a03..28abc2f 100644 --- a/book/assets/inkscape/TSK.svg +++ b/book/assets/inkscape/TSK.svg @@ -1,31 +1,130 @@ Component KeyD07B 24EC 91A1 4DD2 40AC 2D53 E6C8 A9E0 5494 9A41 222E A738 576E D19C AEA3 DC99signing- key creation timeComponent KeyencryptionC0A5 8384 A438 E5A1 4F73 7124 26A4 D45D BAEE F4A3 9E6B 30B0 9D55 13F9 78AC CA94- key creation time- key creation timeComponent Key (primary)AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3certificationDr. Alice Adams<adams@work.example>Transferable secret key + y="158.38867">Transferable secret keyComponent KeyD07B 24EC 91A1 4DD2 40AC 2D53 E6C8 A9E0 5494 9A41 222E A738 576E D19C AEA3 DC99signing- key creation timeComponent KeyencryptionC0A5 8384 A438 E5A1 4F73 7124 26A4 D45D BAEE F4A3 9E6B 30B0 9D55 13F9 78AC CA94- key creation timeDr. Alice Adams<adams@work.example>- key creation timeComponent Key (primary)AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3certificationThe "Notes on OpenPGP" projecthttps://codeberg.org/openpgp/notes/ From 331800e3ed04930aef1c84d6e71feb997a0a963d Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 2 Jan 2024 22:22:04 +0100 Subject: [PATCH 77/80] Minor edit --- book/source/adv/signing_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 57408a0..4fefc7a 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -146,7 +146,7 @@ By contrast, a message, where the signer attests an already signed message has t A {term}`prefixed signed message` consists of {term}`signature packet(s)` followed by the message. For the verifier, processing one-pass signed and prefixed signed messages are equally convenient. However, on the signer's side, it takes more resources to generate a {term}`prefixed signed message`. -This is a legacy format. Not all modern implementations support. However, for example, GnuPG 2.4.x can validate messages with this signature format. +This is a legacy format. Not all modern implementations support it. However, for example, GnuPG 2.4.x can validate messages with this signature format. #### Structure From cdeff965ce095f465f846eed0d387f571abbd749 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 3 Jan 2024 13:03:24 +0100 Subject: [PATCH 78/80] drop extraneous link --- book/source/adv/signing_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/adv/signing_data.md b/book/source/adv/signing_data.md index 4fefc7a..68ac002 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -154,7 +154,7 @@ In this format, the signature packets are stored ahead of the message itself: 1. **{term}`Data signature packets`**: These one or more packets contain the {term}`cryptographic signature` corresponding to the original data. -2. [**{term}`OpenPGP message`**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion. +2. **{term}`OpenPGP message`**: This contains the original data (e.g., the body of a message), without additional interpretation or conversion. ```{figure} ../plain_svg/prefixed-signed-message.svg :name: fig-prefixed-signed-message From 654b9739fdf9e97df2181f19b6c90162699819f5 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Tue, 9 Jan 2024 12:52:15 +0100 Subject: [PATCH 79/80] Fix section level --- book/source/adv/certificates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/source/adv/certificates.md b/book/source/adv/certificates.md index 0f44205..8ddd3d0 100644 --- a/book/source/adv/certificates.md +++ b/book/source/adv/certificates.md @@ -226,7 +226,7 @@ Disadvantages/risks of minimizing certificates: - Refreshing certificates from key servers may inflate the certificate again, since OpenPGP certificates tend to act as [append-only structures](append-only). - Some libraries, such as [anonaddy-sequoia](https://gitlab.com/willbrowning/anonaddy-sequoia/-/blob/master/src/sequoia.rs?ref_type=heads#L125) strip unusable encryption subkeys, but retain at least one subkey, even if all subkeys are expired. Although this may leave only an expired encryption subkey in the certificate, this presents a better UX for the end-user who potentially is still in possession of the private key for decryption. -## Guidelines +### Guidelines 1. Don't minimize certificates unless you have a good reason to. 2. When minimizing a certificate, minimize it in a way that suites your use-case. E.g., when minimizing a certificate for distribution alongside a signed software packet, make sure to include enough historical self-signatures as to not break the verification of the signed packet. From cd2b2c6ab87e3e6e091af31483951cfa28d958c5 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 18 Jan 2024 22:38:09 +0100 Subject: [PATCH 80/80] Clarify "Key ID" --- book/source/glossary.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/book/source/glossary.md b/book/source/glossary.md index 6b6be3e..4479c35 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -292,8 +292,12 @@ Key Holder See {term}`Certificate Holder`. Key ID - The high-order (leftmost) 64 bits of an {term}`OpenPGP Fingerprint`. - Historically, this term refers to the low-order (rightmost) 64 bits of an {term}`OpenPGP Fingerprint`. + A Key ID is a shorthand identifier for OpenPGP certificates (or for individual subkeys). A Key ID is a shortened versions of a {term}`fingerprint`: + + - For OpenPGP v6 keys, the Key ID consists of the high-order (leftmost) 64 bits of their {term}`OpenPGP Fingerprint`. + - For OpenPGP v4 keys, the Key ID consists of the low-order (rightmost) 64 bits of their {term}`OpenPGP Fingerprint`. + + Note that since Key IDs are relatively short, they don't meaningfully guard against collisions. Applications must not assume that Key IDs are unique. Key Material May refer to {term}`Public Key Material` or {term}`Private Key Material`.