Add PGPKey with a basic key-level API
authorW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 19:43:21 +0000 (11:43 -0800)
committerW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 23:18:13 +0000 (15:18 -0800)
This currently handles importing keys from GnuPG and stubs out a
key-stringification framework along the lines of the existing
packet-parsing framework in PGPPacket.from_bytes.

gpg-migrate.py

index fb5ea92e8fe75c37f9cdc7e2222a8cc0ea1f5a06..5b9ef10f5e2cada317096032b66201c7af4c032e 100755 (executable)
@@ -190,6 +190,17 @@ class PGPPacket (dict):
     def _clean_type(self):
         return self._clean_type_regex.sub('_', self['type'])
 
+    def __str__(self):
+        method_name = '_str_{}'.format(self._clean_type())
+        method = getattr(self, method_name, None)
+        if not method:
+            return self['type']
+        details = method()
+        return '{}: {}'.format(self['type'], details)
+
+    def _str_user_id_packet(self):
+        return self['user']
+
     def from_bytes(self, data):
         offset = self._parse_header(data=data)
         packet = data[offset:offset + self['length']]
@@ -410,6 +421,42 @@ def packets_from_bytes(data):
         yield packet
 
 
+class PGPKey (object):
+    def __init__(self, fingerprint):
+        self.fingerprint = fingerprint
+        self.public_packets = None
+        self.secret_packets = None
+
+    def __str__(self):
+        lines = ['key: {}'.format(self.fingerprint)]
+        if self.public_packets:
+            lines.append('  public:')
+            for packet in self.public_packets:
+                lines.append('    {}'.format(packet))
+        if self.secret_packets:
+            lines.append('  secret:')
+            for packet in self.secret_packets:
+                lines.append('    {}'.format(packet))
+        return '\n'.join(lines)
+
+    def import_from_gpg(self):
+        key_export = _get_stdout(
+            ['gpg', '--export', self.fingerprint])
+        self.public_packets = list(
+            packets_from_bytes(data=key_export))
+        if self.public_packets[0]['type'] != 'public-key packet':
+            raise ValueError(
+                '{} does not start with a public-key packet'.format(
+                    self.fingerprint))
+        key_secret_export = _get_stdout(
+            ['gpg', '--export-secret-keys', self.fingerprint])
+        self.secret_packets = list(
+            packets_from_bytes(data=key_secret_export))
+
+    def export_to_gpg(self):
+        raise NotImplemetedError('export to gpg')
+
+
 def migrate(old_key, new_key):
     """Add the old key and sub-keys to the new key
 
@@ -417,22 +464,13 @@ def migrate(old_key, new_key):
     signatures you'd made.  You will lose signature *on* your old key
     though, since sub-keys can't be signed (I don't think).
     """
-    old_key_export = _get_stdout(
-        ['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(
-        packets_from_bytes(data=old_key_secret_export))
-
-    import pprint
-    pprint.pprint(old_key_packets)
-    pprint.pprint(old_key_secret_packets)
+    old_key = PGPKey(fingerprint=old_key)
+    old_key.import_from_gpg()
+    new_key = PGPKey(fingerprint=new_key)
+    new_key.import_from_gpg()
+
+    print(old_key)
+    print(new_key)
 
 
 if __name__ == '__main__':