Using asymmetric capabilities to secure files using GPG

In my previous posts I discussed how GPG can be used to encrypt a large file using a symmetric key (passphrase). Provided keys are changed regularly, this approach has clear advantages in terms of simplicity, speed, and authentication of the parties.

However the loss or theft of the key would break the security assumptions allowing attackers to snoop on data and potentially impersonate the origin host. A brute-force attack can easily be mounted against symmetric keys.

In addition, the key change procedure required to manage risk is laborious and the task of establishing keys and information exchange processes does not scale particularly well – to the square of the number of parties involved in fact O(n^2) where n is the number of communicating parties. The exchange of keys is also complicated and should be over a secure medium, face-to-face or secure couriers.

In my post I also mentioned that keys and certificates (more specifically, asymmetric cryptography), in some circumstances, could be regarded as preferable. What does this new approach offer?

Textbook answer follows! Advantages include vastly reduced complexity of the task – from O(n^2) to O(n), but that benefit will only become evident for large numbers of communicating entities. The security requirements of key distribution are much less, as the public key has no confidentiality requirement. In addition, a sender only has to possess the public key in order to encrypt a message rather than a more sensitive symmetric key. The disadvantages of pure asymmetric cryptography principally focus on vastly reduced speed, and a limited number of algorithms.

Fortunately GPG (and its commercial forebear, PGP) does not directly walk into this list. GPG does not operate in pure asymmetric mode, instead opting to use a hybrid of both techniques (A + S). However, as we will see, it does remain vulnerable to expiry risks, which presents a problem for automation.

To use GPG in this way, we can take the following steps.

Create the key pair for the recipient

Follow my previous blog post for the instructions to create a key pair for the recipient, and how to import the public key on the sending host. It is also important to create a certificate containing the signed public key on the target host.

This is a potential risk area in PGP/GPG. If a certificate has expired, the risk of encryption and transmission changes. In addition, a malicious user could generate or obtain a revocation certificate and distribute it, delivering a form of DoS.

Encrypt the file using the public key

The sending host should now have the public key of the recipient imported and signed as trusted. Along the way they would have verified the fingerprint of the public key, using a secure channel.

On the sending host, the file should be encrypted using the following command:

$ gpg --output [plaintext file].enc --encrypt --recipient [recipient email address] [plaintext file]

What has happened during this process? GPG employs its hybrid approach. It first creates a session key that is used to encrypt the file.

The hybrid key is then encrypted using the public key of the recipient. This delivers two encrypted outputs (the data and the symmetric key). Both are then packaged in the encrypted file as an octet stream in accordance with RFC 8880.

This package then makes its way to the recipient, who them uses GPG to decrypt the symmeric key and then the payload.

Decrypt the file using the private key

The recipient host can decrypt the file using the following command to use the embedded filename in the RFC 8880 file:

$ gpg --quiet --use-embedded-filename [encrypted file name]

Alternatively, the recipient can specify their own filename with either of the two (equivalent) commands:

$ gpg –decrypt [encrypted file name] > [target plaintext file name]

$ gpg –output [target plaintext file name] –decrypt [encrypted file name]


This scheme is more elaborate than the more straightforward symmetric approach, and there is greater scope for potential error (e.g. accidental disclosure of a private key).

We also encounter a lot more complexity in the ongoing management of this scheme, which may prove difficult to justify for minor applications. Assuming time-limited certificates, they will eventually expire and greater work is needed to maintain a working configuration.

PGP’s (and GPG’s) unique advantage here is the combination of both encryption approaches, which delivers speed and enhanced security in the form of public/private keys.

We are also able to make use of revocation certificates, which can ensure certificates that are compromised or superseded are no longer used.

There are many other benefits GPG offers that are not discussed in this article, including ways of signing public keys to demonstrate trust. It’s well worth taking a look and seeing what the art of the possible is.

GPG and key generation

In this post I’m walking through the process of creating a GPG key. This is needed for GPG operations that require either the public or private key for encryption or signing, respectively. I’ll be referring to this post in a future post where I talk about the combination of PKC and GPG to support secure file transfer.

Note: in this context, GPG generates keys most of the time. A certificate is created when we sign the public key using our private key. We also generate a certificate when a revocation certificate is generated at the key generation stage or afterward.

Generating the keys

The process for creating GPG keys is very straightforward, as the GPG executable will walk the user through the steps required:

$ gpg --generate-key

This produces a new key pair using a set of default parameters. This also generates a revocation certificate, which is stored within the GPG home directory.

You can also access a more comprehensive set of options by using the alternate command, –full-gen-key, which I recommend.

The options presented will be as follows:

  • Key type. The default is to generate two RSA keys. You can also produce an Elgamal key. My advice is to stick with RSA for both.
  • Key size. Lots of discussion can be found on this point. The default of 3072 is adequate, and 4096 is also an option.
  • Key expiry. Unless there are exceptionally strong requirements to have a non-expiring key (you may need mitigating controls if done so), set the key expiry to a reasonable value. The OpenPGP best practice is regarded to be less than two years. My recommendation is one year.
  • Identity (name, email address, comment). GPG will construct the identification string as “Name (comment) <email>”. There is no requirement to use a valid email address, but I’d recommend creating one that is unique and corresponds to a domain or in some way is controllable by you.
  • Passphrase. This protects access to the private key and should be a strong password.

Exporting the public key

The public key for user A must be known to user B in order for them to send information securely to A. There are no particular confidentiality requirements for the public key however the integrity of the key should be maintained. For this reason it is recommended to distribute the public key in a secure way, e.g. over HTTPS.

$ gpg --armor  --emit-version  --emit-version --emit-version --export [email address for the key pair] > output-public-key.gpg.armor

The command above outputs armored (ASCII) public key that can be sent over email. This is the predominant format for public keys on the Internet. The version string can be controlled by reducing the number of “emit-version” switches or removing them entirely.

Considerations about version strings

The version string is not used by any current implementations of GPG and disclosing version strings is usually advised against due to potential profiling of software vulnerabilities.  However, some reasons why you might want to retain the version string:

  • In case future versions of GPG change the way keys are processed, meaning the version string could be used in the future to ensure correct operation
  • Potentially improving interoperability between communicating parties in some way, along the same lines as above

Distributing the public key

The public key can be uploaded to a key server or distributed in some other way, and can be done so in the clear without any additional encryption (except if you’re using it for integrity).

Your public key can also be sent directly from GPG to a public keyserver, as follows:

$ gpg --send-keys --keyserver [email address of public key]

Importing a public key

On other systems the public key should be imported once retrieved. For GPG, this can be accomplished using the following command:

$ gpg --import <key file name>

When importing the public key, care should be taken to verify the key is in fact the expected key. This is usually achieved by comparing the fingerprints of the file as follows:

$ gpg --fingerprint [email address of the public key]

The output will be a string of hex quads that should be checked with the key originator.

Finally, sign the key that is imported if you are satisfied it can be trusted:

$ gpg --sign-key [email address of the public key]