OpenPGP Key Management HowTo

1. Introduction

1.1. About

This document describes the steps of managing OpenPGP keys which are in particular the topics generation, certification, modification, and revocation. Other topics related to mere usage, like encrypting and signing data, are also treated briefly where applicable but do not have high priority.

1.2. Scenario

The underlying scenario of this document is having two separate keys, a working key for daily usage and an offline key for special use cases:

The actual interpretations of "trustworthy", "secure", etc. have to be specified by each individual user. The principle of prudence should establish the baseline.

1.3. Audience

You should already be familiar at least with the basic concepts of public-key cryptography and should also know the differences between asymmetric and symmetric cryptosystems.

You should run a GNU/Linux system. If you are running a different operating system you may consider most parts of this document helpful, too.

Applications with graphical user interfaces are not used in this document because they hide too much information on the exact working methods and the context of the intended actions. Further on, the degree of delegating trust and control from the user over to some software is retained as low as possible. A good look-and-feel is reasonably considered as a major con in this context. Therefore, you also should feel comfortable with working on the command line.

Finally and also to clarify things in the first place: This document will not be suitable for those computer users who instinctively click on all buttons presented to them, in order to quickly proceed under all circumstances with some actions that they do not (want to) understand and the possibly harmful consequences of which for others or for themselves they are not interested in.

Please note

OpenPGP key management is a complex subject. You should not be discouraged. But you should not expect to get through it in just a few minutes either.

1.4. Status and Versions

This document fully covers the scenario described above and provides enough references to allow a deeper research of the technical backgrounds. However, its style and its structure are considered as a work in progress. Also, some possibly useful but rather secondary aspects might be added later.

The latest version of this document is available at https://wiki.lug-in.de/OpenPGP/KeyManagementHowTo.

This document is also available in plain text, HTML or PDF format.

For a short history of this document see the section History below.

Creative Commons License The OpenPGP Key Management HowTo by Mathias Bauer is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

1.6. Acknowledgement

This document would not have been possible without the help and the input of many people. I want to say thank you to

2. Prerequisites

For operating on OpenPGP keys, an installation of the GNU Privacy Guard (GnuPG) is required, which is recent to some extent.

   1 $ gpg --verbose --version
   2 gpg (GnuPG) 1.4.12
   3 Copyright (C) 2012 Free Software Foundation, Inc.
   4 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
   5 This is free software: you are free to change and redistribute it.
   6 There is NO WARRANTY, to the extent permitted by law.
   7 
   8 Home: ~/.gnupg
   9 Supported algorithms:
  10 Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA
  11 Cipher: 3DES (S2), CAST5 (S3), BLOWFISH (S4), AES (S7), AES192 (S8),
  12         AES256 (S9), TWOFISH (S10), CAMELLIA128 (S11), CAMELLIA192 (S12),
  13         CAMELLIA256 (S13)
  14 Hash: MD5 (H1), SHA1 (H2), RIPEMD160 (H3), SHA256 (H8), SHA384 (H9),
  15       SHA512 (H10), SHA224 (H11)
  16 Compression: Uncompressed (Z0), ZIP (Z1), ZLIB (Z2), BZIP2 (Z3)

Other versions of GnuPG, especially patched ones like the one from the Debian GNU/Linux 'wheezy' (stable) release shown above or newer ones, may work as well.

Using a GNU/Linux live system like Debian GNU/Linux Live is strongly recommended because it will completely "live" in the computer's memory during runtime and therefore it does not leave any digital traces on the hard disk(s).

For further details, see the reference section Software below.

Also there should be several storage devices ready, e. g., USB sticks or SD cards. Of course, these devices should not be used for any other purpose.

3. Configuration

Two different configurations have to be developed, as already indicated in the section Scenario above:

A good rule of thumb for changing configurations is to keep the defaults. However, depending on the above scenario and on general considerations, changing some of GnuPG's settings is really recommended.

The following subsections try to group the settings usefully and discuss the details and the differences between the offline and the working configuration:

Where applicable, a short justification is given for a change. For further details, see the GnuPG manual page and the section References below.

Two example configuration files are provided: gpg-working.conf and gpg-offline.conf. Each of them must be renamed to gpg.conf in the respective environment's GnuPG home directory.

3.1. Keys

3.2. Key rings

One or several options keyring FILE can be used to make additional and maybe read-only key rings known to GnuPG (optional).

If the specified FILE begins with a tilde and a slash, these will be replaced by the HOME directory. If the filename does not contain a slash, it will assumed to be in the GnuPG home directory (~/.gnupg if --homedir or GNUPGHOME is not used).

3.3. Key servers

The offline environment is designed as a closed system. It must not use any key servers.

Any other lines with options keyserver ... should be commented out in the offline configuration.

The option no-auto-key-locate also is recommended for the working configuration. Although it is a reasonable assumption to consider neither the key servers and the data they provide nor their operators as trustworthy, key servers can surely be used in the working environment - but not automatically!

The following block lists the modifications discussed in this subsection. Note that the configuration file must not contain any line breaks.

no-auto-key-locate
keyserver-options no-auto-key-retrieve check-cert no-honor-keyserver-url \
    no-honor-pka-record include-disabled include-revoked include-subkeys \
    debug verbose verbose verbose

As most of the key servers synchronize their data, it's a good idea to use a (regional) key server pool that directs each connection via round robin DNS to a certain server. In addition to the above configuration block, use

keyserver hkp://pool.sks-keyservers.net

The more secure HKPS protocol, which is HKP secured by TLS/SSL, should really be considered using instead. Download the X.509 certificate sks-keyservers.netCA.pem, verify it and replace the above setting by:

keyserver hkps://hkps.pool.sks-keyservers.net \
    ca-cert-file=/absolute/path/to/CA/sks-keyservers.netCA.pem

For further details, see the reference section Key servers below. There is an overview of the SKS key server pools of Kristian Fiskerstrand together with some statistical data. And there is also a detailed description about the OpenPGP HTTP Keyserver Protocol (HKP) by David Shaw.

3.4. Signatures and trust

The following block lists the modifications discussed in this subsection.

