Add version-4-signature parsing to PGPPacket
authorW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 19:17:09 +0000 (11:17 -0800)
committerW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 23:18:13 +0000 (15:18 -0800)
From RFC 4880 [1]:

  The body of a version 4 Signature packet contains:

  - One-octet version number (4).
  - One-octet signature type.
  - One-octet public-key algorithm.
  - One-octet hash algorithm.
  - Two-octet scalar octet count for following hashed subpacket data.
    Note that this is the length in octets of all of the hashed
    subpackets; a pointer incremented by this number will skip over
    the hashed subpackets.
  - Hashed subpacket data set (zero or more subpackets).
  - Two-octet scalar octet count for the following unhashed subpacket
    data.  Note that this is the length in octets of all of the
    unhashed subpackets; a pointer incremented by this number will
    skip over the unhashed subpackets.
  - Unhashed subpacket data set (zero or more subpackets).
  - Two-octet field holding the left 16 bits of the signed hash value.
  - One or more multiprecision integers comprising the signature.
    This portion is algorithm specific, as described above.

I've stashed all of the algorithm-specific MPI values in the
'signature' field, because I don't care about verifying signatures at
the moment.

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

gpg-migrate.py

index 1d467fc600948545c406462faf0ac185e9ddf039..3df89900cf352d9936fa4201dfbb4be30287fe2a 100755 (executable)
@@ -372,9 +372,28 @@ class PGPPacket (dict):
     def _parse_signature_packet(self, data):
         self['signature-version'] = data[0]
         offset = 1
     def _parse_signature_packet(self, data):
         self['signature-version'] = data[0]
         offset = 1
-        raise NotImplementedError(
-            'signature packet version {}'.format(
-                self['signature-version']))
+        if self['signature-version'] != 4:
+            raise NotImplementedError(
+                'signature packet version {}'.format(
+                    self['signature-version']))
+        self['signature-type'] = self._signature_types[data[offset]]
+        offset += 1
+        self['public-key-algorithm'] = self._public_key_algorithms[
+            data[offset]]
+        offset += 1
+        self['hash-algorithm'] = self._hash_algorithms[data[offset]]
+        offset += 1
+        hashed_count = _struct.unpack('>H', data[offset: offset + 2])[0]
+        offset += 2
+        self['hashed-subpackets'] = data[offset: offset + hashed_count]
+        offset += hashed_count
+        unhashed_count = _struct.unpack('>H', data[offset: offset + 2])[0]
+        offset += 2
+        self['unhashed-subpackets'] = data[offset: offset + unhashed_count]
+        offset += unhashed_count
+        self['signed-hash-word'] = data[offset: offset + 2]
+        offset += 2
+        self['signature'] = data[offset:]
 
     def to_bytes(self):
         pass
 
     def to_bytes(self):
         pass