Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

Currently I have 3 private GPG pairs which are all master keys. I want to convert these keys into subkeys for a new key pair (and keep that in the vault).

I have read the following thread http://atom.smasher.org/gpg/gpg-migrate.txt which involes some sort of hacking the binary file to convert one master key into a subkey and replace it with another.

Is it possible to combine my different keys into a new single key pair so they still remain valid, and I can refer people to signing my master key, so I don't have to be afraid of losing my secret master key.

What I have

Here I have 3 different keys (the private key is available).

$ gpg2 -k                          
----------------------------------
pub   2048R/712A2BBD 2013-01-29
uid                  Test Key 1
sub   2048R/F0B63FDA 2013-01-29

pub   2048R/72838B89 2013-01-29
uid                  Test Key 2
sub   2048R/A19F06EC 2013-01-29

pub   2048D/AC349218 2013-03-21
uid                  Test Key 3
sub   2048g/179E9F47 2013-03-21

What I want

I like to convert the these keys into subkeys and move them to a new master key. It should look something like this instead:

pub   4096R/CB577A43 2013-03-21
uid                  Master Key
sub   2048R/712A2BBD 2013-01-29
sub   2048R/F0B63FDA 2013-01-29
sub   2048R/72838B89 2013-01-29
sub   2048R/A19F06EC 2013-01-29
sub   2048D/AC349218 2013-03-21
sub   2048g/179E9F47 2013-03-21

Is this even possible to do? Or Are my best hope to revoke my 3 keys and start from scratch and create a new key that fits my use.

What I done so far

Using the instructions from http://atom.smasher.org/gpg/gpg-migrate.txt

I managed to export and extracted my keys using gpgsplit. I've also changed the secret_key into a secret_subkey by changing the first byte från 0x95 to 0x9d

So that pgpdump says the secret is is a secret subkey

~/keytest/key1❯ pgpdump/pgpdump 000001-005.secret_subkey          
Old: Secret Subkey Packet(tag 7)(920 bytes)
        Ver 4 - new
        Public key creation time - Tue Jan 29 13:09:07 CET 2013
        Pub alg - RSA Encrypt or Sign(pub 1)
        ...

I've then merge all keys together into a new key my concatenating the files.