no-ask-cert-level
default-cert-level 0
min-cert-level 2
ask-cert-expire
default-cert-expire 0
auto-check-trustdb
completes-needed 1
marginals-needed 3
max-cert-depth 5
require-cross-certification
trust-model pgp
force-v4-certs
no-force-v3-sigs
ask-sig-expire
default-sig-expire 0
sig-notation issuer-fpr@notations.openpgp.fifthhorseman.net=%g

3.5. Algorithms

The following tables present an overview of the algorithms defined by the OpenPGP standards RFCs 4880 (2007) and its extensions RFC 5581 (2009) and RFC 6637 (2012). The column "GnuPG" lists the text name used by GnuPG, e.g., for the configuration. The column "Level" shows whether the respective algorithm may, should or must be implemented in a standard-compliant software.

Public-key algorithms

ID

Description and definition

GnuPG

Level

1

RSA (Encrypt or Sign) [ HAC ]

RSA

SHOULD

2

RSA Encrypt-Only [ HAC ]

RSA-E

deprecated

3

RSA Sign-Only [ HAC ]

RSA-S

deprecated

16

Elgamal (Encrypt-Only) [ ELGAMAL, HAC ]

ELG-E

MUST

17

DSA (Digital Signature Algorithm) [ FIPS186, HAC ]

DSA

MUST

18

ECDH public key algorithm [ RFC6637 ]

MUST

19

ECDSA public key algorithm [ FIPS186, RFC6090, SEC1 ]

MUST

20

Reserved (formerly Elgamal Encrypt or Sign)

21

Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME)

Symmetric-key algorithms

ID

Description and definition

GnuPG

Level

0

Plaintext or unencrypted data

MAY

1

IDEA [ IDEA ]

MAY

2

TripleDES (DES-EDE, 168 bit key derived from 192) [ SCHNEIER, HAC ]

3DES

MUST

3

CAST5 (128 bit key) [ RFC2144 ]

CAST5

SHOULD

4

Blowfish (128 bit key, 16 rounds) [ BLOWFISH ]

BLOWFISH

MAY

5

Reserved

6

Reserved

7

AES with 128 bit key [ AES ]

AES

SHOULD

8

AES with 192 bit key [ AES ]

AES192

MAY

9

AES with 256 bit key [ AES ]

AES256

MAY

10

Twofish with 256 bit key [ TWOFISH ]

TWOFISH

MAY

11

Camellia 128 bit key [ RFC3713 ]

CAMELLIA128

MAY

12

Camellia 192 bit key [ RFC3713 ]

CAMELLIA192

MAY

13

Camellia 256 bit key [ RFC3713 ]

CAMELLIA256

MAY

Hash algorithms

ID

Description and definition

GnuPG

Level

1

MD5 [ HAC ]

MD5

deprecated

2

SHA-1 [ FIPS180 ]

SHA1

MUST

3

RIPE-MD/160 [ HAC ]

RIPEMD160

MAY

4

Reserved

5

Reserved

6

Reserved

7

Reserved

8

SHA256 [ FIPS180 ]

SHA256

MAY

9

SHA384 [ FIPS180 ]

SHA384

MAY

10

SHA512 [ FIPS180 ]

SHA512

MAY

11

SHA224 [ FIPS180 ]

SHA224

MAY

Data compression algorithms

ID

Description and definition

GnuPG

Level

0

Uncompressed

Uncompressed

MUST

1

ZIP [ RFC1951 ]

ZIP

SHOULD

2

ZLIB [ RFC1950 ]

ZLIB

MAY

3

BZip2 [ BZ2 ]

BZIP2

MAY

Use the listing presented in the section Prerequisites above to examine the current GnuPG's capabilities. Note that the elliptic curve algorithms have not yet been implemented in the GnuPG version which is used for this document. (This is only a minor drawback as these algorithms are not widely used yet.)

For further details, see the reference sections Algorithms and Recommendations below.

Note that there are many purposes for the selection of the algorithms below. First, only secure algorithms are selected, of course. Deprecated or even broken ones are certainly not specified. Also, the basic tenor for recommendations in this document is to avoid a cryptographic monoculture. However, this is a rather political question.

The following block lists the modifications discussed in this subsection. Note that the configuration file must not contain any line breaks.

cert-digest-algo SHA512
enable-dsa2
personal-cipher-preferences AES256 CAMELLIA256 TWOFISH AES192 CAMELLIA192 \
    AES CAMELLIA128 CAST5 3DES
personal-digest-preferences SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1
personal-compress-preferences BZIP2 ZLIB ZIP Uncompressed
default-preference-list AES256 CAMELLIA256 TWOFISH AES192 CAMELLIA192 AES \
    CAMELLIA128 CAST5 3DES SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1 \
    BZIP2 ZLIB ZIP Uncompressed

3.6. Security and privacy

Operating with OpenPGP key material should not emit more information as is absolutely necessary, i. e., no (unnecessary) user IDs, no comments, no version strings, etc.

For a comparison and for details of the algorithms specified in this subsection, see the previous subsection as well as the reference sections Algorithms and Recommendations below.

The following block lists the modifications discussed in this subsection. Note that the configuration file must not contain any line breaks.

no-allow-freeform-uid
no-allow-non-selfsigned-uid
no-comments
no-default-recipient
no-emit-version
exit-on-status-write-error
force-mdc
no-greeting
require-secmem
s2k-cipher-algo AES256
s2k-digest-algo SHA512
verify-options no-pka-lookups no-pka-trust-increase show-keyserver-urls \
    show-notations no-show-photos show-policy-urls \
    no-show-primary-uid-only show-uid-validity show-unusable-uids

3.7. Miscellaneous

The following block lists the modifications discussed in this subsection. Note that the configuration file must not contain any line breaks.

compress-level 9
bzip2-compress-level 9
display-charset utf-8
utf8-strings
keyid-format long
list-options show-keyring show-keyserver-urls show-notations \
    no-show-photos show-policy-urls show-sig-expire show-uid-validity \
    show-unusable-subkeys show-unusable-uids
