Transfer subkey to other keyring
Jack Bates
di44vq at nottheoilrig.com
Fri Sep 13 01:18:32 CEST 2013
On 07/09/13 07:10 AM, Peter Lebbing wrote:
> On 27/06/13 18:55, Jack Bates wrote:
>> except that I am using the key id of a subkey, with an exclamation
>> mark, to export just one subkey instead of all the subkeys belonging to the
>> primary key. The subkey with that key id definitely doesn't already exist in the
>> destination keyring, although the destination keyring does already contain a
>> different subkey.
>
> I believe once GnuPG has a secret key, it won't update it anymore with any
> subsequent imports. So to get the additional subkey, re-export the whole thing,
> delete the existing one on the other system and import your re-exported whole thing.
>
> I'm also wondering why you're being so explicit about it in the first place,
> with transferring little chunks at a time using the exclamation mark instead of
> the whole thing. Is there something specific you're trying to achieve?
>
>> gpg: secret keys unchanged: 1
>
> This message to me implies it is actually possible to change something about a
> secret key. I haven't figured out what yet.
Thank you for following up Peter, I looked again and I think it's a
difference between public vs. secret subkeys. It will merge a new public
subkey with existing subkeys, but it won't merge a new secret subkey
with existing ones. Here is a first crack at a patch to merge new secret
subkeys similar to how it already handles public ones:
http://nottheoilrig.com/gnupg/201309120/merge.patch
I'd love to contribute a change like this to GnuPG, would a change like
this be welcome? (considered for inclusion?) If so, can anyone help me
review it and get it into shape? What is the right way to submit a patch
to GnuPG?
Here's what GnuPG does before and after the patch:
# Generate primary key
$ gpg2 --gen-key
pub 4096R/B575FAD1 2013-09-12
Key fingerprint = 19C1 3488 6B2A A80C E30A 6A96 4CB2 EAFB
B575 FAD1
uid John Doe <jdoe at example.com>
# Add subkey
$ gpg2 --edit-key B575FAD1 addkey
pub 4096R/B575FAD1 created: 2013-09-12 expires: never
usage: SC
trust: ultimate validity: ultimate
sub 4096R/3BEA5E48 created: 2013-09-12 expires: 2013-09-13
usage: S
# Export secret subkey
$ gpg2 --export-secret-subkeys 3BEA5E48! > 3BEA5E48
# Add another subkey
gpg2 --edit-key B575FAD1 addkey
pub 4096R/B575FAD1 created: 2013-09-12 expires: never
usage: SC
trust: ultimate validity: ultimate
sub 4096R/3BEA5E48 created: 2013-09-12 expires: 2013-09-13
usage: S
sub 4096R/1F01C58C created: 2013-09-12 expires: 2013-09-13
usage: S
# Export other secret subkey
$ gpg2 --export-secret-subkeys 1F01C58C! > 1F01C58C
# Start over with an empty keyring
$ rm -r ~/.gnupg
# Import first subkey
$ gpg2 --import 3BEA5E48
gpg: key B575FAD1: secret key imported
gpg: key B575FAD1: public key "John Doe <jdoe at example.com>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg: secret keys read: 1
gpg: secret keys imported: 1
Here's what it does before the patch:
# Import second subkey
$ gpg2 --import 1F01C58C
gpg: key B575FAD1: already in secret keyring
gpg: Total number processed: 1
gpg: secret keys read: 1
gpg: secret keys unchanged: 1
$ gpg2 -K
sec# 4096R/B575FAD1 2013-09-12
uid John Doe <jdoe at example.com>
ssb 4096R/3BEA5E48 2013-09-12
And here's what happens after the patch:
# Import second subkey
$ gpg2 --import 1F01C58C
gpg: key B575FAD1: "John Doe <jdoe at example.com>" 1 new signature
gpg: key B575FAD1: "John Doe <jdoe at example.com>" 1 new subkey
gpg: key B575FAD1: "John Doe <jdoe at example.com>" 1 new signature
gpg: key B575FAD1: "John Doe <jdoe at example.com>" 1 new subkey
gpg: Total number processed: 1
gpg: new subkeys: 2
gpg: new signatures: 2
gpg: secret keys read: 1
$ gpg2 -K
sec# 4096R/B575FAD1 2013-09-12
uid John Doe <jdoe at example.com>
ssb 4096R/3BEA5E48 2013-09-12
ssb 4096R/1F01C58C 2013-09-12
I looked at the code in gnupg/g10/import.c and when you import
something, the import() procedure gets called once by
import_keys_internal(), etc. The import_one() procedure gets called if
import() finds a PKT_PUBLIC_KEY keyblock and import_secret_one() gets
called if it finds a PKT_SECRET_KEY keyblock. After import_secret_one()
imports a new secret key, it converts it to a public key with
sec_to_pub_keyblock() and passes that to import_one().
import_one() and import_secret_one() both check if the key already
exists in the keyring. If import_one() finds that it does, it reads the
existing keyblock, calls merge_blocks(), and if anything changed it
writes back the updated keyblock.
However if import_secret_one() finds that the key already exists,
currently it just says:
1273 else if( !rc )
1274 { /* we can't merge secret keys */
1275 log_error( _("key %s: already in secret keyring\n"),
1276 keystr_from_sk(sk));
1277 stats->secret_dups++;
1278 if (is_status_enabled ())
1279 print_import_ok (NULL, sk, 16);
1280
1281 /* TODO: if we ever do merge secret keys, make sure to handle
1282 the sec_to_pub_keyblock feature as well. */
1283 }
To make the patch, I cargo-culted a combination of code from where
import_secret_one() imports new secret keys and where import_one()
merges new public subkeys with existing ones. It reads the existing
keyblock, calls merge_blocks(), and writes back the updated keyblock if
anything changed.
I am grateful for feedback or help getting the patch into shape, if this
is a welcome change.
Thanks!
More information about the Gnupg-users
mailing list