Add secret-key decryption to _parse_generic_secret_key_packet
authorW. Trevor King <wking@tremily.us>
Sat, 21 Dec 2013 05:19:59 +0000 (21:19 -0800)
committerW. Trevor King <wking@tremily.us>
Mon, 23 Dec 2013 02:32:15 +0000 (18:32 -0800)
The checksum checks will fail with encrypted algorithm-specific key
data.  This adds handling to decrypt the encrypted section with a new
PGPPacket.decrypt_symmetric_encryption stub that still needs to be
filled in.  From RFC 4880 [1]:

   With V4 keys, a simpler method is used.  All secret MPI values are
   encrypted in CFB mode, including the MPI bitcount prefix.

   The two-octet checksum that follows the algorithm-specific portion
   is the algebraic sum, mod 65536, of the plaintext of all the
   algorithm- specific octets (including MPI prefix and data).  With
   V3 keys, the checksum is stored in the clear.  With V4 keys, the
   checksum is encrypted like the algorithm-specific data.

[1]: http://tools.ietf.org/search/rfc4880#section-5.5.3

gpg-migrate.py

index 3444982a39257b1948d30aabfca14dbe57509faa..785f78eeec4dea5a40068f8efbd90be566e3d914 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+import getpass as _getpass
 import hashlib as _hashlib
 import math as _math
 import re as _re
@@ -518,15 +519,20 @@ class PGPPacket (dict):
                         self['symmetric-encryption-algorithm']))
             self['initial-vector'] = data[offset: offset + block_size]
             offset += block_size
+            ciphertext = data[offset:]
+            offset += len(ciphertext)
+            decrypted_data = self.decrypt_symmetric_encryption(data=ciphertext)
+        else:
+            decrypted_data = data[offset:key_end]
         if string_to_key_usage in [0, 255]:
             key_end = -2
         elif string_to_key_usage == 254:
             key_end = -20
         else:
             key_end = 0
-        secret_key = data[offset:key_end]
+        secret_key = decrypted_data[:key_end]
         if key_end:
-            secret_key_checksum = data[key_end:]
+            secret_key_checksum = decrypted_data[key_end:]
             if key_end == -2:
                 calculated_checksum = sum(secret_key) % 65536
             else:
@@ -783,6 +789,9 @@ class PGPPacket (dict):
                     self['public-key-algorithm']))
         return b''.join(chunks)
 
+    def decrypt_symmetric_encryption(self, data):
+        raise NotImplementedError('decrypt symmetric encryption')
+
 
 def packets_from_bytes(data):
     offset = 0