25

When I send, say, a great recipe for funnel cake to Alice and Bob using GPG, I can be pretty sure they will both be able to decrypt it. However, can I be certain, or prove after the fact, that they will be the only ones who can?*

Context: I assumed this was easy: gpg messages have a list of possible decryption key IDs, which I thought was always guaranteed to be complete. However, then I stumbled upon the --try-all-secrets option for gpg itself and now I'm not sure anymore. If I understand the options correctly, I can have a key that is able to decrypt the message, but is not on the 'public' list of recipients. The 'public' list might have an all-zeroes key ID to show there's something going on but it appears it doesn't always need to. So, that got me thinking...

Question: Would I be able to tell (based on the encrypted output only) if someone had modified my version of gpg to secretly add Eve as an anonymous recipient? Would I need to be one of the recipients to be able to tell?

I know that this scenario would probably never occur in practice, and if an attacker was able to replace your gpg binary this scenario would probably be the least of your worries, but I'm still curious.


*: Assuming of course their private keys are kept private, nobody bribes Alice to share the winning recipe, and so on.

1

2 Answers 2

28

You can't necessarily tell who can decrypt a given GPG file by looking at it, but assuming nobody has any knowledge aside from their own private keys and the encrypted file itself, it is possible tell how many people can.

When you encrypt a message, GPG generates a random symmetric key, called a "session key", and uses it to encrypt the message. It then makes a bunch of copies of the session key, and encrypts each one under a different public key, one for each recipient. It then packages all of these encrypted "key packets" along with the encrypted message using the OpenPGP container format.

The important thing is that if all you have is the encrypted file, you have to be able to decrypt at least one of these encrypted session key packets in order to get to the message.

You can list all of the packets in an encrypted file using the gpg --list-packets command:

$ gpg --batch --list-packets myfile.gpg
:pubkey enc packet: version 3, algo 16, keyid 0000000000000000
        data: [2048 bits]
        data: [2046 bits]
gpg: anonymous recipient; trying secret key ABCDE123 ...
:pubkey enc packet: version 3, algo 16, keyid 123ABCDE0987654F
        data: [2048 bits]
        data: [2046 bits]
:encrypted data packet:
...

(The --batch flag prevents GPG from asking me for my passphrase, so that it can't decrypt anything. If you're running a GPG agent, it'll take more than that.)

Those "pubkey encrypted packets" are encrypted session key packets that were read from the file. The one with "keyid 123ABCDE0987654F" is a normal recipient; the key ID is a hint to tell you which key can be used to decrypt the packet. The one with "keyid 0000000000000000" is an anonymous recipient: you don't know which key will decrypt it, but you know it's there waiting to be decrypted by something. If your gpg was modified to add Eve as an anonymous recipient, this is what you would see when inspecting the .gpg file using a clean gpg binary. It's also what you would see if you added an anonymous recipient on purpose.

If Eve's a little more clever, though, then there are a couple of ways to further hide recipients:

  • The listed keyid value could be a lie. The all-zeroes keyid is just a convention, and the normal keyid is just a hint: there could be anything there. Eve could label her encrypted key packet using Bob's keyid, and replace Bob's legitimate packet with hers. It would look like a packet for Bob, but if he tried to use it, the decryption would fail. Only Bob would be able to check this. The --try-all-secrets flag is somewhat related, and could be useful if the keyid was accidentally wrong.
  • Eve doesn't have to put her key packet into the file, or even create an encrypted key packet for herself at all. Try out the --show-session-key and --override-session-key flags on a dummy file with no sensitive data. These will let you handle the session key directly instead of keeping it hidden away in encrypted key packets. If Eve has replaced your gpg binary, she could (for example) have it email her the session key of every file you encrypt, along with a hash of the encrypted data for easy identification. This violates the "no prior knowledge" assumption from earlier, but I felt the existence of these flags made it worth mentioning.
0
1

Try this:

# gpg -d your_encrypted_file > /dev/null

gpg: encrypted with 2048-bit ELG key, ID 245AC23E80C4A478, created 2005-12-17]
     "Bobby - [email protected]"
gpg: encrypted with 4096-bit RSA key, ID CB6D005B993F02AB, created 2020-04-08
      "Mary - [email protected]"
gpg: encrypted with 4096-bit RSA key, ID 8AB5B9CEB6F0B2D2, created 2018-11-29
      "Betty Liu - [email protected]"

( the -d flag is for decrypting the file. As GPG decrypts, it sends the information for each key to STDERR, which will display on your screen. For a normal decryption, you would redirect STDOUT to a file but, in this case, we don't actually care about the file contents, so we redirect it to /dev/null. )

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .