From 0259ecd09774789d56789b361b839a347dc6c88b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 18 Dec 2013 21:52:42 -0800 Subject: [PATCH] Add public key parsing to PGPPacket Use the same parser for public-key and public-subkey packets. From RFC 4880 [1]: A Public-Subkey packet (tag 14) has exactly the same format as a Public-Key packet, but denotes a subkey. One or more subkeys may be associated with a top-level key. The generic (sub)key parsing is specified in section 5.5.2 [2]: OpenPGP implementations MUST create keys with version 4 format. V3 keys are deprecated; an implementation MUST NOT generate a V3 key, but MAY accept it. ... A version 4 packet contains: - A one-octet version number (4). - A four-octet number denoting the time that the key was created. - A one-octet number denoting the public-key algorithm of this key. - A series of multiprecision integers comprising the key material. Also check that the --export packets begin with a public-key packet. From RFC 4880 [3]: A Public-Key packet starts a series of packets that forms an OpenPGP key (sometimes called an OpenPGP certificate). [1]: http://tools.ietf.org/search/rfc4880#section-5.5.1.2 [2]: http://tools.ietf.org/search/rfc4880#section-5.5.2 [3]: http://tools.ietf.org/search/rfc4880#section-5.5.1.1 --- gpg-migrate.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/gpg-migrate.py b/gpg-migrate.py index f754aef..066463b 100755 --- a/gpg-migrate.py +++ b/gpg-migrate.py @@ -96,6 +96,25 @@ class PGPPacket (dict): self['type'] = self._packet_types[type_code] return offset + def _parse_public_key_packet(self, data): + self._parse_generic_public_key_packet(data=data) + + def _parse_public_subkey_packet(self, data): + self._parse_generic_public_key_packet(data=data) + + def _parse_generic_public_key_packet(self, data): + self['key-version'] = data[0] + offset = 1 + if self['key-version'] != 4: + raise NotImplementedError( + 'public (sub)key packet version {}'.format( + self['key-version'])) + length = 5 + self['creation_time'], self['public-key-algorithm'] = _struct.unpack( + '>IB', data[offset: offset + length]) + offset += length + self['key'] = data[offset:] + def to_bytes(self): pass @@ -119,6 +138,10 @@ def migrate(old_key, new_key): ['gpg', '--export', old_key]) old_key_packets = list( packets_from_bytes(data=old_key_export)) + if old_key_packets[0]['type'] != 'public-key packet': + raise ValueError( + '{} does not start with a public-key packet'.format( + old_key)) old_key_secret_export = _get_stdout( ['gpg', '--export-secret-keys', old_key]) old_key_secret_packets = list( -- 2.26.2