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]