Convert GPG keys to subkeys

From Exterior Memory
Jump to: navigation, search

This is a short log (how to) I converted my PGP key to PGP subkeys.

First of all, make yourself familiar with your key.

Start and Desired Situation

I had the following key:

pub  1024D/B804CF07 2006-02-05 Freek Dijkstra <freek@macfreek.nl> [usage: SCA]
uid                            Freek Dijkstra <fdijkstr@science.uva.nl>
uat                            [jpeg image of size 5225]
sub  2048g/2C33CF18 2006-02-05 [usage: E]
sec  1024D/B804CF07 2006-02-05
ssb  2048g/2C33CF18 2006-02-05

Desired end situation:

pub   1024D/B804CF07 2006-02-05 [usage: SCA]
uid                  Freek Dijkstra (born 1975-07-03 in Hilversum, the Netherlands)
uid                  Freek Dijkstra <freek@macfreek.nl>
uid                  Freek Dijkstra <fdijkstr@science.uva.nl>
uat                  [jpeg image of size 5225]
uid                  Freek Dijkstra <F.Dijkstra@uva.nl>
sub   2048g/2C33CF18 2006-02-05 [expires: 2010-03-18] [usage: E]
sub   1024D/8B02309E 2008-02-26 [expires: 2010-03-18] [usage: S]
ssb   2048g/2C33CF18 2006-02-05 [expires: 2010-03-18]
ssb   1024D/8B02309E 2008-02-26 [expires: 2010-03-18]

(Note: the keys and secret keys can be listed with gpg --list-keys 0xB804CF07 list and gpg --list-secret-keys 0xB804CF07 list. The usage information can be retrieved using gpg --edit-key 0xB804CF07 list.)

My desired changes were:

  • I wanted me as my identity, rather than my e-mail address. After all, that is what is checked in PGP keysigning
  • I wanted a master key, with temporary subkeys, so that if my laptop is compromised, I do not have to invalidate my PGP key, and start all over again.
  • I did not want to get a new key, and start key signing from scratch.

Implementation

The implementation was in fact more straightforward than I thought.

The most important decision was if I should get a stronger key or not. My current master key is a 1024 bit DSA key. Some security experts move to 4096 bit RSA (DSA and RSA are roughly the same strength, but the DSA specs says that only 1024 bit is allowed).

There are two ways to proceed if a stronger key is desired: either get a new key, or go through a complex process of changing the master key into a subkey.

The rest of this page assumes the key retains the same strength.

Use a masterkey

A very important concept is that a PGP key contains mulitple subkeys. This is my configuration:

  • A master(sub)key for certification (signing of other keys)
  • An encryption (sub)key
  • A signing (sub)key

The secret part of the master(sub)key should be locked away safely, and off-line. The encryption and signing keys are temporary keys, which can easily be revoked if they are compromised. The private part of the master(sub)key must never be present on an online machines. The private part of the encryption and signing keys are present on on-line computers, as they are in active use.

Create a signing only subkey:

gpg --edit-key 0xB804CF07
addkey
choose 2 (DSA, sign only) or 5 (RSA, sign only)

Set an expiration date for the existing encryption only subkey:

gpg --edit-key 0xB804CF07
key 2
expire

Remove private part of masterkey

First, and most important: make a backup of your key. Really. Do that now.

gpg --export 0xB804CF07 > publickey.gpg
gpg --export-secret-keys > secretkeys.gpg
gpg --export-secret-subkeys > secretsubkeys.gpg

To remove the private (secret) part of the subkey:

gpg --delete-secret-key 0xB804CF07
gpg --import publickey.gpg
gpg --import secretsubkeys.gpg

The only thing that has been removed after this procedure is the private part of the master key. The private parts of the subkeys are still there. That is exactly what you want.

Store publickey.gpg and secretkeys.gpg in a safe location. That is, off-line.

Change Primary Identity

To add a new identity, first add it:

gpg --edit-key 0xB804CF07
adduid
Enter yhe UID of your choice.
key 3
primary

At the "key 3" step, make sure to choose the new UID. In this case, I added an UID with my name and date of birth, and without an e-mail address.

Replace Temporary Subkeys

In my desired situation, I have a static certification key (the master key), and temporary encryption and signing subkeys. I let these keys expire in 25 months, meaning that I must create new subkey after two years.

gpg --edit-key 0xB804CF07
addkey
[choose 2 (DSA, sign only) or 5 (RSA, sign only)]

gpg --edit-key 0xB804CF07
addkey
[choose 4 (Elgamal, encrypt only) or 6 (RSA, encrypt only)]

Note that I do not remove the old keys. I still need (the private part of) the old encryption subkey and (the public part of) the old signing subkey to respectively decrypt old e-mails and to verify signatures of old e-mails.

