Add secret key parsing to PGPPacket
[gpg-migrate.git] / gpg-migrate.py
index 7fea58d141e630aeebbdc958da1e8d562b09228a..27054a00c363274215db7265bd7377a08aa150c2 100755 (executable)
@@ -99,6 +99,9 @@ class PGPPacket (dict):
         110: 'private',
         }
 
+    _cipher_block_size = {  # in bits
+        }
+
     _compression_algorithms = {
         0: 'uncompressed',
         1: 'zip',
@@ -303,6 +306,47 @@ class PGPPacket (dict):
                     self['public-key-algorithm']))
         return offset
 
+    def _parse_secret_key_packet(self, data):
+        self._parse_generic_secret_key_packet(data=data)
+
+    def _parse_secret_subkey_packet(self, data):
+        self._parse_generic_secret_key_packet(data=data)
+
+    def _parse_generic_secret_key_packet(self, data):
+        offset = self._parse_generic_public_key_packet(data=data)
+        string_to_key_usage = data[offset]
+        offset += 1
+        if string_to_key_usage in [255, 254]:
+            self['symmetric-encryption-algorithm'] = (
+                self._symmetric_key_algorithms[data[offset]])
+            offset += 1
+            offset += self._parse_string_to_key_specifier(data=data[offset:])
+        else:
+            self['symmetric-encryption-algorithm'] = (
+                self._symmetric_key_algorithms[string_to_key_usage])
+        if string_to_key_usage:
+            block_size_bits = self._cipher_block_size.get(
+                self['symmetric-encryption-algorithm'], None)
+            if block_size_bits % 8:
+                raise NotImplementedError(
+                    ('{}-bit block size for {} is not an integer number of bytes'
+                     ).format(
+                         block_size_bits, self['symmetric-encryption-algorithm']))
+            block_size = block_size_bits // 8
+            if not block_size:
+                raise NotImplementedError(
+                    'unknown block size for {}'.format(
+                        self['symmetric-encryption-algorithm']))
+            self['initial-vector'] = data[offset: offset + block_size]
+            offset += block_size
+        if string_to_key_usage in [0, 255]:
+            key_end = -2
+        else:
+            key_end = 0
+        self['secret-key'] = data[offset:key_end]
+        if key_end:
+            self['secret-key-checksum'] = data[key_end:]
+
     def to_bytes(self):
         pass