Attempt to clarify and structure "nesting" section, some more

This commit is contained in:
Heiko Schaefer 2023-12-28 02:32:34 +01:00
parent fda7264f10
commit 6f3956c3a6
No known key found for this signature in database
GPG key ID: DAE9A9050FCCF1EB

View file

@ -94,22 +94,35 @@ Important to note, the {term}`signer`'s {term}`public key<OpenPGP Certificate>`,
#### 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