Source code for tlslite.handshakehashes

# Copyright (c) 2015, Hubert Kario
#
# See the LICENSE file for legal information regarding use of this file.
"""Handling cryptographic hashes for handshake protocol"""

from .utils.compat import compat26Str, compatHMAC
from .utils.cryptomath import MD5, SHA1
from .utils import tlshashlib as hashlib

[docs] class HandshakeHashes(object): """ Store and calculate necessary hashes for handshake protocol Calculates message digests of messages exchanged in handshake protocol of SSLv3 and TLS. """
[docs] def __init__(self): """Create instance""" self._handshakeMD5 = hashlib.md5() self._handshakeSHA = hashlib.sha1() self._handshakeSHA224 = hashlib.sha224() self._handshakeSHA256 = hashlib.sha256() self._handshakeSHA384 = hashlib.sha384() self._handshakeSHA512 = hashlib.sha512() self._handshake_buffer = bytearray()
[docs] def update(self, data): """ Add `data` to hash input. :param bytearray data: serialized TLS handshake message """ text = compat26Str(data) self._handshakeMD5.update(text) self._handshakeSHA.update(text) self._handshakeSHA224.update(text) self._handshakeSHA256.update(text) self._handshakeSHA384.update(text) self._handshakeSHA512.update(text) self._handshake_buffer += text
[docs] def digest(self, digest=None): """ Calculate and return digest for the already consumed data. Used for Finished and CertificateVerify messages. :param str digest: name of digest to return """ if digest is None: return self._handshakeMD5.digest() + self._handshakeSHA.digest() elif digest == 'md5': return self._handshakeMD5.digest() elif digest == 'sha1': return self._handshakeSHA.digest() elif digest == 'sha224': return self._handshakeSHA224.digest() elif digest == 'sha256': return self._handshakeSHA256.digest() elif digest == 'sha384': return self._handshakeSHA384.digest() elif digest == 'sha512': return self._handshakeSHA512.digest() elif digest == "intrinsic": return self._handshake_buffer else: raise ValueError("Unknown digest name")
[docs] def digestSSL(self, masterSecret, label): """ Calculate and return digest for already consumed data (SSLv3 version) Used for Finished and CertificateVerify messages. :param bytearray masterSecret: value of the master secret :param bytearray label: label to include in the calculation """ #pylint: disable=maybe-no-member imacMD5 = self._handshakeMD5.copy() imacSHA = self._handshakeSHA.copy() #pylint: enable=maybe-no-member # the below difference in input for MD5 and SHA-1 is why we can't reuse # digest() method imacMD5.update(compatHMAC(label + masterSecret + bytearray([0x36]*48))) imacSHA.update(compatHMAC(label + masterSecret + bytearray([0x36]*40))) md5Bytes = MD5(masterSecret + bytearray([0x5c]*48) + \ bytearray(imacMD5.digest())) shaBytes = SHA1(masterSecret + bytearray([0x5c]*40) + \ bytearray(imacSHA.digest())) return md5Bytes + shaBytes
#pylint: disable=protected-access, maybe-no-member
[docs] def copy(self): """ Copy object Return a copy of the object with all the hashes in the same state as the source object. :rtype: HandshakeHashes """ other = HandshakeHashes() other._handshakeMD5 = self._handshakeMD5.copy() other._handshakeSHA = self._handshakeSHA.copy() other._handshakeSHA224 = self._handshakeSHA224.copy() other._handshakeSHA256 = self._handshakeSHA256.copy() other._handshakeSHA384 = self._handshakeSHA384.copy() other._handshakeSHA512 = self._handshakeSHA512.copy() other._handshake_buffer = bytearray(self._handshake_buffer) return other