47

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.

unor
  • 1,769
  • 1
  • 19
  • 38
lz.
  • 571
  • 1
  • 4
  • 5

5 Answers5

41

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).

breakingbits
  • 511
  • 4
  • 6
  • 1
    Thanks for the really nice tutorial! Do you know if there is a new way to do this without GPG 1.2.0? I cannot seem to be able to install it on 64-bit Mac OS. `error: instruction requires: Not 64-bit mode` and as expected it's not easy to find solutions to problems for such old version. – Haralan Dobrev May 04 '16 at 21:16
  • 5
    Splitting the master key brings me closer to horcruxes than I ever wanted to be. – fbmd Jan 04 '17 at 07:28
8

There is an easy way to do this starting, if I am not mistaken, from GnuPG 2.1. You just create your new primary key and then add any other existing key as a subkey.

Here I have an old key:

$ gpg2 --with-keygrip -k
<...>
------------------------------------
pub   rsa2048 2017-05-31 [SC] [expires: 2019-05-31]
      3758BEEEA38377DC66708915C102DFD7B21740B0
      Keygrip = 42B4CE6092555D85F6BF93CEE13DC20A0B347048
uid           [ultimate] Mr Test
sub   rsa2048 2017-05-31 [E]
      Keygrip = A5CA49DB1EF812E278340BE6B8590D51F5EF9A2C

I first create a completely new primary key:

$ gpg2 --quick-generate-key 'Mr Test New'
About to create a key for:
    "Mr Test New"

Continue? (Y/n) y
<...>

pub   rsa2048 2017-05-31 [SC] [expires: 2019-05-31]
      4B496C1EF14F63BBA2F7C566AEA5541400F78E93
      4B496C1EF14F63BBA2F7C566AEA5541400F78E93
uid                      Mr Test New
sub   rsa2048 2017-05-31 [E]

(I used --quick-generate-key for simplicity. Of course, you can go with --generate-key or --full-generate-key if you wish.)

Next I will edit the new key using the --expert flag:

$ gpg2 --expert --edit-key 4B496C1EF14F63BBA2F7C566AEA5541400F78E93
<...>
sec  rsa2048/AEA5541400F78E93
     created: 2017-05-31  expires: 2019-05-31  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048/7882EFF25C40792B
     created: 2017-05-31  expires: never       usage: E
[ultimate] (1). Mr Test New

gpg>

I use the addkey subcommand and because of the --expert flag it will give me an option to add an existing key using its keygrip (it is option 13 in my example, but the numbers can change, so I chose to use the stable alias keygrip):

gpg> addkey
Please select what kind of key you want:
   <...>
  (13) Existing key
Your selection? keygrip
Enter the keygrip: 42B4CE6092555D85F6BF93CEE13DC20A0B347048

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? e

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 365
Key expires at Thu May 31 10:21:30 2018 MSK
Is this correct? (y/N) y
Really create? (y/N) y

sec  rsa2048/AEA5541400F78E93
     created: 2017-05-31  expires: 2019-05-31  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048/7882EFF25C40792B
     created: 2017-05-31  expires: never       usage: E
ssb  rsa2048/072D4F8908E1A926
     created: 2017-05-31  expires: 2018-05-31  usage: S
[ultimate] (1). Mr Test New

gpg>

(When asked about allowed actions, adjust the key capabilities properly as they will always default to sign&encrypt.)

This way you can add all the old primary keys and their subkeys to your new key. And don’t forget to save at the very end.

You can verify that this is indeed the same key by comparing the keygrips:

$ gpg2 --with-keygrip -k
<...>
------------------------------------
pub   rsa2048 2017-05-31 [SC] [expires: 2019-05-31]
      3758BEEEA38377DC66708915C102DFD7B21740B0
      Keygrip = 42B4CE6092555D85F6BF93CEE13DC20A0B347048
uid           [ultimate] Mr Test
sub   rsa2048 2017-05-31 [E]
      Keygrip = A5CA49DB1EF812E278340BE6B8590D51F5EF9A2C

