Missing uid in secret key

How I dealt with this problem

For some reason, I was missing my UID on my secret ring, although it existed on my public ring, this is a story about what happened and what I did to fix it.

I don’t know why/how this happened, but someone pointed out to me that they had a similar problem and the reason for the missing uid in the secret key was that they had added the uid on their desktop computer and sent the public key to the keyserver. Later, they refreshed the keys on their laptop from the keyserver, which made the new uid appear in the public key, but of course not in the secret key.

Many thanks to dkg who I could not have done this without.

If I edit my key:

micah@lillypad> gpg --edit-key 7355FAFF                          
Secret key is available.

pub  1024D/7355FAFF  created: 2000-12-31  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  2048g/C252AFCD  created: 2000-12-31  expires: never       usage: E   
sub  2048R/3EFFEA75  created: 2008-09-02  expires: never       usage: A   
[ultimate] (1). Micah Anderson <micah@riseup.net>
[ultimate] (2)  Micah Anderson <micah@debian.org>
[ultimate] (3)  Micah Anderson <micah@indymedia.org>
[ultimate] (4)  Micah Johan Anderson <micah@riseup.net>

You see that I have UIDs in my public part of my key. However, as soon as I switch to the secret keyring, I am missing UIDs:

Command> toggle

sec  1024D/7355FAFF  created: 2000-12-31  expires: never     
ssb  2048g/C252AFCD  created: 2000-12-31  expires: never     

I could also see this by doing the following:

micah@lillypad> gpg --list-secret-keys
./secring.gpg
-------------
sec   1024D/7355FAFF 2000-12-31
ssb   2048g/C252AFCD 2000-12-31

I discovered this when I had first exported my secret keys to a file, and then attempted to re-import them:

micah@lillypad> gpg --export-secret-keys 7355faff > 7355faff                           
micah@lillypad> mv ~/.gnupg/secring.gpg{,.bak}; touch ~/.gnupg/secring.gpg; chmod 600 secring.gpg
micah@lillypad> gpg --import < 7355faff
gpg: key 7355FAFF: no user ID
gpg: Total number processed: 1
gpg:       secret keys read: 1

Although it processed and read one secret key, because there was no user ID, it didn’t actually import it:

micah@lillypad> gpg --list-secret-keys   
micah@lillypad> 

Nothing there!

If I added verbosity to the import, it shows that the exported secret keyfile that I had simply did not have any uid packets:

micah@lillypad> gpg --verbose --import --verbose < 7355faff            
:secret key packet:
	version 4, algo 17, created 978297126, expires 0
	skey[0]: [1024 bits]
	skey[1]: [160 bits]
	skey[2]: [1022 bits]
	skey[3]: [1023 bits]
	iter+salt S2K, algo: 3, simple checksum, hash: 2, salt: 8245d6357e5321f7
	protect count: 96
	protect IV:  b7 3a 0c 97 ee 45 9d a8
	encrypted stuff follows
:secret sub key packet:
	version 4, algo 16, created 978297145, expires 0
	skey[0]: [2048 bits]
	skey[1]: [3 bits]
	skey[2]: [2048 bits]
	iter+salt S2K, algo: 3, simple checksum, hash: 2, salt: 8245d6357e5321f7
	protect count: 96
	protect IV:  3e dc 21 58 78 4d bd a4
	encrypted stuff follows
:signature packet: algo 17, keyid C4E00BB37355FAFF
	version 4, created 978297145, md5len 0, sigclass 0x18
	digest algo 2, begin of digest c2 a0
	hashed subpkt 2 len 4 (sig created 2000-12-31)
	subpkt 16 len 8 (issuer key ID C4E00BB37355FAFF)
	data: [160 bits]
	data: [160 bits]
gpg: sec  1024D/7355FAFF 2000-12-31   
gpg: key 7355FAFF: no user ID
gpg: Total number processed: 1
gpg:       secret keys read: 1

That shows a secret key packet, a secret subkey packet, and a signature packet, but no user_id packet!

Arg… I know I have a userid on the public part, and its been self-signed, but the secret part doesn’t have it, and now it wont import it.

