I'd like to know how to implement forward secrecy using GnuPG, and I presume I need some kind of authenticated key exchange. Assuming that I have the following working already:

  • Alice and Bob have both generated their own regular asymmetric keypairs
  • Alice has Bob's public key, and Bob has Alice's public key
  • Alice and Bob have verified that they have the correct keys and therefore trust each other
  • Alice can send messages asymmetrically encrypted with Bob's public key, and Bob can decrypt them, read them and verify signatures (and vice versa)

The problem I'd like to solve is that if somebody had managed to intercept and store an encrypted message from last week, and subsequently managed to obtain the corresponding private key from either Alice or Bob, then they could decrypt and read the old message. It's my hope that with a temporary session key (negotiated but not sent) this would no longer be possible, as the message from last week would be symmetrically encrypted with a random session key, and this session key was never sent in any message.

I believe that what this needs is an Authenticated Key Exchange (AKE) like Diffie-Hellman, so can my program do this using GnuPG as a library?

  • Generation of suitable random token
  • Combination of this token with private key
  • (program is then responsible for storage of temporary data in memory, and transmission of encrypted, signed message)
  • Combination of received (token+key) from other party with own private key to give temporary session key k
  • Use of this agreed k as a symmetric session key

Ideally this session key would not need to be added to any keyring, and creating it would be significantly faster than generating an asymmetric keypair.


According to the FAQ at https://gnupg.org/faq/gnupg-faq.html#compatible :

“Diffie-Hellman” is what PGP calls the Elgamal encryption algorithm. If your PGP-generated keypair uses a Diffie-Hellman encryption subkey, it will appear in GnuPG as an Elgamal subkey.

but according to the manual at https://gnupg.org/gph/en/manual.html#AEN26 the key generation for ElGamal produces a keypair:

Option 4 creates a single ElGamal keypair usable for both making signatures and performing encryption.

This makes it sound like an asymmetric keypair which is not what I want, and it also sounds like it would be added to the keyring, which sounds undesirable and inefficient. So I'm a little confused about what GnuPG means by "ElGamal", and I don't see how a key exchange protocol can be considered equivalent to an encryption algorithm.


Thanks to forest's answer below, I understand that this isn't possible, even though it seems that GnuPG is more than capable of doing the mathematics required. I left it open for a little longer just in case somebody else knew a way.

I will have to look further into OTR, which is obviously a separate question.

I also realized after asking this question that maybe I should have put it in crypto.stackexchange - my apologies if putting it there would have been more appropriate. Thanks for the comments!

  • ElGamal is just one of the alternatives to RSA for encryption. Despite operating on the same basis as Diffie-Hellman, it does not provide forward secrecy. The only similarity is that it operates on the principal of the discrete logarithm problem. – forest Feb 26 '18 at 12:41

Is there anything like this?

There is actually a draft specifically on doing this, titled Forward Secrecy Extensions for OpenPGP. The gist of the draft is that temporary keys must be created for each message and securely deleted after they are used. This runs into a few problems. Most importantly, an OpenPGP extension will not be able to guarantee that data is securely removed from a storage device. Many storage devices will not allow data to be erased in place. This is done by solid state drives as a form of wear leveling, with the purpose being to reduce the wear on any individual area of storage. Certain filesystems employ a technique to improve reliability in the event of crashes called copy-on-write which has the side-effect of causing writes to the same location to not overwrite the data that was previously there. Additionally, many systems take snapshots of their state, defeating the purpose of securely erasing a key.

What makes forward secrecy hard with PGP?

The main difference between something like PGP and TLS is that TLS is quick. You can be confident that a handshake will complete in a second or two. This allows you to store the temporary key material entirely in memory. A PGP-encrypted message on the other hand may sit unread for an indefinite period, increasing the chances that a key is stolen. Forward secrecy is thus easy to implement with live systems that begin and finish the key exchange in a single session, but much harder to implement on a highly asynchronous system where there is no guarantee that a message will be quickly read.

Overall, the main reasons PGP is so much harder to use with forward secrecy is:

  • PGP is interactive so you can't keep ephemeral keys in memory for only a split second.
  • Keys must be stored on a non-volatile storage device, at which point secure erasure is uncertain.

Possible alternatives

The most viable alternative you have right now is to have rather short-lived encryption subkeys. Create one long-lived master key, preferably stored on an external device (and thus resistant to compromise). Subkeys should be kept for a shorter period and revoked after a minimum amount of time, for example one month, or a dozen messages. When revoking a key, update your public key to include freshly generated subkeys. People communicating with you will need to update their copy of your public key regularly in order to communicate with you. You will need to be aware of how your system works to avoid leaving traces of previous private keys on your device. This could be mitigated by keeping them on a different smart card, as they are designed to store these keys and can often also securely erase them at a moment's notice. GnuPG supports using smart cards as a source of key material.

You can also use OTR, which allows for real-time encrypted communication with forward secrecy. It is a plugin for various messaging systems that encrypts data using Diffie-Hellman key exchange and AES. It is currently supported on various social media messaging applications (e.g. Facebook's messenger), as well as IRC and XMPP. There is also a plugin for Pidgin, a chat client that supports a wide variety of protocols. Any protocol that Pidgin supports can be encrypted using OTR.

  • I don't understand this sentence: "A PGP-encrypted message on the other hand may sit unread for an indefinite period, increasing the chances that a key is stolen". There are no keys inside the message so which key do you mean could be stolen? And regarding your comments why it's hard, I expect GnuPG to be stateless during these steps, so it shouldn't need to keep anything in memory. – user171587 Feb 26 '18 at 13:00
  • 1
    The keys must be stored by the client which wants to decrypt them. In order to decrypt a message encrypted with key A, you need to have key A. If a user's drive is compromised, then whatever private keys are on the computer can be stolen, allowing decryption of captured messages. With TLS, someone would have to compromise the system while the operation is taking place to get the key. I can't imagine how GnuPG could be stateless and provide forward secrecy. An ephemeral key must be stored up until the time the message is decrypted. For TLS, this is instant. Not so for GnuPG. – forest Feb 26 '18 at 13:06
  • I see. Yes I expect the program to have state, and keep the key in RAM, and I was hoping (but not requiring) that GnuPG would be able to be stateless. I'm not too worried about keys held in RAM being stolen. But I don't like the idea of "updating your public key to include freshly generated subkeys" - I was hoping for a kind of AKE deriving a shared secret like Diffie-Hellman. – user171587 Feb 26 '18 at 13:26
  • 1
    The only way that would be possible is if the encryption and decryption happened in one go. You would need to store the ephemeral key somewhere between the time of first encrypting it (after all, the sender needs to have the public key of the ephemeral keypair), and it getting decrypted (after which it is safe to delete the key). Unless you expect someone to decrypt your message the instant you send it out, you will need to store the key on your disk. – forest Feb 26 '18 at 13:31
  • 2
    No, what you are looking for requires a completely different architecture. GnuPG is fundamentally designed for asynchronous, offline encryption and decryption, not real-time communication. Perhaps you want to use OTR instead, which provides real-time communication along with forward secrecy. – forest Feb 26 '18 at 13:59

Your Answer

