diff --git a/book/assets/drawio/ops-signed-message.drawio b/book/assets/drawio/ops-signed-message.drawio new file mode 100644 index 0000000..deaec9a --- /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..da6b370 --- /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: 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 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/adv/signing_data.md b/book/source/adv/signing_data.md index f031233..57408a0 100644 --- a/book/source/adv/signing_data.md +++ b/book/source/adv/signing_data.md @@ -5,48 +5,189 @@ SPDX-License-Identifier: CC-BY-SA-4.0 # Advanced material: Signatures over data -## Nesting of one-pass signatures +(adv-inline-signature)= +## Internals of inline signed messages -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. +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`. -An OpenPGP message can contain multiple signatures added that way. +OpenPGP defines two variant forms of inline signed messages: -```{note} -One-Pass-Signatures are nested, meaning the outermost One-Pass-Signature packet corresponds to the outermost signature packet. -``` +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 is now rarely used and can be considered a legacy format. -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. +[^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/). -There is one exception though. -```{note} -Of course there is. +(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. **{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`**: 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 signed 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. ``` -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. +```{note} +Despite its name, a {term}`one-pass signature packet` is not a type of {term}`signature packet`. -[^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). +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. +``` -This mechanism enables attested signatures, where the signer signs an already one-pass-signed message including the already contained 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. + +Without this packet, the position of signature packets within an inline signed OpenPGP message constitutes a trade-off: + +- 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 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. 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 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. + +#### Verification + +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`. + +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. + +#### Nesting of one-pass signatures + +A {term}`one-pass signed message` can actually contain multiple, nested, signatures. + +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. + +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. + +##### Two semantics of nested signatures + +There are two different use cases and semantics for nested one-pass signatures: + +- 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]. + +[^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`. * `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`. +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: -`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 plaintext `Hello World`. +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`. -Now, a message, where the signer attests an already signed message has the following format: -`OPS₁ OPS₁ LIT("Hello World") SIG SIG` +(prefixed-signature)= +### Prefixed signed message -While the inner signature is calculated over the usual plaintext `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`. +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: + +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. + +```{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: + +- 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. diff --git a/book/source/glossary.md b/book/source/glossary.md index 40c2fa3..6b6be3e 100644 --- a/book/source/glossary.md +++ b/book/source/glossary.md @@ -115,7 +115,7 @@ Component Key See {term}`OpenPGP Component Key`. Compressed Data Packet - A packet containing a compressed {term}`OpenPGP Message` (typically a {term}`Literal Data Packet`). + A {term}`packet` that contains a compressed {term}`OpenPGP Message` (typically a {term}`Literal Data Packet`). A Compressed Data Packet represents a "compressed message". Compression See {term}`Data Compression`. @@ -245,7 +245,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 a {term}`Transferable Secret Key`. @@ -307,7 +314,11 @@ Life-cycle Management See [](self-signatures). Literal Data Packet - 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. + A {term}`packet` that contains a payload of data. It represents a "literal message". + + A literal data packet typically stores the paintext data of an encrypted message, and/or the data of an inline signed message. + + See [RFC 5.9](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit). MAC See {term}`Message Authentication Code`. @@ -336,7 +347,15 @@ 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`. + + 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) @@ -344,6 +363,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). @@ -356,7 +378,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 packets, such as {term}`literal`, {term}`compressed`, {term}`encrypted` or {term}`signed` 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`. @@ -428,6 +457,10 @@ 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 + 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`. diff --git a/book/source/signing_data.md b/book/source/signing_data.md index ca174b3..a9817ec 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 @@ -35,62 +35,34 @@ 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. -### 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. +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. (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`. This method is commonly used for signing or encrypting emails. Most email software capable of handling OpenPGP communications typically uses {term}`inline signatures`. -#### Structure - -An {term}`inline-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. - -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. - -3. **{term}`Data signature packets`**: These contain the {term}`cryptographic signature` corresponding to the original data. - -#### 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. - -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 . - -#### 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}`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`. - -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. +For more details and internals, see [](adv-inline-signature). (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: @@ -111,7 +83,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`: @@ -123,7 +95,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: @@ -131,7 +103,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.