photo-viewer /bin/true

4. Structure of an OpenPGP key

Speaking about "the OpenPGP key" actually is lax and misleading at least. When looking at the details, it is very irritating, too. In fact there are several keys and even more several non-key components forming altogether an OpenPGP key. This section explains the basics of its structure.

For example, in the figure above, the secret part consists of the packets (1) to (3) and the public part consists of the packets (4) to (6). Also, there is a main key which consists of the packets (1) and (4). And there are two subkeys: the first one consists of the packets (2) and (5), the second one of the packets (3) and (6).

Subkeys, in general, will be needed if the cryptographic functionality is split into several keys, which is usually regarded as a good thing. This includes

For further details on subkeys, see the Debian wiki article Using OpenPGP subkeys in Debian development in the reference section Articles below.

Keep the scheme above in mind when generating the offline key and the working key. This is covered by the section Create a new offline/working key below. It is very important to realize, that the offline key will consist of the packets (1) to (6), but the working key will have the packet (1) stripped off!

So far, only components of an OpenPGP key with real "key material" have been described. This means, loosely speaking, those (very large) numbers, that the cryptographic algorithms and the underlying mathematics are based upon. However, there are other components beyond that, too. The figure below shows the public part of an OpenPGP key:

As the figure above shows, signature packets form the glue between the main key and the user IDs on the one hand. On the other hand, they also bind together the main key and the subkeys. There are several different types of signature packets. The following ones are commonly seen on OpenPGP keys:

The secret part of an OpenPGP key looks quite similar.

For further details, see the very well written OpenPGP standard RFC 4880 in the References section below.

5. Setup the offline environment

As already mentioned in the section Scenario above, setting up the offline environment depends on the subjective interpretation of "trustworthy", "secure", etc. Therefore, the following list serves as an example.

The actual steps related to the above actions remain beyond the scope of this document.

Make a typescript of everything printed on the terminal during the session. Use the script program to create the log file session-offline-YYYY-MM-DD.log. Finally, exit the forked shell to finish logging.

$ script -f /path/to/session-offline-YYYY-MM-DD.log

Adjust the localization settings to unify the output language. Translations of GnuPG, although being quite complete, may use some formulation which may give a wrong understanding and then may lead to wrong decisions related to security.

$ export LC_ALL=C.UTF-8

All operations will take place in a separate directory which is located on a temporary filesystem (tmpfs). Hence, this directory will totally reside in memory and digital traces on any hard disk(s) will be avoided. The directory /tmp commonly uses tmpfs. For further details, see /etc/fstab. Set the GNUPGHOME environment variable to ensure that GnuPG will use this directory instead.

$ umask 77
$ mkdir /tmp/work
$ export GNUPGHOME=/tmp/work

Optionally kill a running GnuPG agent process. At least unset the environment variables GPG_AGENT_INFO and GPG_TTY.

$ killall -v gpg-agent
$ unset GPG_AGENT_INFO GPG_TTY

Before continuing check the GnuPG configuration file gpg.conf and ensure that it's the correct one for the offline environment. The configuration file must be located in the directory specified by GNUPGHOME. For further details, see the Configuration section above.

Now, the offline environment is setup.

6. Create a new offline/working key

Setup the offline environment as described in the previous section.

The following subsections show the steps to create a new offline key and a new working key according to the underlying scenario described in the section Scenario above.

6.1. Create the main key

The main key is a 4096 bit RSA sign-only key. It should expire in five years at most. The key's validity can simply be extended near the end of this period of time.

   1 $ gpg --gen-key
   2 Please select what kind of key you want:
   3    (1) RSA and RSA (default)
   4    (2) DSA and Elgamal
   5    (3) DSA (sign only)
   6    (4) RSA (sign only)
   7 Your selection? 4
   8 RSA keys may be between 1024 and 4096 bits long.
   9 What keysize do you want? (2048) 4096
  10 Requested keysize is 4096 bits
  11 [...]
  12 Key is valid for? (0) 2020-02-01
  13 Key expires at Fri 01 Feb 2020 12:00:00 AM CET

The (first) user ID should only contain a real name. Just do not specify an email address. A comment on user IDs should almost always be omitted, too. For further details, see Daniel Kahn Gillmor's article OpenPGP user ID comments considered harmful in the reference section Articles below.

  14 You need a user ID to identify your key; the software constructs the user ID
  15 from the Real Name, Comment and Email Address in this form:
  16     "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
  17 
  18 Real name: John Q. Example
  19 Email address:
  20 Comment:
  21 You selected this USER-ID:
  22     "John Q. Example"
  23 
  24 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

Choose a short dummy passphrase because it is needed very often in the next steps of the process. But do not use an empty passphrase!

  25 You need a Passphrase to protect your secret key.
  26 
  27 Enter passphrase: ***
  28 Repeat passphrase: ***

Follow the instructions.

  29 pub   4096R/2F3894F9C5688391 2014-12-05 [expires: 2020-01-31]
  30       Key fingerprint = 9E3C 32C1 4F32 002B EC79  605A 2F38 94F9 C568 8391
  31 uid               [ultimate] John Q. Example

For simplicity, create an environment variable with the key ID.

$ export KEYID=2F3894F9C5688391

6.2. Update the configuration file

The configuration file gpg.conf of the offline environment must be updated. Set the option trusted-key with the new key's ID as argument (16 characters):

trusted-key 2F3894F9C5688391

Of course, the configuration file of the working environment should also be updated. For further details, see the top of the section Configuration above.

6.3. Add two subkeys

For daily usage, two 3072 bit RSA subkeys are created: the first one for signing and the second one for encryption. Both subkeys should roughly be valid for one year and should expire at the same date. If desired, their validity can simply be extended near the end of this period of time. For further details, see the Debian Wiki article Using OpenPGP subkeys in Debian development in the reference section Articles below.

