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