If your key has multiple signing (usage: s) or encryption (usage: e) subkeys, GPG will pick the one with the latest creation date. That is what you want.

Off-line Actions

Since the key on my computer no longer has a secret (master) key, I can no longer use it for signing (neither can a culprit who steals my laptop).

For all administrative actions, I use a USB stick. It would be more secure to dedicate a specific machine for that purpose, but I regard a USB key safe enough. Just be sure to store the USB key at home and never take it with you on the road.

A little note about longevity of your data: I expect my keys to outlast my USB flash drive. So I simply use two USB sticks of a different brand, and read the data every two years.

My USB stick contains the following layout:

/mnt/keys/README.txt
/mnt/keys/2009-02-22
/mnt/keys/2009-02-22/B804CF07-publickey.gpg
/mnt/keys/2009-02-22/B804CF07-secretkey.gpg
/mnt/keys/2009-02-22/B804CF07-secretsubkey.gpg
/mnt/keys/gnupg
/mnt/keys/gnupg/gpg.conf
/mnt/keys/gnupg/pubring.gpg
/mnt/keys/gnupg/pubring.gpg~
/mnt/keys/gnupg/random_seed
/mnt/keys/gnupg/secring.gpg
/mnt/keys/gnupg/trustdb.gpg

The README is basically the following text (since I can't remember these things by head). The 2009-02-22 directory contains a backup of my key (both public and secret keys). The gnupg directory contains all keys, but with secret key.

Before I run any administrative PGP task, I insert my USB key and set $GNUPGHOME variable.

export GNUPGHOME=/mnt/keys/gnupg

After I am finished, I unset $GNUPGHOME and eject the USB key from my computer.

Sign Other Keys

Singing another key is simple:

export GNUPGHOME=/mnt/keys/gnupg
gpg --recv-key 0x12341234
gpg --sign-key --ask-cert-level 0x12341234
gpg --edit-key 0x12341234 trust
gpg --send-key 0x12341234

To load it in my online keyring:

unset GNUPGHOME
gpg --recv-key <key>

Create New Subkeys

This works the same as described above.

First backup the key (if you haven't done so already). This is just a temporary backup in case you screw up.

export GNUPGHOME=/mnt/keys/gnupg
gpg --export 0xB804CF07     > 2009-02-22/B804CF07-publickey.gpg
gpg --export-secret-keys    > 2009-02-22/B804CF07-secretkey.gpg
gpg --export-secret-subkeys > 2009-02-22/B804CF07-secretsubkey.gpg

Of course, you should not store this backup on your online computer, but on the USB stick. Otherwise it would still be online after you remove the USB stick.

Then create the new subkeys. In my case, one sign-only subkey, and one encrypt-only subkey.

gpg --edit-key 0xB804CF07
addkey
[...]
addkey
[...]

My current choices (for no specific reason) are DSA (sign only) and Elgamal (encrypt only), both 2048 bits and valid for 750 days.

Third, you should revoke the old keys:

gpg --edit-key 0xB804CF07
key 1      # select the subkeys to revoke (watch the * in front of the subkeys)
key 2 
revkey
save

This only revoked the keys, but does not delete them: you will need the old decryption key to decrypt old files.

If you are happy and confident that everything works as you want (you may want to analyze your key if you feel unsure), you can commit your changes. Step four starts by making the same export as we did for the backup.

export GNUPGHOME=/mnt/keys/gnupg
gpg --export 0xB804CF07     > 2009-02-22/B804CF07-publickey.gpg
gpg --export-secret-keys    > 2009-02-22/B804CF07-secretkey.gpg
gpg --export-secret-subkeys > 2009-02-22/B804CF07-secretsubkey.gpg

Since the above only created the new subkeys on your USB stick, you need to import them on your online computer too:

unset GNUPGHOME
gpg --delete-secret-key 0xB804CF07
gpg --import 2009-02-22/B804CF07-publickey.gpg
gpg --import 2009-02-22/B804CF07-secretsubkey.gpg

In the above, the delete-secret-key should not be necessary, but I found that gnupg has a bug where is does not import new secret subkeys if there are already previous secret subkeys present, ignoring the new ones.

Finally, let the rest of the world know:

gpg --send-key 0xB804CF07

Recovering from Backups

If you made a mistake during this process, simply delete your keys, and import your backups (you did make those backups, did you?):

On the USB stick:

gpg --delete-secret-key 0xB804CF07
gpg --import 2009-02-22/B804CF07-publickey.gpg
gpg --import 2009-02-22/B804CF07-secretkey.gpg
gpg --import 2009-02-22/B804CF07-secretsubkey.gpg

Or on your online computer:

gpg --delete-secret-key 0xB804CF07
gpg --import 2009-02-22/B804CF07-publickey.gpg
gpg --import 2009-02-22/B804CF07-secretsubkey.gpg