SecurityInnovation / PGPy

Pretty Good Privacy for Python
BSD 3-Clause "New" or "Revised" License
313 stars 98 forks source link

PGPy does not correctly sign text documents with spaces befor a newline #463

Open jaccol opened 6 months ago

jaccol commented 6 months ago

Hi,

After some debugging, I found that text files with spaces before a newline would never verify after being signed with PGPy.

First, generate a fresh key to test with:

$ mkdir /tmp/gpgtest/
$ gpg --homedir /tmp/gpgtest/ --generate-key
< ... >
pg: /tmp/gpgtest/trustdb.gpg: trustdb created
gpg: directory '/tmp/gpgtest/openpgp-revocs.d' created
gpg: revocation certificate stored as '/tmp/gpgtest/openpgp-revocs.d/271E7DCCD583640122145B379DFECADCD8C4EEA7.rev'
public and secret key created and signed.

pub   ed25519 2024-02-16 [SC] [expires: 2027-02-15]
      271E7DCCD583640122145B379DFECADCD8C4EEA7
uid                      Test User <test@example.com>
sub   cv25519 2024-02-16 [E] [expires: 2027-02-15]

$ gpg --homedir /tmp/gpgtest/ --armor --export-secret-keys  > /tmp/gpgtest/export.pgp

I have some sample code to demonstrate the issue:

import pgpy

private_key, _ = pgpy.PGPKey.from_file('/tmp/gpgtest/export.pgp')
p = pgpy.PGPMessage.new('/tmp/test.txt', file=True, cleartext=True)
with private_key.unlock("test1234"): p |= private_key.sign(p)
with open('/tmp/test-out.txt', "w+") as f: f.write(str(p))

Test case that proves the key is OK and the code does sign correct:

$ echo 1 > test.txt
$ python sign_test.py 
$ gpg --homedir /tmp/gpgtest/ --verify test-out.txt 
gpg: Signature made Fri 16 Feb 2024 04:01:27 PM CET
gpg:                using EDDSA key 271E7DCCD583640122145B379DFECADCD8C4EEA7
gpg: Good signature from "Test User <test@example.com>" [ultimate]

Test case that demonstrates what is wrong:

$ echo ' ' > test.txt
$ python sign_test.py 
$ gpg --homedir /tmp/gpgtest/ --verify test-out.txt 
gpg: Signature made Fri 16 Feb 2024 04:03:51 PM CET
gpg:                using EDDSA key 271E7DCCD583640122145B379DFECADCD8C4EEA7
gpg: BAD signature from "Test User <test@example.com>" [ultimate]