To add a subkey use addkey. To list all keys and user IDs use list. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> addkey
   3 [...]
   4 Please select what kind of key you want:
   5    (3) DSA (sign only)
   6    (4) RSA (sign only)
   7    (5) Elgamal (encrypt only)
   8    (6) RSA (encrypt only)
   9 Your selection? 4
  10 RSA keys may be between 1024 and 4096 bits long.
  11 What keysize do you want? (3072)
  12 Requested keysize is 3072 bits
  13 [...]
  14 Key is valid for? (0) 2016-02-01
  15 Key expires at Sun 01 Feb 2016 12:00:00 AM CET
  16 [...]
  17 gpg> addkey
  18 [...]
  19 Your selection? 6
  20 RSA keys may be between 1024 and 4096 bits long.
  21 What keysize do you want? (3072)
  22 Requested keysize is 3072 bits
  23 [...]
  24 gpg> list
  25 pub  4096R/2F3894F9C5688391  created: 2014-12-05  expires: 2020-01-31  usage: SC
  26                              trust: ultimate      validity: ultimate
  27 sub  3072R/8CB8E0FFDADD3834  created: 2014-12-05  expires: 2016-01-31  usage: S
  28 sub  3072R/3EF8C012214CDCB3  created: 2014-12-05  expires: 2016-01-31  usage: E
  29 [ultimate] (1). John Q. Example
  30 gpg> save

The listing above shows the main key and the two subkeys with their usage flags:

6.4. Add further user IDs

The key may be equipped with further user IDs with real names and email addresses. As above, comments should almost always be omitted.

To add a user ID use adduid. To list all keys and user IDs use list. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> adduid
   3 [...]
   4 gpg> list
   5 [...]
   6 [ultimate] (1)  John Q. Example
   7 [ unknown] (2)  John Q. Example <john@example.com>
   8 [ unknown] (3). John Example <jonny@example.net>
   9 gpg> save

The listing above shows "unknown" trust values for the new user IDs because they are calculated after saving the key.

6.5. Specify the primary user ID

If there are several user IDs, one of them should be manually marked as primary user ID. Usually this should be the user ID without an email address.

To select or unselect a user ID use uid N. To make the selected user ID the primary one use primary. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> uid 2
   3 [ultimate] (1). John Example <jonny@example.net>
   4 [ultimate] (2)* John Q. Example
   5 [ultimate] (3)  John Q. Example <john@example.com>
   6 gpg> primary
   7 [...]
   8 gpg> list
   9 [...]
  10 [ultimate] (1)  John Example <jonny@example.net>
  11 [ultimate] (2)* John Q. Example
  12 [ultimate] (3)  John Q. Example <john@example.com>
  13 gpg> save

6.6. Create a revocation certificate

To be prepared for the worst case which is the compromising or lost of the offline key, a revocation certificate must be created now.

You should almost never provide any reason for the revocation if asked. The revocation itself is a sufficient statement. Do not specify any optional description either. But perhaps it is a good idea to create even several revocation certificates for each of the provided reasons.

   1 $ gpg --output revoke.asc --gen-revoke $KEYID
   2 sec  4096R/2F3894F9C5688391 2014-12-05 John Q. Example
   3 
   4 Create a revocation certificate for this key? (y/N) y
   5 Please select the reason for the revocation:
   6   0 = No reason specified
   7   1 = Key has been compromised
   8   2 = Key is superseded
   9   3 = Key is no longer used
  10   Q = Cancel
  11 (Probably you want to select 1 here)
  12 Your decision? 0
  13 Enter an optional description; end it with an empty line:
  14 >
  15 Reason for revocation: No reason specified
  16 (No description given)
  17 Is this okay? (y/N) y

Move this revocation certificate to a medium which can be hidden at some safe place. For example, if you rate paper as more secure than bits and bytes, you might even print the revocation certificate because it is in ASCII format. In this case it is wise to print its checksum, too, in order to detect errors when retyping it to its digital form.

$ gpg --print-mds revoke.asc > revoke.sum
$ cat revoke.asc revoke.sum > revoke.txt

The file revoke.txt contains all information needed and can be printed.

Warning

  1. There is no passphrase needed to revoke a key.

  2. If the revoked key is published, the revocation cannot be undone.
  3. If the revoked key is not published, the revocation can be undone only if there is a backup.

Therefore, destroy all digital traces of the revocation certificate after it has been saved away.

6.7. Export the offline/working key

The dummy passphrase set above for the generation process only is now replaced. Two strong passphrases are needed:

Note that if you forget the working key's passphrase, you can easily reset it. For details see either this section or the section Export the offline/working key below. But if you forget the offline key's passphrase, you can still use all your keys and subkeys just as long as they are valid. After that you will have to regenerate them completely. Be prepared to avoid this show-stopper.

To set the offline key's passphrase use passwd. To remove any unusable signatures, which in this case are internal ones only, use clean. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> passwd
   3 [...]
   4 gpg> clean
   5 [...]
   6 gpg> save

Export the key components to files in ASCII format. Perhaps it is a good idea to add a timestamp YYYY-MM-DD to the filenames. For the sake of brevity this document does not.

$ gpg --armor --export $KEYID > public.asc
$ gpg --armor --export-secret-keys $KEYID > offline-secret.asc
$ gpg --armor --export-secret-subkeys $KEYID > working-secret.asc

Ensure that the above three commands are executed successfully. After that, remove the key rings.

$ rm pubring.gpg secring.gpg

Import only the files working-secret.asc and public.asc.

$ gpg --import working-secret.asc public.asc

To set the working key's passphrase use passwd. To remove any unusable signatures, which in this case are internal ones only, use clean. Finally save and quit.

   7 $ gpg --edit-key $KEYID
   8 gpg> passwd
   9 [...]
  10 gpg> clean
  11 [...]
  12 gpg> save

Remove the file working-secret.asc and export the respective key components again with the modified passphrase to this file in ASCII format. Perhaps it is a good idea to add a timestamp YYYY-MM-DD to the filename. For the sake of brevity this document does not.

$ rm working-secret.asc
$ gpg --armor --export-secret-subkeys $KEYID > working-secret.asc

Ensure that the above command was executed successfully.

The three resulting files contain different key components. For reference, see the section Structure of an OpenPGP key above.

The next step is grouping the files for the two environments. They must be stored on two different storage devices.

