Extract the packet tag
authorW. Trevor King <wking@tremily.us>
Thu, 19 Dec 2013 03:51:10 +0000 (19:51 -0800)
committerW. Trevor King <wking@tremily.us>
Thu, 19 Dec 2013 04:05:14 +0000 (20:05 -0800)
From RFC 4880 [1]:

  The first octet of the packet header is called the "Packet Tag".  It
  determines the format of the header and denotes the packet contents.
  The remainder of the packet header is the length of the packet.

  Note that the most significant bit is the leftmost bit, called bit
  7.  A mask for this bit is 0x80 in hexadecimal.

              +---------------+
         PTag |7 6 5 4 3 2 1 0|
              +---------------+
         Bit 7 -- Always one
         Bit 6 -- New packet format if set

  PGP 2.6.x only uses old format packets.  Thus, software that
  interoperates with those versions of PGP must only use old format
  packets.  If interoperability is not an issue, the new packet format
  is RECOMMENDED.  Note that old format packets have four bits of
  packet tags, and new format packets have six; some features cannot
  be used and still be backward-compatible.

  Also note that packets with a tag greater than or equal to 16 MUST
  use new format packets.  The old format packets can only express
  tags less than or equal to 15.

  Old format packets contain:

         Bits 5-2 -- packet tag
         Bits 1-0 -- length-type

  New format packets contain:

         Bits 5-0 -- packet tag

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

gpg-migrate.py

index e6f1f3811a1056a524e126a6744c5d7cf1e2d432..1eb09be90fabd506622a8743f843447e84342ed7 100755 (executable)
@@ -19,7 +19,16 @@ def _get_stdout(args, stdin=None):
 class PGPPacket (dict):
     # http://tools.ietf.org/search/rfc4880
     def from_bytes(self, data):
-        pass
+        packet_tag = data[0]
+        always_one = packet_tag & 1 << 7
+        if not always_one:
+            raise ValueError('most significant packet tag bit not set')
+        self['new-format'] = packet_tag & 1 << 6
+        if self['new-format']:
+            self['packet-tag'] = packet_tag & 0b111111
+        else:
+            self['packet-tag'] = packet_tag >> 2 & 0b1111
+            self['length-type'] = packet_tag & 0b11
 
     def to_bytes(self):
         pass