Cleartext signatures considered harmful
Source: Hacker News
Cleartext Signatures in PGP – Pitfalls and Verification
Since the very first PGP versions of the early 1990s, PGP (and all implementations derived from it) have supported a feature called a cleartext signature. You will still encounter such signatures today. Below is an example of a clearsigned message:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Far out in the uncharted backwaters of the unfashionable end of
the western spiral arm of the Galaxy lies a small unregarded
yellow sun.
-----BEGIN PGP SIGNATURE-----
iJEEARYKADkWIQSHd0YfKgdOvEgNNZQZzByeCFsQegUCaU5mGhsUgAAAAAAEAA5t
YW51MiwyLjUrMS4xMSwyLDIACgkQGcwcnghbEHq27gEAqE+Cw1FmIlDXyzc1+5K8
3e60/3TjpqpFmkmuot8ZROMBAIrQXMhfN3gr7jdsxLuV1L7+IzHSRyUMlelZSnAs
k+AL
=kCuN
-----END PGP SIGNATURE-----
Why a cleartext signature can be misleading
- The signed text is immediately readable, but verifying it correctly requires a PGP tool. Simply looking at the terminal output is not enough because:
- Lines that start with a dash (
-) or the stringFromare escaped. - Many terminal emulators interpret escape codes (e.g., colour or cursor‑movement sequences) that can alter what you see.
- Lines that start with a dash (
- The only reliable way to know what was actually signed is to let a PGP implementation process the whole message and output the canonical signed text.
Verifying a clearsigned message with GnuPG
# Using gpg (prints status and writes the signed text to signed.txt)
gpg --verify -o signed.txt message.asc
# Using gpgv (intended for scripts; only trusts keys in trustedkeys.*)
gpgv -o signed.txt message.asc
Typical output:
gpg: Signature made Fri 26 Dec 2025 11:40:26 AM CET
gpg: using EDDSA key 8777461F2A074EBC480D359419CC1C9E085B107A
gpg: Good signature from "wk@gnupg.org" [ultimate]
...
If the diagnostics show a good signature from a key you trust, you can safely use the contents of signed.txt.
When several keys verify the same message, they all signed the identical text.
Note: gpgv is preferable in automated scripts because it only accepts signatures made by keys listed in trustedkeys.gpg (or trustedkeys.kbx). The --assert-signer option of gpg can be used as an alternative.
Recommendation: use detached signatures (or PGP/MIME)
Cleartext signatures are easy to read but hard to get right. The crucial point is that you must know exactly what was verified. For new messages you should:
-
Prefer a detached signature:
# Verify a detached signature gpg --verify message.sig message.txt gpgv message.sig message.txt(Do not use the
-o/--outputoption here; it would create an empty file.) -
Or, for email, use PGP/MIME (the modern, standard format for signed or encrypted mail).
Historical background
In the early 1990s the Internet was far from ubiquitous; most communication occurred on dial‑up BBSes. Phil Zimmermann designed PGP to let users exchange ASCII‑encoded messages even when the recipients had not yet installed PGP.
Email soon replaced BBSes, but MIME took a while to become common. In 1996 Michael Elkins introduced PGP/MIME (RFC 2015) for the Mutt mail client, gradually supplanting cleartext‑signed and cleartext‑encrypted mail. Today PGP/MIME is the de‑facto standard for signed/encrypted messages, although some clients still allow the older cleartext format.
Why cleartext signatures are insecure
- Armor line manipulation – the
-----BEGIN PGP …header can be forged with fewer dashes or look‑alike Unicode characters, causing a user to believe the signed text starts earlier than it really does. - Comment lines – users are not expected to know that comment lines (e.g.,
Hash:) are not part of the signed text. Adding extra comment lines can inject unsigned material. - Blank‑line tricks – the empty line that separates the armor header from the signed text can be replaced with terminal‑control or UTF‑8 characters, misleading the viewer.
- Overlong lines – can cause display or parsing anomalies.
These and many other variations have been demonstrated over the past 30 years, leading to the widespread adoption of PGP/MIME.
Bottom line
Avoid cleartext signatures for new data. Use detached signatures or PGP/MIME instead, and never assume that the text you see on the screen is exactly what was signed.