Next, save the two different configuration files, named gpg.conf, which were adapted near the beginning of the key generation process above.

Also, do not forget the revocation certificate revoke.asc. It will also have to be saved if it is not printed in the previous subsection. The revocation certificate should absolutely be kept apart from the working key files and it is not recommended either to save it together with the offline key files. A third storage device, which eventually is paper, is really recommended.

Warning

It is not possible to use only one storage device because in this case connecting it to some working machine will inevitably imply exposing the offline key files. The initial interpretation of the word "offline" in the section Scenario should be followed strictly.

Any temporary or less-than-ideal solution may break your security.

All files must really be located on the respective storage devices before unmounting them. Finally, clean up the offline environment and shut down the system.

7. Install the working key

The following steps will apply if a new GnuPG setup is established or if the working key should be integrated into some existing GnuPG setup.

Import the files working-secret.asc and public.asc.

$ gpg --import working-secret.asc public.asc

If there is an error with the previous command, it will help to create a backup of the existing key rings, to completely remove them, and to import the files and the backup files afterwards again.

$ mv -i secring.gpg secring-backup.gpg
$ mv -i pubring.gpg pubring-backup.gpg
$ gpg --import working-secret.asc public.asc
$ gpg --import secring-backup.gpg pubring-backup.gpg

For simplicity, create an environment variable with the key ID.

$ export KEYID=2F3894F9C5688391

Initialize or update the web of trust.

$ gpg --trusted-key $KEYID --update-trustdb

To remove any unusable signatures, which in this case are internal ones only, use clean. Finally save and quit.

$ gpg --edit-key $KEYID clean save

The working key is now fully functional.

   1 $ gpg --fingerprint --list-keys $KEYID
   2 pub   4096R/2F3894F9C5688391 2014-12-05 [expires: 2020-01-31]
   3       Key fingerprint = 9E3C 32C1 4F32 002B EC79  605A 2F38 94F9 C568 8391
   4 uid               [ultimate] John Q. Example
   5 uid               [ultimate] John Q. Example <john@example.com>
   6 uid               [ultimate] John Example <jonny@example.net>
   7 sub   3072R/8CB8E0FFDADD3834 2014-12-05 [expires: 2016-01-31]
   8 sub   3072R/3EF8C012214CDCB3 2014-12-05 [expires: 2016-01-31]
   9 $ gpg --list-secret-keys $KEYID
  10 sec#  4096R/2F3894F9C5688391 2014-12-05 [expires: 2020-01-31]
  11 uid                          John Q. Example
  12 uid                          John Q. Example <john@example.com>
  13 uid                          John Example <jonny@example.net>
  14 ssb   3072R/8CB8E0FFDADD3834 2014-12-05 [expires: 2016-01-31]
  15 ssb   3072R/3EF8C012214CDCB3 2014-12-05 [expires: 2016-01-31]

The # after the letters sec means that the secret main key is not usable. In fact, it is missing completely. For details, see the section Structure of an OpenPGP key above.

8. Certify a key with the offline key

Setup the offline environment as described in the section above.

Get the offline key from its safe place and import the files offline-secret.asc and public.asc.

$ gpg --import offline-secret.asc public.asc

In this example Jane Smith's key should be certified. This document leaves out all aspects related of identity checking and policy matters. As to the key's user ID, it is assumed

So, import the public key to be certified.

   1 $ gpg --verbose jane-smith.asc
   2 pub  2048R/A74017B3538266D1 2013-06-09 Jane Smith <jsmith@example.org>
   3 sig        A74017B3538266D1 2013-06-09   [selfsig]
   4 sub  2048R/CA15902BE41C84FD 2013-06-09 [expires: 2018-06-08]
   5 sig        A74017B3538266D1 2013-06-09   [keybind]
   6 $ gpg --import jane-smith.asc
   7 gpg: key A74017B3538266D1: public key "Jane Smith <jsmith@example.org>" imported
   8 gpg: Total number processed: 1
   9 gpg:               imported: 1  (RSA: 1)

For simplicity, create an environment variable with Jane Smith's key ID.

$ export KEYID=A74017B3538266D1

To list all keys and user IDs use list. To check the key's certification signatures use check. Take care that a self-signature is present for each user ID. To verify its fingerprint use fpr. To select or unselect a user ID use uid N. Not selecting any user ID means working on all of them. To certify the selected one(s) use sign. To remove any unusable signatures afterwards use clean. Finally save and quit.

  10 $ gpg --edit-key $KEYID
  11 gpg> list
  12 pub  2048R/A74017B3538266D1  created: 2013-06-09  expires: 2018-06-08  usage: SC
  13                              trust: unknown       validity: unknown
  14 sub  2048R/CA15902BE41C84FD  created: 2013-06-09  expires: 2018-06-08  usage: E
  15 [ unknown] (1). Jane Smith <jsmith@example.org>
  16 
  17 gpg> check
  18 uid  Jane Smith <jsmith@example.org>
  19 sig!3        A74017B3538266D1 2013-06-09 never       [self-signature]
  20 
  21 gpg> fpr
  22 pub   2048R/A74017B3538266D1 2013-06-09 Jane Smith <jsmith@example.org>
  23  Primary key fingerprint: 8417 30E4 A2A9 895C 433B  4E68 A740 17B3 5382 66D1
  24 
  25 gpg> sign
  26 pub  2048R/A74017B3538266D1  created: 2013-06-09  expires: 2018-06-08  usage: SC
  27                              trust: unknown       validity: unknown
  28  Primary key fingerprint: 8417 30E4 A2A9 895C 433B  4E68 A740 17B3 5382 66D1
  29 
  30      Jane Smith <jsmith@example.org>
  31 
  32 This key is due to expire on 2018-06-08.
  33 Do you want your signature to expire at the same time? (Y/n) n
  34 Please specify how long the signature should be valid.
  35          0 = signature does not expire
  36       <n>  = signature expires in n days
  37       <n>w = signature expires in n weeks
  38       <n>m = signature expires in n months
  39       <n>y = signature expires in n years
  40 Signature is valid for? (0) 0
  41 Signature does not expire at all
  42 Is this correct? (y/N) y
  43 Are you sure that you want to sign this key with your
  44 key "John Q. Example" (2F3894F9C5688391)
  45 
  46 Really sign? (y/N) y
  47 [...]
  48 gpg> clean
  49 [...]
  50 gpg> save

