From 6f3956c3a661983f4cbdb75e6af6f59ebca507f1 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 28 Dec 2023 02:32:34 +0100 Subject: [PATCH] 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