pub   rsa2048 2017-05-31 [SC] [expires: 2019-05-31]
      4B496C1EF14F63BBA2F7C566AEA5541400F78E93
      Keygrip = CB90DD9613FC321B2E609D8ECB219657A6AFCFDD
uid           [ultimate] Mr Test New
sub   rsa2048 2017-05-31 [E]
      Keygrip = D0E14A5E1CD161CF2F18F9EBA53AB2EF12705679
sub   rsa2048 2017-05-31 [S] [expires: 2018-05-31]
      Keygrip = 42B4CE6092555D85F6BF93CEE13DC20A0B347048
kirelagin
  • 270
  • 3
  • 4
  • I have to point out a very important limitation that I have become aware of recently: the key’s fingerprint will change. For some reason that is not a problem for GnuPG, and I was still able to decrypt using the ke with a wrong fingerprint. But you should keep this in mind. – kirelagin Jun 21 '17 at 12:21
  • It seems that a key has its password changed to that of its new master when being added to a master key. Did you not find that? I'd like to keep them separate. – Craig Hicks May 02 '18 at 07:20
  • 2
    @CraigHicks GnuPG cannot have individual passwords for subkeys. See e.g. https://superuser.com/questions/879977/how-to-have-a-different-pass-phrase-for-a-gpg-subkey. – kirelagin May 02 '18 at 12:13
  • I agree that at least it is difficult, maybe impossible, and seemingly not practical. But I found this archived gnupg.org mail which implies that it is not the data structure that is the constraint, but rather the software interface. It claims to show a backhand method for achieving separate passwords: https://lists.gnupg.org/pipermail/gnupg-users/2013-July/047174.html . I'd really like to find some gpupg documentation on this issue but have found nothing so far. – Craig Hicks May 02 '18 at 22:46
  • See the comments to this answer https://superuser.com/a/335676/762751 for a modern un- or lightly-documented method to make individual passwords for subkeys. Please note my objection to trusting said method without more documentation. [ gpg-connect-agent 'PASSWD ' /bye ] – Craig Hicks May 03 '18 at 17:53
  • @kirelagin Can you please elaborate on the "very important limitation" of the key's fingerprint changing? What are the implications? Thanks! – friederbluemle Jun 01 '18 at 09:23
  • 2
    @friederbluemle The only implication for me was that OpenKeychain (for Android) did not see my keys on the smartcard. – kirelagin Jun 02 '18 at 08:34
  • 2
    I found that the fingerprint change can cause problems for ECDH, because the way GPG uses ECDH incorporates the key ID. It means the moved key can't be used to decrypt old messages. The fingerprint changes because of the timestamp, so a way to avoid this is to use --faked-system-time="!" and --ignore-time-conflict when using addkey. After that, call --edit-key again without the faked time and modify expiry (then save), which will reset the timestamp on the "subkey binding signature" and things will look normal-ish. – Sumudu Fernando Apr 04 '20 at 08:15
2

Thanks to breakingbits for the thorough walkthrough. The lost/broken usage flags can be corrected with a new selfsig. My research showed several posts in gnupg-users on the subject, all saying essentially "not supported but you can edit the code." One post cited by another thread provided a rough sketch of a code solution, but it doesn't in fact work. (This is the (*p) &= ~2 post; in recent gnupg-1.4 at least, it makes your local gpg parse your key to look as if you changed usage flags, but doesn't actually change your key material and it won't work in someone else's gpg, which is what you want after all.)

Since I found no extant solutions, I wrote a patch to gnupg-1.4 to really fix usage flags by allowing almost-arbitrary usage flag edits in --edit-key. It doesn't require changing expiry, which you may know is a common trick for forcing a selfsig update. You can find it here if you're interested: https://github.com/xdgc/gnupg/tree/dgc/usage-1-4.

dgc
  • 121
  • 1
1

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.

petiepooo
  • 117
  • 5
1

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.

felixphew
  • 121
  • 2