Export the certified key to a file in ASCII format and copy it to the storage device.

  51 $ gpg --armor --export $KEYID > jane-smith-certified.asc
  52 $ gpg --verbose jane-smith-certified.asc
  53 pub  2048R/A74017B3538266D1 2013-06-09 Jane Smith <jsmith@example.org>
  54 sig        A74017B3538266D1 2013-06-09   [selfsig]
  55 sig        2F3894F9C5688391 2014-12-06   John Q. Example
  56 sub  2048R/CA15902BE41C84FD 2013-06-09 [expires: 2018-06-08]
  57 sig        A74017B3538266D1 2013-06-09   [keybind]

Ensure that the file is really located on the respective storage devices before unmounting them. Finally, clean up the offline environment and shut down the system.

Note that deleting a certification signature using delsig will not make sense provided the public key is already published (with this signature). As components can only be added to an OpenPGP key, the next refresh of the public key will bring back the deleted certification signature. It should be revoked instead using revsig.

9. Modify the offline/working key

Setup the offline environment as described in the section above.

Get the offline key from its safe place and import the files offline-secret.asc and public.asc.

$ gpg --import offline-secret.asc public.asc

For simplicity, create an environment variable with the key ID.

$ export KEYID=2F3894F9C5688391

Initialize or update the web of trust.

$ gpg --trusted-key $KEYID --update-trustdb

The offline key is now fully functional. The following subsections show some common use cases of modifying the offline key:

Finally, it is necessary to complete the modification actions with exporting the offline key and the working key again.

9.1. Add a subkey

Note that it is not necessary to add a new subkey if some existing one has expired. A new expiration date can simply be set to restore its validity. For details, see the next subsection.

Also note that the usage capabilities of encrypting (E) and signing data (S) must be provided entirely by the subkeys. In this case, the main key's capabilities do not matter because it is not part of the working key!

To list all keys and user IDs use list. To add a subkey use addkey. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> addkey
   3 [...]
   4 gpg> save

9.2. Extend a subkey's validity

Specifying an expiration date on keys and subkeys will give you a much finer control if some unforeseen circumstances happen.

To list all keys and user IDs use list. To select or unselect a subkey use key N. Not selecting any subkey means working on the main key. To adjust the expiration date of the selected key(s) or the main key use expire. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> key 1
   3 pub  4096R/2F3894F9C5688391  created: 2014-12-05  expires: 2020-01-31  usage: SC
   4                              trust: ultimate      validity: ultimate
   5 sub* 3072R/8CB8E0FFDADD3834  created: 2014-12-05  expires: 2016-01-31  usage: S
   6 sub  3072R/3EF8C012214CDCB3  created: 2014-12-05  expires: 2016-01-31  usage: E
   7 [...]
   8 gpg> expire
   9 Changing expiration time for a subkey.
  10 Please specify how long the key should be valid.
  11          0 = key does not expire
  12       <n>  = key expires in n days
  13       <n>w = key expires in n weeks
  14       <n>m = key expires in n months
  15       <n>y = key expires in n years
  16 Key is valid for? (0) 2017-02-01
  17 Key expires at Wed 01 Feb 2017 12:00:00 AM CET
  18 Is this correct? (y/N) y
  19 [...]
  20 pub  4096R/2F3894F9C5688391  created: 2014-12-05  expires: 2020-01-31  usage: SC
  21                              trust: ultimate      validity: ultimate
  22 sub* 3072R/8CB8E0FFDADD3834  created: 2014-12-05  expires: 2017-01-31  usage: S
  23 sub  3072R/3EF8C012214CDCB3  created: 2014-12-05  expires: 2016-01-31  usage: E
  24 [...]
  25 gpg> save

9.3. Revoke a subkey

Note that it is not necessary to revoke a subkey if it has expired. A new expiration date can simply be set to restore its validity. For details, see the previous subsection.

Also note that the usage capabilities of encrypting (E) and signing data (S) must be provided entirely by the subkeys. In this case, the main key's capabilities do not matter because it is not part of the working key!

Further on, deleting a subkey using delkey will not make sense provided the public key is already published (with this subkey). As components can only be added to an OpenPGP key, the next refresh of the public key will bring back the deleted subkey. It should be revoked instead.

To list all keys and user IDs use list. To select or unselect a subkey use key N. Not selecting any subkey means working on the main key. To revoke the selected one(s) or the main key use revkey. You should almost never provide any reason for the revocation if asked. The revocation itself is a sufficient statement. Do not specify any optional description either. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> key 2
   3 pub  4096R/2F3894F9C5688391  created: 2014-12-05  expires: 2020-01-31  usage: SC
   4                              trust: ultimate      validity: ultimate
   5 sub  3072R/8CB8E0FFDADD3834  created: 2014-12-05  expires: 2016-01-31  usage: S
   6 sub* 3072R/3EF8C012214CDCB3  created: 2014-12-05  expires: 2016-01-31  usage: E
   7 [...]
   8 gpg> revkey
   9 Do you really want to revoke this subkey? (y/N) y
  10 Please select the reason for the revocation:
  11   0 = No reason specified
  12   1 = Key has been compromised
  13   2 = Key is superseded
  14   3 = Key is no longer used
  15   Q = Cancel
  16 Your decision? 0
  17 Enter an optional description; end it with an empty line:
  18 >
  19 Reason for revocation: No reason specified
  20 (No description given)
  21 Is this okay? (y/N) y
  22 [...]
  23 pub  4096R/2F3894F9C5688391  created: 2014-12-05  expires: 2020-01-31  usage: SC
  24                              trust: ultimate      validity: ultimate
  25 sub  3072R/8CB8E0FFDADD3834  created: 2014-12-05  expires: 2016-01-31  usage: S
  26 This key was revoked on 2014-12-06 by RSA key 2F3894F9C5688391 John Q. Example
  27 sub  3072R/3EF8C012214CDCB3  created: 2014-12-05  revoked: 2014-12-06  usage: E
  28 [...]
  29 gpg> save

