Convert GPG keys to subkeys
This is a short log (how to) I converted my PGP key to PGP subkeys.
First of all, make yourself familiar with your key.
Contents
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