diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-05-24 11:18:18 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-06-06 08:47:21 +0200 |
commit | 4f3d260a013835a8ab0b2f15f45e22ca4678ab24 (patch) | |
tree | c9c485e53b73841efe07a29f71bc0906396d1361 /openpgp/src/parse/stream.rs | |
parent | 940a7267a61418661f61da2f0676069096ca2626 (diff) |
openpgp: Fix the cleartext signature framework.
- Previously, we considered the line break immediately before the
signature marker to be part of the signature. This is not
correct. See Section 7.1 of RFC4880:
The line ending (i.e., the <CR><LF>) before the '-----BEGIN PGP
SIGNATURE-----' line that terminates the signed text is not
considered part of the signed text.
- This interpretation allows us to preserve the final newline in the
signed text. See
https://gitlab.com/sequoia-pgp/sequoia-sop/-/issues/16 where dkg
requests:
[...] if a trailing newline goes in, a trailing newline comes
out.
- The previous interpretation required very careful handling of the
trailing line break, making sure it is not hashed. This was
complicated by the fact that line breaks may use two characters,
and the two characters may straddle reads/writes. So, this change
of interpretation makes the code quite a bit simpler.
- To clarify, signing the four octet string "test" yields a message
looking like
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
test
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----
Whereas signing the five octet string "test\n" now yields
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
test
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----
- It is worth pointing out that GnuPG does something similar to what
we did before: it makes sure any signed text ends in a line
break (see `copy_clearsig_text`), but "swallows" this newline by
using it as delimiter between text and signature (see
`clearsign_file` where no explicit newline is emitted before the
armor filter is pushed and the signatures are emitted).
When verifying a message, GnuPG will emit the final line break,
being very careful not to hash it (see `handle_plaintext`).
The result is that any message signed by GnuPG seems to end in a
line break when verified by GnuPG, but will never end in a line
break when verified with Sequoia (or any other implementation that
considers the signature-separating line break to be not part of
the message, like OpenPGP.js). Signature validity is not
affected.
Diffstat (limited to 'openpgp/src/parse/stream.rs')
-rw-r--r-- | openpgp/src/parse/stream.rs | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index 74036553..b59005e7 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -3204,13 +3204,15 @@ pub mod test { (crate::tests::message("a-cypherpunks-manifesto.txt.cleartext.sig") .to_vec(), { + // The test vector, created by GnuPG, does not preserve + // the final newline. + // // The transformation process trims trailing whitespace, // and the manifesto has a trailing whitespace right at // the end. let mut manifesto = crate::tests::manifesto().to_vec(); - let ws_at = manifesto.len() - 2; - let ws = manifesto.remove(ws_at); - assert_eq!(ws, b' '); + assert_eq!(manifesto.pop(), Some(b'\n')); + assert_eq!(manifesto.pop(), Some(b' ')); manifesto }, false, @@ -3218,7 +3220,14 @@ pub mod test { VHelper::new(1, 0, 0, 0, certs.clone())), (crate::tests::message("a-problematic-poem.txt.cleartext.sig") .to_vec(), - crate::tests::message("a-problematic-poem.txt").to_vec(), + { + // The test vector, created by GnuPG, does not preserve + // the final newline. + let mut reference = + crate::tests::message("a-problematic-poem.txt").to_vec(); + assert_eq!(reference.pop(), Some(b'\n')); + reference + }, false, None, VHelper::new(1, 0, 0, 0, certs.clone())), |