9.4. Add a user ID

The key may be equipped with further user IDs with real names and email addresses. A comment should almost always be omitted. For further details, see Daniel Kahn Gillmor's article OpenPGP user ID comments considered harmful in the reference section Articles below.

If there are several user IDs, one of them should be manually marked as primary user ID. Usually this should be the user ID without an email address.

To list all keys and user IDs use list. To add a user ID use adduid. To select or unselect a user ID use uid N. To make the selected user ID the primary one use primary. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> adduid
   3 Real name: John Q. Example
   4 Email address: j.example@mail.example.org
   5 Comment:
   6 You selected this USER-ID:
   7     "John Q. Example <j.example@mail.example.org>"
   8 
   9 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
  10 [...]
  11 gpg> uid 4
  12 [...]
  13 [ultimate] (1). John Q. Example
  14 [ultimate] (2)  John Q. Example <john@example.com>
  15 [ultimate] (3)  John Example <jonny@example.net>
  16 [ unknown] (4)* John Q. Example <j.example@mail.example.org>
  17 gpg> primary
  18 [...]
  19 [ultimate] (1)  John Q. Example
  20 [ultimate] (2)  John Q. Example <john@example.com>
  21 [ultimate] (3)  John Example <jonny@example.net>
  22 [ unknown] (4)* John Q. Example <j.example@mail.example.org>
  23 gpg> save

The trust values of the new user ID(s) are determined after saving the key. Therefore, the above listing shows "unknown" values.

9.5. Revoke a user ID

Note that deleting a user ID using deluid will not make sense provided the public key is already published (with this user ID). As components can only be added to an OpenPGP key, the next refresh of the public key will bring back the deleted user ID back. It should be revoked instead.

If there are still several valid user IDs after revoking, one of them should be manually marked as primary user ID. Usually this should be the user ID without an email address.

To list all keys and user IDs use list. To select or unselect a user ID use uid N. To revoke the selected one(s) use revuid. You should almost never provide any reason for the revocation if asked. The revocation itself is a sufficient statement. Do not specify any optional description either. To make a selected user ID the primary one use primary. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> uid 3
   3 [...]
   4 [ultimate] (1). John Q. Example
   5 [ultimate] (2)  John Q. Example <john@example.com>
   6 [ultimate] (3)* John Example <jonny@example.net>
   7 gpg> revuid
   8 Really revoke this user ID? (y/N) y
   9 Please select the reason for the revocation:
  10   0 = No reason specified
  11   4 = User ID is no longer valid
  12   Q = Cancel
  13 (Probably you want to select 4 here)
  14 Your decision? 0
  15 Enter an optional description; end it with an empty line:
  16 >
  17 Reason for revocation: No reason specified
  18 (No description given)
  19 Is this okay? (y/N) y
  20 [...]
  21 [ultimate] (1). John Q. Example
  22 [ultimate] (2)  John Q. Example <john@example.com>
  23 [ revoked] (3)  John Example <jonny@example.net>
  24 gpg> save

9.6. Change a user ID's preferences

Each user ID stores its own set of algorithm preferences (cipher, digest, compression) in the corresponding self-signature. These preferences are handled by the commands pref, showpref, and setpref. To select or unselect a user ID use uid N. Not selecting any user ID means working on all of them.

To list the actual preferences of the selected user ID(s) use showpref. Compared to the listing of pref, which is less understandable for humans, some default preferences may additionally be included:

Note that instead of changing the preferences directly on the key, it is strongly recommended to change the arguments of the option default-preference-list in the configuration file. After that, the setpref command can be used at the prompt without any arguments as they are taken from the configuration file. Alternately, specifying all algorithms manually as arguments of setpref is very error-prone. For further details, see the section Algorithms above.

The following example removes the AES algorithm from the cipher preferences of all user IDs.

   1 $ gpg --edit-key $KEYID
   2 gpg> showpref
   3 [ultimate] (1). John Q. Example
   4      Cipher: AES256, CAMELLIA256, TWOFISH, AES192, CAMELLIA192, AES, \
   5              CAMELLIA128, CAST5, 3DES
   6      Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
   7      Compression: BZIP2, ZLIB, ZIP, Uncompressed
   8      Features: MDC, Keyserver no-modify
   9 [...]
  10 gpg> pref
  11 [ultimate] (1). John Q. Example
  12      S9 S13 S10 S8 S12 S7 S11 S3 S2 H10 H9 H8 H11 H3 H2 Z3 Z2 Z1 Z0 \
  13      [mdc] [no-ks-modify]
  14 [...]
  15 gpg> quit
  16 $ gpg --verbose --version
  17 [...]
  18 Cipher: 3DES (S2), CAST5 (S3), BLOWFISH (S4), AES (S7), AES192 (S8),
  19         AES256 (S9), TWOFISH (S10), CAMELLIA128 (S11),
  20         CAMELLIA192 (S12), CAMELLIA256 (S13)
  21 Hash: MD5 (H1), SHA1 (H2), RIPEMD160 (H3), SHA256 (H8), SHA384 (H9),
  22       SHA512 (H10), SHA224 (H11)
  23 Compression: Uncompressed (Z0), ZIP (Z1), ZLIB (Z2), BZIP2 (Z3)

Edit the configuration file gpg.conf and remove AES from the settings default-preference-list (and eventually from personal-cipher-preferences as well). Then adopt this change. To remove any unusable signatures, which in this case are internal ones only, use clean. Finally save and quit.

  24 $ gpg --edit-key $KEYID
  25 gpg> setpref
  26 Set preference list to:
  27      Cipher: CAMELLIA256, TWOFISH, CAMELLIA192, CAMELLIA128, CAST5, 3DES
  28      Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
  29      Compression: BZIP2, ZLIB, ZIP, Uncompressed
  30      Features: MDC, Keyserver no-modify
  31 Really update the preferences? (y/N) y
  32 [...]
  33 gpg> clean
  34 [...]
  35 gpg> save

