From 309ff8afbf8a592b668c7539583b44656e68501c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 21 Dec 2013 09:45:23 -0800 Subject: [PATCH] Decode the string-to-key count for iterated and salted S2Ks We need this for decryption. From RFC 4880 [1]: The count is coded into a one-octet number using the following formula: #define EXPBIAS 6 count = ((Int32)16 + (c & 15)) << ((c >> 4) + EXPBIAS); The above formula is in C, where "Int32" is a type for a 32-bit integer, and the variable "c" is the coded count, Octet 10. [1]: http://tools.ietf.org/search/rfc4880#section-3.7.1.3 --- gpg-migrate.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/gpg-migrate.py b/gpg-migrate.py index 9f775e1..f8c1fd4 100755 --- a/gpg-migrate.py +++ b/gpg-migrate.py @@ -184,6 +184,8 @@ class PGPPacket (dict): 110: 'private', } + _string_to_key_expbias = 6 + _signature_types = { 0x00: 'binary document', 0x01: 'canonical text document', @@ -415,6 +417,15 @@ class PGPPacket (dict): offset += length return (offset, value) + @classmethod + def _decode_string_to_key_count(cls, data): + r"""Decode RFC 4880's string-to-key count + + >>> PGPPacket._decode_string_to_key_count(b'\x97'[0]) + 753664 + """ + return (16 + (data & 15)) << ((data >> 4) + cls._string_to_key_expbias) + def _parse_string_to_key_specifier(self, data): self['string-to-key-type'] = self._string_to_key_types[data[0]] offset = 1 @@ -434,7 +445,8 @@ class PGPPacket (dict): offset += 1 self['string-to-key-salt'] = data[offset: offset + 8] offset += 8 - self['string-to-key-coded-count'] = data[offset] + self['string-to-key-count'] = self._decode_string_to_key_count( + data=data[offset]) offset += 1 else: raise NotImplementedError( @@ -736,6 +748,21 @@ class PGPPacket (dict): integer = integer >> 8 return b''.join(chunks) + @classmethod + def _encode_string_to_key_count(cls, count): + r"""Encode RFC 4880's string-to-key count + + >>> PGPPacket._encode_string_to_key_count(753664) + b'\x97' + """ + coded_count = 0 + count = count >> cls._string_to_key_expbias + while not count & 1: + count = count >> 1 + coded_count += 1 << 4 + coded_count += count & 15 + return bytes([coded_count]) + def _serialize_string_to_key_specifier(self): string_to_key_type = bytes([ self._reverse( @@ -753,7 +780,8 @@ class PGPPacket (dict): chunks.append(bytes([self._reverse( self._hash_algorithms, self['string-to-key-hash-algorithm'])])) chunks.append(self['string-to-key-salt']) - chunks.append(bytes([self['string-to-key-coded-count']])) + chunks.append(self._encode_string_to_key_count( + count=self['string-to-key-count'])) else: raise NotImplementedError( 'string-to-key type {}'.format(self['string-to-key-type'])) -- 2.26.2