class MAC(object): """Class describing the MAC algorithm to use and how to get the key. Instances of this class provide the following attributes: algorithm: the name of the HMAC to use (currently only HMAC_SHA1) key: the binary value of the MAC key if it can be decrypted """ def __init__(self, pskc, mac_method=None): from pskc.encryption import EncryptedValue self.algorithm = None self._mac_key = EncryptedValue(pskc.encryption) self.parse(mac_method) def parse(self, mac_method): """Read MAC information from the <MACMethod> XML tree.""" from pskc.xml import find, findtext if mac_method is None: return self.algorithm = mac_method.get('Algorithm') self._mac_key.parse(find(mac_method, 'pskc:MACKey')) mac_key_reference = findtext(mac_method, 'pskc:MACKeyReference') @property def key(self): """Provides access to the MAC key binary value if available.""" return self._mac_key.decrypt()
def __init__(self, key, element=None): self.value = None self.encrypted_value = EncryptedValue(key.pskc.encryption) self.value_mac = ValueMAC(key.pskc.mac) self.parse(element)
class DataType(object): """Provide access to possibly encrypted, MAC'ed information. This class is meant to be subclassed to provide typed access to stored values. Instances of this class provide the following attributes: value: unencrypted value if present encrypted_value: reference to an EncryptedValue instance value_mac: reference to a ValueMAC instance """ def __init__(self, key, element=None): self.value = None self.encrypted_value = EncryptedValue(key.pskc.encryption) self.value_mac = ValueMAC(key.pskc.mac) self.parse(element) def parse(self, element): """Read information from the provided element. The element is expected to contain <PlainValue>, <EncryptedValue> and/or ValueMAC elements that contain information on the actual value.""" from pskc.xml import find, findtext if element is None: return value = findtext(element, "pskc:PlainValue") if value is not None: self.value = self.from_text(value) self.encrypted_value.parse(find(element, "pskc:EncryptedValue")) self.value_mac.parse(find(element, "pskc:ValueMAC")) def make_xml(self, key, tag): from pskc.xml import find, mk_elem # skip empty values value = self.get_value() if value is None: return # find the data tag and create our tag under it data = find(key, "pskc:Data") if data is None: data = mk_elem(key, "pskc:Data", empty=True) element = mk_elem(data, tag, empty=True) mk_elem(element, "pskc:PlainValue", self.to_text(self.value)) def get_value(self): """Provide the raw binary value.""" if self.value is not None: return self.value if self.encrypted_value.cipher_value: # check MAC and decrypt self.check() return self.from_bin(self.encrypted_value.decrypt()) def set_value(self, value): """Set the unencrypted value.""" self.value = value self.encrypted_value.cipher_value = None def check(self): """Check whether the embedded MAC is correct.""" # this checks the encrypted value return self.value_mac.check(self.encrypted_value.cipher_value)
def __init__(self, pskc, mac_method=None): from pskc.encryption import EncryptedValue self.algorithm = None self._mac_key = EncryptedValue(pskc.encryption) self.parse(mac_method)