9.7. Export the offline/working key

Note that after modifying the offline key, both the offline key and the working key must be exported again - just like the final step of the initial key generation process above. This also means to reset the working key's passphrase!

Export the key components to files in ASCII format. Perhaps it is a good idea to add a timestamp YYYY-MM-DD to the filenames. For the sake of brevity this document does not.

$ gpg --armor --export $KEYID > public.asc
$ gpg --armor --export-secret-keys $KEYID > offline-secret.asc
$ gpg --armor --export-secret-subkeys $KEYID > working-secret.asc

Ensure that the above three commands are executed successfully. After that, remove the key rings and import only the files working-secret.asc and public.asc.

$ rm pubring.gpg secring.gpg
$ gpg --import working-secret.asc.asc public.asc

To set the working key's passphrase, use passwd. To remove any unusable signatures, which in this case are internal ones only, use clean. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> passwd
   3 [...]
   4 gpg> clean
   5 [...]
   6 gpg> save

Remove the file working-secret.asc and export the respective key components again with the modified passphrase to this file in ASCII format. Perhaps it is a good idea to add a timestamp YYYY-MM-DD to the filename. For the sake of brevity this document does not.

$ rm working-secret.asc
$ gpg --armor --export-secret-subkeys $KEYID > working-secret.asc

Ensure that the above command was executed successfully.

All files must really be located on the respective storage devices before unmounting them. Finally, clean up the offline environment and shut down the system.

10. Revoke the offline/working key

Note that it is not necessary to revoke the offline key if it has expired. A new expiration date can simply be set to restore its validity. For details, see the section Extend a subkey's validity above (do no select any subkey there).

For simplicity, create an environment variable with the key ID.

$ export KEYID=2F3894F9C5688391

There are two different ways of revoking the offline key discussed in the following subsections:

10.1. Using a revocation certificate

There is a revocation certificate for the offline key which was created as in the section Create a revocation certificate above. It is assumed to be in the file revoke.asc. You need the public key, too. In case of a prior key lost, it can easily be obtained from a key server.

Warning

  1. There is no passphrase needed to revoke a offline key.

  2. If the revoked offline key is published, the revocation cannot be undone.
  3. If the revoked offline key is not published, the revocation can be undone only if there is a backup.

Optionally import the public key.

   1 $ gpg --import public.asc
   2 gpg: key 2F3894F9C5688391: public key "John Q. Example" imported
   3 gpg: Total number processed: 1
   4 gpg:               imported: 1  (RSA: 1)

Apply the revocation certificate to the public key by also importing it.

   5 $ gpg --import revoke.asc
   6 gpg: key 2F3894F9C5688391: "John Q. Example" revocation certificate imported
   7 gpg: Total number processed: 1
   8 gpg:    new key revocations: 1

10.2. Using the offline key

You have the offline key available and know its passphrase.

To revoke the main key use revkey. You should almost never provide any reason for the revocation if asked. The revocation itself is a sufficient statement. Do not specify any optional description either. Finally save and quit.

   1 $ gpg --edit-key $KEYID
   2 gpg> revkey
   3 Do you really want to revoke the entire key? (y/N) y
   4 Please select the reason for the revocation:
   5   0 = No reason specified
   6   1 = Key has been compromised
   7   2 = Key is superseded
   8   3 = Key is no longer used
   9   Q = Cancel
  10 Your decision? 0
  11 Enter an optional description; end it with an empty line:
  12 >
  13 Reason for revocation: No reason specified
  14 (No description given)
  15 Is this okay? (y/N) y
  16 [...]
  17 gpg> save

10.3. Final steps

Analyze the revoked public key and export it to a file revoked-public.asc in ASCII format. This file needs to be published, which normally means to send it to a key server.

   1 $ gpg --list-keys $KEYID
   2 pub   4096R/2F3894F9C5688391 2014-12-05 [revoked: 2014-12-05]
   3 uid               [ revoked] John Q. Example
   4 uid               [ revoked] John Q. Example <john@example.com>
   5 uid               [ revoked] John Example <jonny@example.net>
   6 sub   3072R/8CB8E0FFDADD3834 2014-12-05 [revoked: 2014-12-05]
   7 sub   3072R/3EF8C012214CDCB3 2014-12-05 [revoked: 2014-12-05]
   8 $ gpg --armor --export $KEYID > revoked-public.asc

Finally, you import the file revoked-public.asc to your existing GnuPG setup(s), i.e., to all your working environment(s).

Warning

Do not remove your revoked offline key because then you will not be able to decrypt any encrypted data for this OpenPGP key or to verify any signatures made by this OpenPGP key any more.

11. Details of the exported files

The processes described in the sections above create several files in ASCII format. Their internal structure consists of a sequence of packets which can be examined by the following commands:

$ pgpdump FILE
$ gpg --list-packets FILE

The first command shows a readable output and the second one gives the exact details. In both cases the OpenPGP standard RFC 4880 is handy, e. g., for looking up the various constants.

The above commands should not be run in a working environment or with any real world secret key material. Stating it more explicitly:

Warning

  1. Never hand over control of secret key material to any third party!

  2. Ensure, that all sensitive information is completely destroyed without anybody being able to restore it ever.
  3. The output of the above commands may contain sensitive information which should not be published without prior redacting! This in turn requires a good knowledge about the internals.

The following list offers the output of both commands

All files can also be downloaded together.

12. References

12.1. General

12.2. Articles

The following entries are sorted alphabetically by their authors.

12.3. Recommendations

The following entries are ordered by their publication date.

12.4. Algorithms

The following entries are ordered by the respective algorithm's name.

12.5. Key servers

The following entries are ordered chronologically.

12.6. Software

The following entries are ordered alphabetically.

13. History

The OpenPGP Key Management HowTo is available in several formats which are produced from (nearly) one single source. This section gives a short overview about the milestones of the document's history. Minor fixes are omitted.

OpenPGP/KeyManagementHowTo (last edited 2015-01-15 22:40:48 by Mathias)