diff --git a/pgpdump/packet.py b/pgpdump/packet.py index 8ee7f7d..39e79f9 100644 --- a/pgpdump/packet.py +++ b/pgpdump/packet.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta import hashlib import re +import binascii from .utils import (PgpdumpException, get_int2, get_int4, get_mpi, get_key_id, get_int_bytes) @@ -334,6 +335,7 @@ def __init__(self, *args, **kwargs): self.group_order = None self.group_gen = None self.key_value = None + self.serial = None super(PublicKeyPacket, self).__init__(*args, **kwargs) def parse(self): @@ -375,22 +377,25 @@ def parse(self): self.pubkey_version) self.fingerprint = md5.hexdigest().upper().encode('ascii') elif self.pubkey_version == 4: + self.raw_pub_algorithm = self.data[offset+4] + # This trickery with afterkey_offset is to avoid confusion from + # special parameters that are present e.g. for card readers. + # Fingerprint/key_id would be screwed if the special params were + # used in hash computation. + afterkey_offset = self.parse_key_material(offset+5) + sha1 = hashlib.sha1() - seed_bytes = (0x99, (self.length >> 8) & 0xff, self.length & 0xff) + seed_bytes = (0x99, (afterkey_offset >> 8) & 0xff, afterkey_offset & 0xff) sha1.update(bytearray(seed_bytes)) - sha1.update(self.data) + sha1.update(self.data[:afterkey_offset]) self.fingerprint = sha1.hexdigest().upper().encode('ascii') self.key_id = self.fingerprint[24:] self.raw_creation_time = get_int4(self.data, offset) self.creation_time = datetime.utcfromtimestamp( self.raw_creation_time) - offset += 4 - - self.raw_pub_algorithm = self.data[offset] - offset += 1 - offset = self.parse_key_material(offset) + offset = afterkey_offset else: raise PgpdumpException("Unsupported public key packet, version %d" % self.pubkey_version) @@ -543,6 +548,26 @@ def parse(self): offset += 1 if mode == 1001: has_iv = False + elif mode == 1002: + # gnu-divert-to-card S2K - divert to HSM or card reader + serial_len = self.data[offset] + + # This is not a real IV, even though gnupg stores it in + # IV structure internally + has_iv = False + + # This guessing of hash length is ugly, but it's taken from + # gnupg 2.0.19's g10/parse-packet.c line 1945 - + # self.lookup_sym_algorithm_iv may not work in this case. + if serial_len > 16: + serial_len = 16 + offset += 1 + s2k_length += 1 + + # Keys tied to tokens and smart cards have token serial ID + # stored here. + serial_bin = self.data[offset:offset + serial_len] + self.serial = binascii.hexlify(serial_bin).upper() else: # TODO implement other modes? raise PgpdumpException(