Merge pull request 'ch7: Describe nested one-pass-signatures' (#189) from paul-ch7-nested-sigs into draft

Reviewed-on: https://codeberg.org/openpgp/notes/pulls/189
This commit is contained in:
heiko 2023-12-10 20:21:04 +00:00
commit d5125b0454

View file

@ -69,13 +69,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<Literal Data Packet>` prior to its reading. This requirement is addressed by the {term}`one-pass signature packets<One-pass Signature Packet>` located at the beginning of {term}`inline-signed<Inline Signature>` messages. These {term}`packets<Packet>` include essential information such as the {term}`fingerprint<OpenPGP Fingerprint>` of the {term}`signing key<OpenPGP Component Key>` and the {term}`hash<Hash Digest>` algorithm used for computing the {term}`signature<OpenPGP Signature Packet>`'s {term}`hash digest`. This setup enables the verifier to process the data correctly and efficiently.
```{admonition} TODO
:class: warning
Is the signer keyid/fingerprint in the OPS important for the verifier to be able to verify the signature efficiently? Or is it (only?) there to be hashed and signed, along with the literal data?
Realization: It's probably useful to know the fingerprints right away, to first go find the public key material, before calculating the hash of a huge file.
```
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
@ -148,8 +142,46 @@ Despite their widespread adoption, {term}`cleartext signatures<Cleartext Signatu
### Nesting of one-pass signatures
```{admonition} TODO
:class: warning
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.
Write
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.
```
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.
[^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:
* `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`.
* `SIG` represents a signature packet.
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:
`OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG`
All three signatures are calculated over the same plaintext `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`.