decryption outputs to stdout before verification

Tennyson T Bardwell tennysontaylorbardwell at gmail.com
Fri Oct 17 03:37:20 CEST 2025


Hi gnupg-users,

In short: I experimented and found that `gpg -d > results.txt` will
write to `results.txt` even if the verification (signature or MDC) of
the wrapped message fails.

This is confirmed by the output[6] of a short script that I wrote[5],
which was inspired by a Qubes thread[1].

I think that I understand why this happens[2], why integrity is
important[3], and that writing to a temporary file (and checking the
exit code before use) is the recommended way to handle this. (Although,
I don't think that this behavior is as prominently documented as I think
that it should be[4])

However, I notice that gpg's `--decrypt` flag does not have a way to
specify the expected signer, meaning that (without parsing stderr)
there is no way to automatically verify the authenticity of an encrypted
file, only the integrity (by observing the exit code).

I guess that my questions are:

1. Am I missing something?
2. Do I need to manually verify that PGP blocks in my emails match the
   sender to avoid https://articles.59.ca/doku.php?id=pgpfan:forwarding
   or simply email sender spoofing?
3. May I, respectfully, request improvement to the documentation?

Warmly,
Tennyson
🌸

P.S. Should I start my emails with "Hello [name] <[email at address]>" to
ensure that the intended sender is included in the signed message?

[1]
https://groups.google.com/g/qubes-devel/c/TQr_QcXIVww

[2]
My understanding/mental-model is that our order of operations is:

1. Decrypted text is streamed and a live hash value is computed while
   the text is sent to /dev/stdout
2. The live hash value is checked
3. GPG exits with zero or non-zero code depending on the results of the check

[3]
I often see it recommended to sign messages before encrypting to ensure
integrity (and, as a byproduct, authentication). It seems that this was
so crucial that MDCs are now enabled by default. My understanding is
that MDCs provide integrity guarantees without signing. It seems that a
lack of integrity allows the injection of text into the message, such as
Efail: https://efail.de/

[4]
AI recommended that I pipe directly from GPG to my consumption program, and
made the assertion that no text would be output until verification
passed. Asserting the negative to AI in a new chat and asking for it to
find a citation didn't immediately work, nor did my own websearching. As
a result, I felt compelled to write the attached script to verify, and
to email this list.

I did not see the answer in the man page, nor the manual:

https://www.gnupg.org/gph/en/manual.html

And it seems like there is confusion/uncertainty from the creator of age:

https://words.filippo.io/age-authentication/#fn:mdc

As well as in the (old) Qubes thread that I linked.

[5]
```bash
#!/usr/bin/env bash
set -xeuo pipefail
IFS=$'\n\t'

gpg --version
cd "$(mktemp -d)"
dd if=/dev/zero of=test.bin bs=1k count=1k
gpg -c --batch --yes --passphrase pass --compress-level 0 test.bin
cp test.bin.gpg test-hacked.bin.gpg
ls -al
dd if=/dev/zero of=test-hacked.bin.gpg bs=1 count=1 seek=666999 conv=notrunc
xxd test.bin.gpg > test.bin.gpg.xxd
xxd test-hacked.bin.gpg > test-hacked.bin.gpg.xxd
diff test.bin.gpg.xxd test-hacked.bin.gpg.xxd || :
gpg -d --batch --yes --passphrase pass test-hacked.bin.gpg > dangerousOutput.bin || :
ls -al
du -hs dangerousOutput.bin
```

[6]
```
$ ./gpg-test.sh
+ IFS='
        '
+ gpg --version
gpg (GnuPG) 2.4.8
libgcrypt 1.10.3
Copyright (C) 2025 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /Users/tennyson/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
++ mktemp -d
+ cd /var/folders/30/9ql0lf1n509_v6q0br5pvv_r0000gn/T/tmp.6iExzO756J
+ dd if=/dev/zero of=test.bin bs=1k count=1k
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.002648 s, 396 MB/s
+ gpg -c --sign --batch --yes --passphrase pass --compress-level 0 test.bin
gpg: AES256.CFB encryption will be used
+ cp test.bin.gpg test-hacked.bin.gpg
+ ls -al
total 3080
drwx------   5 tennyson staff     160 Oct 16 18:59 .
drwx------ 417 tennyson staff   13344 Oct 16 18:59 ..
-rw-r--r--   1 tennyson staff 1048900 Oct 16 18:59 test-hacked.bin.gpg
-rw-r--r--   1 tennyson staff 1048576 Oct 16 18:59 test.bin
-rw-r--r--   1 tennyson staff 1048900 Oct 16 18:59 test.bin.gpg
+ dd if=/dev/zero of=test-hacked.bin.gpg bs=1 count=1 seek=666999 conv=notrunc
1+0 records in
1+0 records out
1 byte copied, 0.000159 s, 6.3 kB/s
+ xxd test.bin.gpg
+ xxd test-hacked.bin.gpg
+ diff test.bin.gpg.xxd test-hacked.bin.gpg.xxd
41688c41688
< 000a2d70: 720c cfea 9d8e e778 4373 768f c741 f207  r......xCsv..A..
---
> 000a2d70: 720c cfea 9d8e e700 4373 768f c741 f207  r.......Csv..A..
+ :
+ gpg -d --batch --yes --passphrase pass test-hacked.bin.gpg
gpg: AES256.CFB encrypted data
gpg: encrypted with 1 passphrase
gpg: Signature made Thu Oct 16 18:59:32 2025 CDT
gpg:                using EDDSA key AFFC0B718C7AF7AAF8B6EC2C76FA7C3D275E4D55
gpg: BAD signature from "Tennyson T Bardwell (onxy machine) <tennysontaylorbardwell at gmail.com>" [ultimate]
+ :
+ ls -al
total 12816
drwx------   8 tennyson staff     256 Oct 16 18:59 .
drwx------ 417 tennyson staff   13344 Oct 16 18:59 ..
-rw-r--r--   1 tennyson staff 1048576 Oct 16 18:59 dangerousOutput.bin
-rw-r--r--   1 tennyson staff 1048900 Oct 16 18:59 test-hacked.bin.gpg
-rw-r--r--   1 tennyson staff 4457864 Oct 16 18:59 test-hacked.bin.gpg.xxd
-rw-r--r--   1 tennyson staff 1048576 Oct 16 18:59 test.bin
-rw-r--r--   1 tennyson staff 1048900 Oct 16 18:59 test.bin.gpg
-rw-r--r--   1 tennyson staff 4457864 Oct 16 18:59 test.bin.gpg.xxd
+ du -hs dangerousOutput.bin
1.0M    dangerousOutput.bin
```



More information about the Gnupg-users mailing list