From 0c4c22c896c6f4be34bca6411045ebad344e988e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sun, 22 Dec 2013 16:23:47 -0800 Subject: [PATCH] Add a serialization check after parsing Ensure that we can serialize everything we parse, using the input data as a check against our output. --- gpg-migrate.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/gpg-migrate.py b/gpg-migrate.py index f3eb3f9..8d475f7 100755 --- a/gpg-migrate.py +++ b/gpg-migrate.py @@ -411,6 +411,7 @@ class PGPPacket (dict): raise NotImplementedError( 'cannot parse packet type {!r}'.format(self['type'])) method(data=packet) + self['raw'] = data[:offset] return offset def _parse_header(self, data): @@ -978,6 +979,27 @@ class PGPPacket (dict): plaintext = plaintext[:-padding] return plaintext + def check_roundtrip(self): + serialized = self.to_bytes() + source = self['raw'] + if serialized != source: + if len(serialized) != len(source): + raise ValueError( + ('serialized {} is {} bytes long, ' + 'but input is {} bytes long').format( + self['type'], len(serialized), len(source))) + chunk_size = 8 + for i in range(0, len(source), 8): + in_chunk = source[i: i + chunk_size] + out_chunk = serialized[i: i + chunk_size] + if in_chunk != out_chunk: + raise ValueError( + ('serialized {} differs from input packet: ' + 'at byte {}, {} != {}').format( + self['type'], i, + ' '.join('{:02x}'.format(byte) for byte in out_chunk), + ' '.join('{:02x}'.format(byte) for byte in in_chunk))) + class PGPKey (object): """An OpenPGP key with public and private parts. @@ -1055,6 +1077,8 @@ class PGPKey (object): raise ValueError( '{} does not start with a secret-key packet'.format( self.fingerprint)) + for packet in self.public_packets + self.secret_packets: + packet.check_roundtrip() def _packets_from_bytes(self, data): offset = 0 -- 2.26.2