Nicolas Martyanoff — Brain dump About

Using GnuPG

Edit (2023-02-07)
Updated to mention subkey selection during renewal.

Introduction

I recently tried to learn more about GnuPG and it turned out to be more difficult than expected. So here are my notes regarding various GnuPG operations.

GnuPG 2.2.32 was used for all commands.

Configuration

GnuPG

The gpg command line tool looks for $HOME/.gnupg/gpg.conf.

Options are provided using the command line arguments used by the gpg program without the -- prefix. For example:

verbose

causes GnuPG to behave as if the --verbose option was passed to every command.

I went with the following configuration:

# Do not print any greeting message
no-greeting

# Do not include comment or version numbers in signatures
no-comments
no-emit-version

# Display long key ids to minimize collision risks
keyid-format long

# Set preferences when signing and encrypting
# Use gpg --version to see available algorithms
personal-digest-preferences SHA256
personal-cipher-preferences AES256
personal-compress-preferences ZLIB

# Use AES256 as default cipher
cipher-algo AES256

# Use SHA256 as default digest
digest-algo SHA256
cert-digest-algo SHA256

# Use ZLIB as default compression algorithm
compress-algo ZLIB

# Always export in ASCII format by default
armor

Password prompts

GnuPG uses the pinentry collection of programs to prompt for passwords. We can configure the GPG agent to always use the terminal version of pinentry instead of spawning a graphical prompt.

The agent is configured in $HOME/.gnupg/gpg-agent.conf; to use the terminal prompt, set the following option:

pinentry-program /usr/bin/pinentry-tty

Note that the agent has to be restarted after any modification:

gpgconf --reload gpg-agent

Managing keys

Creating a key

Use the --full-gen-key option to create a new key. The --gen-key option can also be used but offer less control on the process.

The --expert option can also be used to access more advanced features such as ECC support.

The process is interactive.

Once created, the new key should be visible in the list of keys which can be visualized with gpg --list-keys.

Using multiple identities

A key can contain multiple identities. Edit the key with gpg --edit-key <key-id> and use the adduid command to add a new identity. You then need to trust the new identity. Use the uid <n> command to select the new uid, and run the trust command to select the trust level (probably ultimate since this is your own key). Make sure to use the primary command to select the current identity as the main one. Use the save command to write the modification and exit.

Note that modifying the list of identities changes the public key. If you published it, you will need to update it.

Deleting a key

Keys can be deleted using gpg --delete-secret-keys <key-id> and gpg --delete-keys <key-id>. Note that the secret key must be deleted before the associated public key.

Using subkeys

Newly created keys contain a public key, a secret key which can be used for signing and certifying other signatures, and a secret subkey which can be used for encryption.

It is a good idea to store the signing secret key in a safe location and to generate new signing subkeys for each device which will need to sign content. This way, if a device is compromised, one can revoke the associated signing subkey and generate a new one without compromising the primary identity which is guaranteed by the primary signing key.

To create a new subkey, edit the key with gpg --edit-key <keyid> and use the addkey command. Again, the --expert option can be passed to the --edit-key command to be able to create ECC keys. The addkey command will ask for a kind of key; to create a signing sub key, opt to “set your own capabilities”, and select the sign and authenticate capabilities. Use the save command to write the modification and exit.

At this point, it is possible to export both the new signing subkey and the encryption subkey and import then on the new device. Take care too use the ! suffix to only export these subkeys, as described in the next section. For example:

gpg --export-secret-keys <signing-subkey-id>! <encryption-subkey-id>!

If you want to remove the primary secret key from the local GnuPG directory, first obtain its keygrip using gpg --with-keygrip --list-secret-keys, then delete the key stored in $HOME/.gnupg/private-keys-v1.d/<keygrip>.key. You can check that the primary secret key is not here anymore: when listing secret keys, the deleted key type will have the # suffix, e.g. sec#.

Exporting keys

The most obvious way to share public keys is to export them from the local keyring. The keyring is stored in $HOME/.gnupg/pubring.kbx.

The gpg --export <user-id> command outputs one or more public keys associated with a user id. Note that there are multiple way to select a user id. See the official documentation for more information.

Using the key id or the email address is the simplest way to select the public key.

Secret key exports works the same way but use the --export-secret-key command. Note that exporting a subkey will by default export the entire secret key. Add a ! suffix to the key id to export a single subkey.

When backing up keys, use --export-options backup to include all necessary data for later restoration.

Publishing a key

Public keys can be published on internet servers to make it easier for other people to download them.

Note that the presence of a key on a public server does not imply it actually belong to the person identified by the key: anyone can generate keys using any name or email address.

Also remember that published keys can never be deleted.

To publish a key, simply use gpg --keyserver <address> --send-keys <key-id>.

Importing a key

Public and private keys can be imported in the local keyring, making them available for verification or decryption. Simply gpg --import <file>. It is also possible to pipe the public key directly into gpg --import.

Revoking a key

Compromised keys must be revoked to signal that someone other than the owner of the key has access to it.

Revocation uses a revocation certificate which is generated from the private key using gpg --gen-revoke <key-id>. The command is interactive and asks for the reason of the revocation.

The revocation certificate can then be imported or published like any other public key. After importing a revocation certificate in a keyring, the key will be marked as revoked.

Renewing a key

If a key has an expiration date, it may need to be renewed. This can be done by editing the key. Start the edition shell using gpg --edit-key <key-id>, and select the subkey you want to modify using the key <index> command. Then run the expire interactive command. You can then write the modification and exit with save.

Do not forget to backup the new version of the private key and to publish the new version of the public key.

Note that you should generate and backup a new revocation certificate.

Using keys

Encrypting a file

Data are encrypted using gpg --encrypt --recipient <key-id>, and decrypted using gpg --decrypt. Encrypted messages contain the key id; decrypting the file requires the presence of the associated secret key in the local GnuPG directory.

Signing a file

Data are signed using gpg --sign <file>. The output contains both the data and the signature.

Signed data are verified using gpg --verify.

It is also possible to generate a separate — or detached — signature using gpg --detach-sig, e.g.:

gpg --output my-file.asc --detach-sig my-file
gpg --verify my-file.asc my-file

Share the word!

Liked my article? Follow me on Twitter or on Mastodon to see what I'm up to.