$ gpg2 --export-secret-key CB577A43 > master.gpg
$ cat master.gpg key1/* key2/* key3/* > newkey.gpg
# Removed ~/.gnupg
$ gpg2 --import newkey.gpg
# Ended up with this:
$ gpg -k
----------------------------------
pub   4096R/CB577A43 2013-03-21
uid                  Master Key
sub   2048R/208FAE4C 2013-03-21

~/keytest❯ gpg -K
----------------------------------
sec   4096R/CB577A43 2013-03-21
uid                  Master Key
ssb   2048R/208FAE4C 2013-03-21
ssb   2048R/712A2BBD 2013-01-29
uid                  Test Key 1
ssb   2048R/F0B63FDA 2013-01-29
ssb   2048R/72838B89 2013-01-29
uid                  Test Key 2
ssb   2048R/A19F06EC 2013-01-29
ssb   2048D/AC349218 2013-03-21
uid                  Test Key 3
ssb   2048g/179E9F47 2013-03-21

Which doesn't look so bad. But if I import my keys from the keyserver gpg2 --recv-keys 712A2BBD 72838B89 AC349218 to get the signatures back. It turns into this:

$ gpg -k                          
----------------------------------
pub   4096R/CB577A43 2013-03-21
uid                  Master Key
sub   2048R/208FAE4C 2013-03-21

pub   2048R/712A2BBD 2013-01-29
uid                  Test Key 1
sub   2048R/F0B63FDA 2013-01-29

pub   2048R/72838B89 2013-01-29
uid                  Test Key 2
sub   2048R/A19F06EC 2013-01-29

pub   2048D/AC349218 2013-03-21
uid                  Test Key 3
sub   2048g/179E9F47 2013-03-21

What remains

After this I have 4 public keys in my keyring. I wanted to move these keys so they are dependent on the master key CB577A43 like above under What I want.

share|improve this question

3 Answers 3

It can actually be done.

The instructions at atom.smasher.org/gpg/gpg-migrate.txt are now out of date.

Try this. As always, make backups, because it's really easy to mess it up.


So these are your 'old' keys:

$ gpg -K                          
----------------------------------
sec   2048R/712A2BBD 2013-01-29
uid                  Test Key 1
ssb   2048R/F0B63FDA 2013-01-29

sec   2048R/72838B89 2013-01-29
uid                  Test Key 2
ssb   2048R/A19F06EC 2013-01-29

sec   2048D/AC349218 2013-03-21
uid                  Test Key 3
ssb   2048g/179E9F47 2013-03-21

And you have created a new "master key" which has no subkeys:

sec   4096R/CB577A43 2013-03-21
uid                  Master Key

For simplicity's sake, I will only rehearse the procedure using the first of your "old" keys:

sec   2048R/712A2BBD 2013-01-29  
uid                  Test Key 1
ssb   2048R/F0B63FDA 2013-01-29  

Using the same procedure, you can add all of them. I recommend you add all of them at the same time, because every time you break the keys and then reassemble them you have to recreate the binding signatures, and that is a pain.


1. Use gpgsplit to split the "old" key into its constituent packets.

$ gpg --export-secret-keys 712A2BBD | gpgsplit -vp 712A2BBD_

Now look at the files it created:

$ ls
----------------------------------
712A2BBD_000001-005.secret_key
712A2BBD_000002-013.user_id
712A2BBD_000003-002.sig
712A2BBD_000004-007.secret_subkey
712A2BBD_000005-002.sig

The first file, "712A2BBD_000001-005.secret_key" contains the packet for the main private key (packet type tag 5, hence the "005") of your "old" key, "712A2BBD". (You will need this, but you will need to convert it into a subkey if you want to migrate it into your new "master key". In keys generated using standard settings on GPG, the main private key normally has usage flags "S" for sign and "C" for certify, and does not have "E" for encrypt, which is normally why the key is generated with an "E" subkey. However, because of the procedure we are using, when eventually the main key is turned into a subkey and migrated to your new "master key", it will have all usage flags ("SCEA") enabled. This probably makes it less secure, and is probably a behaviour to be avoided.)

The second file, "712A2BBD_000002-013.user_id", is the packet for the user id (packet type tag 13). (You won't need this).

The third file, "712A2BBD_000003-002.sig", is a binding signature (packet type tag 2) for these packets. (You won't need this).

The fourth file is the packet for the secret subkey (F0B63FDA) (packet type tag 7). (You will need this. Typically, a subkey like this has the "E" usage flag, meaning it is solely for encryption. However, in the process of importing it to your new "master key" it will acquire all of the usage flags, ("SCEA"), which is probably not a good thing.)

The fifth file, "712A2BBD_000005-002.sig", is the binding signature (packet type tag 2) for the subkey. You won't need it.

Save the two files you need and remove the others.


2. Change the main key (712A2BBD) into a subkey.

You don't need to do anything to the subkey (F0B63FDA) in order to migrate it to your new "master key", but the main key (712A2BBD) of your old key needs to be altered in order to make it work.

Open the main key, "712A2BBD_000001-005.secret_key", in an editor capable of making hex or binary edits. I used ghex:

$ ghex 712A2BBD_000001-005.secret_key

If you are using a hex editor, the first byte will be "95". Change it to "9D".

If you are using a binary editor, the first byte will be "10010101". Change it to "10011101".

Save it, and then use pgpdump to see if it you have been successful in changing it to a subkey. If you have been successful, you will see the following output:

$ pgpdump 712A2BBD_000001-005.secret_key | head -1
-----------------
Old: Secret Subkey Packet(tag 7)(1836 bytes)

3. Add a "dummy" subkey to your new "master key" for each of the subkeys you want to add.

Just like in the tutorial at atom.smasher.org, you will need to create new "dummy" subkeys on your "master key" in order to make sure you have keybinding signatures on the master key which can accomodate (at least at first) the migrating subkeys.

Think of it as creating "slots" for the old subkeys to slot into. You will need as many slots as keys you want to add.

In the present example, we'll make two dummy subkeys, but if you want to add all of the keys you listed in your original post, you'll want to make six.

$ gpg --expert --edit-key CB577A43
----------------------------------------
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub  4096R/CB577A43  created: 2013-03-21  expires: never       usage: SC  
                     trust: unknown      validity: unknown

gpg>addkey

Make sure, while going through the subkey generation wizard (which is in expert mode, thanks to the --expert option above) that when you generate your new "dummy" subkey, it is of the same...

  • key strength (2048, 4096, etc)
  • type (DSA, RSA, elgamal)
  • usage (encrypt, sign)

...as the subkey you intend to add in that "slot".

Since we're adding two subkeys, we finish up with two new "dummy" subkeys on the "master key". Save and exit:

pub  4096R/CB577A43  created: 2013-03-21  expires: never       usage: SC  
                         trust: unknown      validity: unknown
sub  2048R/AAAAAAAA  created: 2014-01-01  expires: never       usage: S
sub  2048R/BBBBBBBB  created: 2014-01-01  expires: never       usage: E

gpg> save

4. Split your new "master key" - along with its new subkeys - into its constituent packets.

$ gpg --export-secret-keys CB577A43 | gpgsplit -vp CB577A43_

You should end up with something like the following:

$ ls
----------------
CB577A43_000001-005.secret_key
CB577A43_000002-013.user_id
CB577A43_000003-002.sig
CB577A43_000004-007.secret_subkey
**CB577A43_000005-002.sig**
CB577A43_000006-007.secret_subkey
**CB577A43_000007-002.sig**

The fifth and seventh files (the ones I have put in **s) are the subkey keybinding signature packets that were generated when you generated the "dummy subkeys." You'll need these.

The fourth and sixth files are the actual "dummy subkey" packets. They can now be safely deleted (the only files you should delete.)

$ rm CB577A43_000004-007.secret_subkey CB577A43_000006-007.secret_subkey

5. "Slot in" your migrating "subkeys" into the split master key.

Steps one and two left you with two files:

712A2BBD_000001-005.secret_key (the original main key of your "old key", now edited into a subkey)
712A2BBD_000004-007.secret_subkey (the original subkey of your "old key".)

Now copy these into the folder with the split constituents of the "master key" and rename these files so that they replace the "dummy subkey" files that we just deleted.

$ mv 712A2BBD_000001-005.secret_key CB577A43_000004-007.secret_subkey
$ mv 712A2BBD_000004-007.secret_subkey CB577A43_000006-007.secret_subkey

You should once again have seven (in this example) files, but files four and six are now your old keys, all set and ready to become subkeys of your new master key.

$ ls
----------------
CB577A43_000001-005.secret_key
CB577A43_000002-013.user_id
CB577A43_000003-002.sig
**CB577A43_000004-007.secret_subkey**
CB577A43_000005-002.sig
**CB577A43_000006-007.secret_subkey**
CB577A43_000007-002.sig

6. Concatenate the files into private and public key files, ready for import

Put the files together so that they are concatenated consecutively into single files, for ease of import later.

$ cat CB577A43_000001-005.secret_key CB577A43_000002-013.user_id CB577A43_000003-002.sig CB577A43_000004-007.secret_subkey CB577A43_000005-002.sig CB577A43_000006-007.secret_subkey CB577A43_000007-002.sig > concatenated_CB577A43.secret

Use the same command, but pipe the output to gpgsplit in order to create public counterparts, before redirecting to a new file:

$ cat CB577A43_000001-005.secret_key CB577A43_000002-013.user_id CB577A43_000003-002.sig CB577A43_000004-007.secret_subkey CB577A43_000005-002.sig CB577A43_000006-007.secret_subkey CB577A43_000007-002.sig | gpgsplit --no-split --secret-to-public > concatenated_CB577A43.public

7. Back up your keyring and then delete the "old" AND "master" keys, both public and private, from your keyring.

$ cp -R ~/.gnupg/ ~/.gnupg_backup
$ gpg --delete-secret-and-public-keys CB577A43 712A2BBD

8. Download and build gnupg-1.2.0.

Recently whenever anyone tries to follow the tutorial at atom.smasher.org, the problem they run into is that, with the newest versions of gpg, once they reassemble the key and add it to their keyring, the added subkeys 1) have no usage flags, and 2) they are unable to reset the expiry date, as advised in the atom.smasher.org tutorial, a necessary step to creating new and valid keybinding signatures. The result is that after one export/import cycle, the keys are deemed invalid by GPG, and disappear from the private keyring.

In order to successfully import the keys, you have to download and build an old version of gnupg: a version from 2002 no less. One you have build it, you will be able to reset the expiry dates on the new keys, and successfully recreate valid keybindings for the keys.

Download the old gnupg.

$ wget ftp://mirror.tje.me.uk/pub/mirrors/ftp.gnupg.org/gnupg/gnupg-1.2.0.tar.bz2
$ tar -xjf gnupg-1.2.0.tar.bz2
$ cd gnupg-1.2.0/
$ ./configure
$ make

Navigate into the g10 folder, which contains your newly build gpg binary

$ cd g10

In order to use this binary, instead of the system-wide build of gpg, which is more recent, you have to type the absolute path to the binary. If you are in the same folder, use ./gpg, for example:

$ ./gpg --list-keys

8. Append the new assembled "master key" file with imported subkeys to your public and private keyrings.

Don't import the keys the normal way, because the keybinding signatures don't check out, with the result that the imported subkeys wouldn't import the normal way. Instead, cat the files to the end of your public and private keyrings.

$ cat concatenated_CB577A43.secret >> ~/.gnupg/secring.gpg
$ cat concatenated_CB577A43.public >> ~/.gnupg/pubring.gpg

Check that they have gotten in there by using the gnupg-1.2.0 to list the keys:

$ ./gpg --list-keys
-----------------
pub   4096R/CB577A43 2013-03-21
uid                  Master Key
sub   2048R/712A2BBD 2013-01-29
sub   2048R/F0B63FDA 2013-01-29

9. Edit the keys using the gnupg-1.2.0.

Make sure to navigate back to the build folder for gnupg-1.2.0/g10, and invoke the built binary to edit your newly imported, newly assembled master key, complete with your imported old subkeys:

$ ./gpg --edit-keys CB577A43
-----------------
sec  4096R/CB577A43  created: 2013-03-21 expires: never     
ssb  2048R/712A2BBD  created: 2013-01-29 expires: never     
ssb  2048R/F0B63FDA  created: 2013-01-29 expires: never 

First, reset the passwords.

Command> passwd

It is likely that all of your old keys had different passwords from your new master key. If you reset the password now, it will prompt you for each of the passwords of the old keys in turn (along with the subkey id) and when you have inputted them all properly, it will ask you for a new key. Once this is done, they will all have the same password, avoiding weirdness later.

Second, reset the expiry date on ALL of the keys. Begin with the main master key:

Command> expiry

And then work your way through each of the subkeys, changing the expiry date on each of them.

Command> key 1
Command> expiry
Command> key 1
Command> key 2
Command> expiry
Command> key 2
Command> key 3

And so on

Make sure you change it to a value it was not on already, or there will be no change. You can change it back to the original value later on: what is required now is a change, so that gpg-1.2.0 can create new subkey binding signatures.

Once all of this is done save.

Command> save

gnupg-1.2.0 will exit and save the new keybinding signatures, validating the migration of your old keys into your new master key.


10. Now edit the keys using the standard (current) gnupg, to see if it worked.

Open the same key for editing using the standard, system-wide version of gpg, to see if it worked. If it worked, you will see two things:

  1. The expiry dates will be the new expiry dates you have just changed to in step 9, and not the original ones.
  2. The usage flags to the right of the subkeys will display "usage:SCEA"

.

$ gpg --edit-key CB577A43
--------------------------
pub  4096R/CB577A43  created: 2013-03-21  expires: [newdate]     usage: SC  
                     trust: unknown      validity: unknown
sub  2048R/712A2BBD  created: 2013-01-29  expires: [newdate]     usage: SCEA
sub  2048R/F0B63FDA  created: 2013-01-29  expires: [newdate]     usage: SCEA

If it did not work, the usage flags will be blank, and the expiry date will now show the change you just made in step 9.

$ gpg --edit-key CB577A43
--------------------------
pub  4096R/CB577A43  created: 2013-03-21  expires: **never**     usage: SC  
                     trust: unknown      validity: unknown
sub  2048R/712A2BBD  created: 2013-01-29  expires: **never**     usage: 
sub  2048R/F0B63FDA  created: 2013-01-29  expires: **never**     usage: 

Finally, you need to put it through one export/import cycle, and delete the keys in between. If it survives this, the procedure has worked.

$ gpg --export-secret-keys CB577A43 > CB577A43_new.secret
$ gpg --export CB577A43 > CB577A43_new.public
$ gpg --delete-secret-and-public-keys CB577A43
$ gpg --import CB577A43_new.secret CB577A43_new.public
$ gpg --edit-key CB577A43
--------------------------
pub  4096R/CB577A43  created: 2013-03-21  expires: [newdate]     usage: SC  
                     trust: unknown      validity: unknown
sub  2048R/712A2BBD  created: 2013-01-29  expires: [newdate]     usage: SCEA
sub  2048R/F0B63FDA  created: 2013-01-29  expires: [newdate]     usage: SCEA

11. Final tasks.

Assuming it worked, you will now need to cross certify your subkeys, so that they can create and verify signatures.

$ gpg --edit-key CB577A43

And from the gpg edit prompt:

gpg> cross-certify

You will also need to reset trust:

gpg> trust

Finally, make sure to test the key rigorously, to make sure it works before you distribute it. I refer back to the atom.smasher.org tutorial for these final steps:

  • check all expiration dates and preferences. some of these operations may have changed your expiration dates and preferences; reset as necessary.

  • test out all key components for creating and verifying signatures, and encryption/decryption. use the bang (!) to force each (sub)key: create & verify signatures:

$ date | gpg -u '712A2BBD!' --clearsign | gpg -v --verify
$ date | gpg -u 'F0B63FDA!' --clearsign | gpg -v --verify

encrypt/decrypt:

$ date | gpg -ear '712A2BBD!' | gpg -v --decrypt
$ date | gpg -ear 'F0B63FDA!' | gpg -v --decrypt
  • after testing out the keys locally, send your new public key to one or two people and test all key components (sending signed/encrypted messages to each other using all key components). make sure that they first delete (from their keyrings) your old key! and make sure that they understand that the key should NOT be circulated until all functions are verified to be working!

  • when putting the new key into circulation, it's probably a good idea to expire/revoke the old key. include a revocation comment that specifies the new key ID and instructions to delete the old key from the keyring.

  • note on key revocation: according to the OpenPGP standards a revocation generated by a sub key will be ignored, unless that subkey has been designated (by the primary key) as a revocation key. GnuPG seems to behave correctly, but some versions of PGP(tm) may not. if someone is claiming that your new key is revoked, have then remove all of your old and current keys from their keyring: then re-import your current key(s).

share|improve this answer

This may simply be a matter of deleting the subkeys from your key server, as I think when you're trying to import the signatures, you're overwriting the key types back to their original value.

If your consolidated keys don't have the signatures you're expecting, you may need to verify they're in the keys you're splitting, and are added back correctly when reassembling them. Is it perhaps an ordering issue when you're concatenating them? Or are you missing signatures of the master signing the subkeys when they are reassembled (sig type 0x18: subkey binding sig)?

I'd suggest creating a new master key with three subkeys just like what you want your final product to look like, then dumping or splitting it to see how it's constructed, and finally assembling your original master key with subkeys in the same order with all the same pieces. Pay attention to the signature types in pgpdump, as you may have to create some of them. gpg --edit-key may help with that and with checking what sigs the keys have.

Then push your updated keys up to the server before attempting to download them again.

edit: I should add, if any of the subkey signatures your trying to restore are from any of the other subkeys, they should probably be omitted, as they don't make sense in their new context. In fact, I'd verify that subkeys are normally signed at all, or if only the master key is normally signed.

share|improve this answer

Unfortunately, your best option would be to revoke the keys, create a new one with the subkeys you want, and upload that to the keyserver. I tried to do this splitting-and-merging thing a few years ago, and ran into similar problems to you. I eventually ran into an excellent article showing why it doesn't work, but I can't seem to find it. If I do, I will post the link.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.