This is how I solved it.

  1. First I created two directories, one for the secret key, and one for the public key, and then I exported them and sent that export through gpgsplit, which splits up the packets into individual components:
micah@lillypad> mkdir sec ; cd sec
micah@lillypad> gpg --export-secret-keys 7355FAFF | gpgsplit                           
micah@lillypad> ls
000001-005.secret_key  000002-007.secret_subkey  000003-002.sig
micah@lillypad> cd ..                                                                      
micah@lillypad> mkdir pub                                                                      
micah@lillypad> gpg --export 7355FAFF | (cd pub && gpgsplit)                                   
micah@lillypad> cd pub                                                                         
micah@lillypad> ls                                                                         
000001-006.public_key  000179-002.sig      000357-002.sig      000535-002.sig
000002-013.user_id     000180-002.sig      000358-002.sig      000536-002.sig
000003-002.sig         000181-002.sig      000359-002.sig      000537-002.sig
000004-002.sig         000182-002.sig      000360-002.sig      000538-002.sig
000005-002.sig         000183-002.sig      000361-002.sig      000539-002.sig
000006-002.sig         000184-002.sig      000362-002.sig      000540-002.sig
....

I have a bunch of signatures so I didn’t list them all. I also have four user_ids on my key:

micah@lillypad> ls *user_id*                                                               
000002-013.user_id  000127-013.user_id  000329-013.user_id  000532-013.user_id

So, first I backed up my secring.gpg file, and created an empty one:

micah@lillypad> cd ~/.gnupg
micah@lillypad> mv secring.gpg secring.gpg.bak; touch secring.gpg; chmod 600 secring.gpg

Then I decided I would try to import all the secret key packets in order by concatenating them all together, and slap on the end all my user_id packets:

micah@lillypad> cat 000001-005.secret_key  000002-007.secret_subkey  000003-002.sig ../pub/*user_id* | gpg --import
gpg: key 7355FAFF: secret key imported
gpg: key 7355FAFF: no valid user IDs
gpg: this may be caused by a missing self-signature
gpg: Total number processed: 1
gpg:           w/o user IDs: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
[2] micah@lillypad> gpg --list-secret-keys                                                 ~/sec
/home/micah/.gnupg/secring.gpg
------------------------------
sec   1024D/7355FAFF 2000-12-31
ssb   2048g/C252AFCD 2000-12-31
uid                  Micah Anderson <micah@debian.org>
uid                  Micah Anderson <micah@riseup.net>
uid                  Micah Anderson <micah@indymedia.org>
uid                  Micah Johan Anderson <micah@riseup.net>

Close, it actually imported it without the user-id this time! Thats a step forwards, but I want those user-ids, and the hint about the missing self-signature made me realize I should also bring in the signature packets. It appears as if packets are typically assembled with the user_id packet followed immediately by the signature packet, I decided to import the concatenation of the user_id packet, and the signature packet that followed immediately thereafter.

First I re-created an empty secring.gpg file:

micah@lillypad> rm ../.gnupg/secring.gpg                                              

Then I concatenated them all together and imported them:

micah@lillypad> cat 000001-005.secret_key  000002-007.secret_subkey  000003-002.sig `ls ../pub | grep -A1 user_id | grep -v '^--$'`  | gpg --import
gpg: keyring `/home/micah/.gnupg/secring.gpg' created
gpg: key 7355FAFF: secret key imported
gpg: key 7355FAFF: "Micah Anderson <micah@riseup.net>" 1 new signature
gpg: Total number processed: 1
gpg:         new signatures: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Voila! Now if I export the secring and try and import it, I dont get that error any longer:

micah@lillypad> gpg --export-secret-keys 7355FAFF > test                   
micah@lillypad> mv ~/.gnupg/secring.gpg secring.gpg_test
micah@lillypad> gpg --import ../sec/test                                         
gpg: keyring `/home/micah/.gnupg/secring.gpg' created
gpg: key 7355FAFF: secret key imported
gpg: key 7355FAFF: "Micah Anderson <micah@riseup.net>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Hooray!