Commit 3a94d054 authored by Arthur de Jong's avatar Arthur de Jong

Import python-pskc_0.5.orig.tar.gz

parent 816c2f20
This diff is collapsed.
changes from 0.4 to 0.5
-----------------------
* numerous compatibility improvements for reading PSKC files that do not
follow the RFC 6030 schema exactly: specifically accept a number of old
Internet Draft specifications that preceded RFC 6030 and support an
ActivIdentity file format
* split device information from key information (keep old API available) to
allow multiple keys per device (this is not allowed by RFC 6030 but was
allowed in older Internet Drafts)
* accept MAC to be over plaintext in addition to ciphertext
* fall back to using encryption key as MAC key
* refactoring of some encryption, parsing and serialising functionality into
separate modules for better maintainability
* add configuration for running test suite via Tox
* addition of a large number of test cases, bringing the branch coverage to
100%
* documentation improvements
* drop official support for Python 2.6 (the module still works but is just no
longer tested with it)
changes from 0.3 to 0.4
-----------------------
......
Metadata-Version: 1.1
Name: python-pskc
Version: 0.4
Version: 0.5
Summary: Python module for handling PSKC files
Home-page: http://arthurdejong.org/python-pskc/
Author: Arthur de Jong
......@@ -25,6 +25,15 @@ Description: Python module for handling PSKC files
... print('%s %s' % (key.serial, str(key.secret.decode())))
987654321 12345678901234567890
The following generates an encrypted PSKC file:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The module should be able to handle most common PSKC files.
Keywords: PSKC,RFC 6030,key container
......@@ -37,11 +46,11 @@ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or l
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
......
......@@ -19,7 +19,7 @@ API
The module provides a straightforward API that is mostly geared towards
parsing existing PSKC files.
Extracting key material from encrypted PSKC files is as simple as.
Extracting key material from encrypted PSKC files is as simple as:
>>> from pskc import PSKC
>>> pskc = PSKC('tests/rfc6030/figure7.pskcxml')
......@@ -28,6 +28,15 @@ Extracting key material from encrypted PSKC files is as simple as.
... print key.serial, key.secret
987654321 12345678901234567890
Writing am encrypted PSKC file is as simple as:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The key object has a number of properties. See the pskc.key.Key documentation
for details.
......@@ -44,7 +53,7 @@ private key material.
Copyright
---------
Copyright (C) 2014-2016 Arthur de Jong
Copyright (C) 2014-2017 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......
......@@ -46,7 +46,7 @@ master_doc = 'index'
# General information about the project.
project = u'python-pskc'
copyright = u'2014-2016 Arthur de Jong'
copyright = u'2014-2017 Arthur de Jong'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
......
......@@ -93,7 +93,7 @@ The Encryption class
.. function:: setup_preshared_key(...)
Configure pre-shared key encryption.
Configure pre-shared key encryption when writing the file.
:param binary key: the encryption key to use
:param str id: encryption key identifier
......@@ -119,7 +119,7 @@ The Encryption class
.. function:: setup_pbkdf2(...)
Configure password-based PSKC encryption.
Configure password-based PSKC encryption when writing the file.
:param str password: the password to use (required)
:param str id: encryption key identifier
......
......@@ -3,8 +3,9 @@ Basic usage
The :mod:`pskc` module implements a simple and efficient API for parsing and
creating PSKC files. The :class:`~pskc.PSKC` class is used to access the file
as a whole which provides access to a list of :class:`~pskc.key.Key`
instances which contain most of the useful information of the PSKC file.
as a whole which provides access to a list of :class:`~pskc.device.Device`
and :class:`~pskc.key.Key` instances which contain most of the useful
information of the PSKC file.
Reading a PSKC file
......@@ -89,6 +90,11 @@ The PSKC class
A unique identifier for the container.
.. attribute:: devices
A list of :class:`~pskc.device.Device` instances that represent the key
containers within the PSKC file.
.. attribute:: keys
A list of :class:`~pskc.key.Key` instances that represent the keys
......@@ -105,11 +111,18 @@ The PSKC class
See :doc:`mac` for more information.
.. function:: add_device([**kwargs])
Add a new key package to the PSKC instance. The keyword arguments may
refer to any attributes of the :class:`~pskc.device.Device` class with
which the new device is initialised.
.. function:: add_key([**kwargs])
Add a new key to the PSKC instance. The keyword arguments may refer to
any attributes of the :class:`~pskc.key.Key` class with which the new
key is initialised.
any attributes of the :class:`~pskc.key.Key` or
:class:`~pskc.device.Device` class with which the new key is
initialised.
.. function:: write(filename)
......@@ -186,7 +199,7 @@ The Key class
.. attribute:: issuer
The name of the party that issued the key. This may be different from
the :attr:`manufacturer` of the device.
the :attr:`~pskc.device.Device.manufacturer` of the device.
.. attribute:: key_profile
......@@ -208,62 +221,7 @@ The Key class
.. attribute:: key_userid
The distinguished name of the user associated with the key.
Also see :attr:`device_userid`.
.. attribute:: manufacturer
The name of the manufacturer of the device to which the key is
provisioned.
`RFC 6030 <https://tools.ietf.org/html/rfc6030#section-4.3.1>`__
prescribes that the value is of the form ``oath.prefix`` for `OATH
Manufacturer Prefixes <http://www.openauthentication.org/oath-id/prefixes/>`_
or ``iana.organisation`` for `IANA Private Enterprise Numbers
<https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers>`_
however, it is generally just a string. The value may be different from
the :attr:`issuer` of the key on the device.
.. attribute:: serial
The serial number of the device to which the key is provisioned.
Together with :attr:`manufacturer` (and possibly :attr:`issue_no`) this
should uniquely identify the device.
.. attribute:: model
A manufacturer-specific description of the model of the device.
.. attribute:: issue_no
The issue number in case there are devices with the same :attr:`serial`
number so that they can be distinguished by different issue numbers.
.. attribute:: device_binding
Reference to a device identifier (e.g. IMEI) that allows a provisioning
server to ensure that the key is going to be loaded into a specific
device.
.. attribute:: start_date
:class:`datetime.datetime` value that indicates that the device should
only be used after this date.
.. attribute:: expiry_date
:class:`datetime.datetime` value that indicates that the device should
only be used before this date. Systems should not rely upon the device
to enforce key usage date restrictions, as some devices do not have an
internal clock.
.. attribute:: device_userid
The distinguished name of the user associated with the device.
Also see :attr:`key_userid`.
.. attribute:: crypto_module
Implementation specific unique identifier of the cryptographic module
on the device to which the keys have been (or will be) provisioned.
Also see :attr:`~pskc.device.Device.device_userid`.
.. attribute:: algorithm_suite
......@@ -322,3 +280,87 @@ The Key class
This will return None if there is no MAC to be checked. It will return
True if all the MACs match. If any MAC fails a
:exc:`~pskc.exceptions.DecryptionError` exception is raised.
Apart from the above, all properties of the :class:`~pskc.device.Device`
class are also transparently available in :class:`~pskc.key.Key`
instances.
The Device class
----------------
.. module:: pskc.device
.. class:: Device()
Instances of this class provide the following attributes and functions:
.. attribute:: keys
A list of :class:`~pskc.key.Key` instances that represent the keys that
are linked to this device. Most PSKC files only allow one key per
device which is why all :class:`~pskc.device.Device` attributes are
available in :class:`~pskc.key.Key`.
.. function:: add_key([**kwargs])
Add a new key to the device. The keyword arguments may refer to
any attributes of the :class:`~pskc.key.Key` or
:class:`~pskc.device.Device` class with which the new key is
initialised.
.. attribute:: manufacturer
The name of the manufacturer of the device to which the key is
provisioned.
`RFC 6030 <https://tools.ietf.org/html/rfc6030#section-4.3.1>`__
prescribes that the value is of the form ``oath.prefix`` for `OATH
Manufacturer Prefixes <http://www.openauthentication.org/oath-id/prefixes/>`_
or ``iana.organisation`` for `IANA Private Enterprise Numbers
<https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers>`_
however, it is generally just a string.
The value may be different from the :attr:`~pskc.key.Key.issuer` of
the key on the device.
.. attribute:: serial
The serial number of the device to which the key is provisioned.
Together with :attr:`manufacturer` (and possibly :attr:`issue_no`) this
should uniquely identify the device.
.. attribute:: model
A manufacturer-specific description of the model of the device.
.. attribute:: issue_no
The issue number in case there are devices with the same :attr:`serial`
number so that they can be distinguished by different issue numbers.
.. attribute:: device_binding
Reference to a device identifier (e.g. IMEI) that allows a provisioning
server to ensure that the key is going to be loaded into a specific
device.
.. attribute:: start_date
:class:`datetime.datetime` value that indicates that the device should
only be used after this date.
.. attribute:: expiry_date
:class:`datetime.datetime` value that indicates that the device should
only be used before this date. Systems should not rely upon the device
to enforce key usage date restrictions, as some devices do not have an
internal clock.
.. attribute:: device_userid
The distinguished name of the user associated with the device.
Also see :attr:`~pskc.key.Key.key_userid`.
.. attribute:: crypto_module
Implementation specific unique identifier of the cryptographic module
on the device to which the keys have been (or will be) provisioned.
# __init__.py - main module
# coding: utf-8
#
# Copyright (C) 2014-2016 Arthur de Jong
# Copyright (C) 2014-2017 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
......@@ -37,6 +37,15 @@ The following prints all keys, decrypting using a password:
... print('%s %s' % (key.serial, str(key.secret.decode())))
987654321 12345678901234567890
The following generates an encrypted PSKC file:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The module should be able to handle most common PSKC files.
"""
......@@ -45,7 +54,7 @@ __all__ = ['PSKC', '__version__']
# the version number of the library
__version__ = '0.4'
__version__ = '0.5'
class PSKC(object):
......@@ -57,68 +66,50 @@ class PSKC(object):
id: identifier
encryption: information on used encryption (Encryption instance)
mac: information on used MAC method (MAC instance)
devices: list of devices (Device instances)
keys: list of keys (Key instances)
"""
def __init__(self, filename=None):
from pskc.encryption import Encryption
from pskc.exceptions import ParseError
from pskc.mac import MAC
self.version = None
self.id = None
self.encryption = Encryption(self)
self.mac = MAC(self)
self.keys = []
self.devices = []
if filename is not None:
from pskc.xml import parse, remove_namespaces
try:
tree = parse(filename)
except Exception:
raise ParseError('Error parsing XML')
remove_namespaces(tree)
self.parse(tree.getroot())
from pskc.parser import PSKCParser
PSKCParser.parse_file(self, filename)
else:
self.version = '1.0'
def parse(self, container):
"""Read information from the provided <KeyContainer> tree."""
from pskc.exceptions import ParseError
from pskc.key import Key
from pskc.xml import find, findall
if container.tag != 'KeyContainer':
raise ParseError('Missing KeyContainer')
# the version of the PSKC schema
self.version = container.get('Version')
if self.version != '1.0':
raise ParseError('Unsupported version %r' % self.version)
# unique identifier for the container
self.id = container.get('Id')
# handle EncryptionKey entries
self.encryption.parse(find(container, 'EncryptionKey'))
# handle MACMethod entries
self.mac.parse(find(container, 'MACMethod'))
# handle KeyPackage entries
for key_package in findall(container, 'KeyPackage'):
self.keys.append(Key(self, key_package))
def make_xml(self):
from pskc.xml import mk_elem
container = mk_elem('pskc:KeyContainer', Version=self.version,
Id=self.id)
self.encryption.make_xml(container)
self.mac.make_xml(container)
for key in self.keys:
key.make_xml(container)
return container
@property
def keys(self):
return tuple(key for device in self.devices for key in device.keys)
def add_device(self, **kwargs):
"""Create a new device instance for the PSKC file.
The device is initialised with properties from the provided keyword
arguments if any."""
from pskc.device import Device
device = Device(self)
self.devices.append(device)
# assign the kwargs as key properties
for k, v in kwargs.items():
if not hasattr(device, k):
raise AttributeError()
setattr(device, k, v)
return device
def add_key(self, **kwargs):
"""Create a new key instance for the PSKC file.
The new key is initialised with properties from the provided keyword
arguments if any."""
from pskc.key import Key
key = Key(self)
self.keys.append(key)
device = self.add_device()
key = device.add_key()
# assign the kwargs as key properties
for k, v in kwargs.items():
if not hasattr(key, k):
......@@ -128,14 +119,9 @@ class PSKC(object):
def write(self, filename):
"""Write the PSKC file to the provided file."""
from pskc.xml import tostring
from pskc.serialiser import PSKCSerialiser
if hasattr(filename, 'write'):
xml = tostring(self.make_xml())
try:
filename.write(xml)
except TypeError: # pragma: no cover (Python 3 specific)
# fall back to writing as string for Python 3
filename.write(xml.decode('utf-8'))
PSKCSerialiser.serialise_file(self, filename)
else:
with open(filename, 'wb') as output:
self.write(output)
# algorithms.py - module for handling algorithm URIs
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Utility module that handles algorthm URIs."""
# cannonical URIs of known algorithms
_algorithms = {
'tripledes-cbc': 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc',
'kw-tripledes': 'http://www.w3.org/2001/04/xmlenc#kw-tripledes',
'aes128-cbc': 'http://www.w3.org/2001/04/xmlenc#aes128-cbc',
'aes192-cbc': 'http://www.w3.org/2001/04/xmlenc#aes192-cbc',
'aes256-cbc': 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
'kw-aes128': 'http://www.w3.org/2001/04/xmlenc#kw-aes128',
'kw-aes192': 'http://www.w3.org/2001/04/xmlenc#kw-aes192',
'kw-aes256': 'http://www.w3.org/2001/04/xmlenc#kw-aes256',
'camellia128': 'http://www.w3.org/2001/04/xmldsig-more#camellia128',
'camellia192': 'http://www.w3.org/2001/04/xmldsig-more#camellia192',
'camellia256': 'http://www.w3.org/2001/04/xmldsig-more#camellia256',
'kw-camellia128': 'http://www.w3.org/2001/04/xmldsig-more#kw-camellia128',
'kw-camellia192': 'http://www.w3.org/2001/04/xmldsig-more#kw-camellia192',
'kw-camellia256': 'http://www.w3.org/2001/04/xmldsig-more#kw-camellia256',
'hmac-md5': 'http://www.w3.org/2001/04/xmldsig-more#hmac-md5',
'hmac-sha1': 'http://www.w3.org/2000/09/xmldsig#hmac-sha1',
'hmac-sha224': 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha224',
'hmac-sha256': 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256',
'hmac-sha384': 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha384',
'hmac-sha512': 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha512',
'hmac-ripemd160': 'http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160',
'pbkdf2': 'http://www.rsasecurity.com/rsalabs/pkcs/schemas/' +
'pkcs-5v2-0#pbkdf2',
}
# translation table to change old encryption names to new names
_algorithm_aliases = {
'3des-cbc': 'tripledes-cbc',
'3des112-cbc': 'tripledes-cbc',
'3des168-cbc': 'tripledes-cbc',
'kw-3des': 'kw-tripledes',
'pbe-3des112-cbc': 'tripledes-cbc',
'pbe-3des168-cbc': 'tripledes-cbc',
'pbe-aes128-cbc': 'aes128-cbc',
'pbe-aes192-cbc': 'aes192-cbc',
'pbe-aes256-cbc': 'aes256-cbc',
'rsa-1_5': 'rsa-1_5',
'rsa-oaep-mgf1p': 'rsa-oaep-mgf1p',
}
def normalise_algorithm(algorithm):
"""Return the canonical URI for the provided algorithm."""
if not algorithm or algorithm.lower() == 'none':
return None
algorithm = _algorithm_aliases.get(algorithm.lower(), algorithm)
return _algorithms.get(algorithm.rsplit('#', 1)[-1].lower(), algorithm)
# __init__.py - general crypto utility functions
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Implement crypto utility functions."""
def pad(value, block_size):
"""Pad the value to block_size length."""
padding = block_size - (len(value) % block_size)
return value + padding * chr(padding).encode('ascii')
def unpad(value, block_size):
"""Remove padding from the plaintext."""
from pskc.exceptions import DecryptionError
padding = ord(value[-1:])
# only unpad if all padding bytes are the same
if (padding > 0 and padding <= block_size and
value[-padding:] == padding * chr(padding).encode('ascii')):
return value[:-padding]
raise DecryptionError('Invalid padding')
# device.py - module for handling device info from pskc files
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Module that handles device information stored in PSKC files."""
class Device(object):
"""Representation of a single key from a PSKC file.
Instances of this class provide the following properties:
manufacturer: name of the organisation that made the device
serial: serial number of the device
model: device model description
issue_no: issue number per serial number
device_binding: device (class) identifier for the key to be loaded upon
start_date: key should not be used before this date
expiry_date: key or device may expire after this date
device_userid: user distinguished name associated with the device
crypto_module: id of module to which keys are provisioned within device
"""
def __init__(self, pskc):
self.pskc = pskc
self.manufacturer = None
self.serial = None
self.model = None
self.issue_no = None
self.device_binding = None
self.start_date = None
self.expiry_date = None
self.device_userid = None
self.crypto_module = None
self.keys = []
def add_key(self, **kwargs):
"""Create a new key instance for the device.
The new key is initialised with properties from the provided keyword
arguments if any."""
from pskc.key import Key
key = Key(self)
self.keys.append(key)
# assign the kwargs as key properties
for k, v in kwargs.items():
if not hasattr(key, k):
raise AttributeError()
setattr(key, k, v)
return key
This diff is collapsed.
This diff is collapsed.
......@@ -29,7 +29,6 @@ with the PSKC encryption key.
"""
import base64
import re
......@@ -53,6 +52,18 @@ def get_hmac(algorithm):
return lambda key, value: hmac.new(key, value, digestmod).digest()
def get_mac(algorithm, key, value):
"""Generate the MAC value over the specified value."""
from pskc.exceptions import DecryptionError
if algorithm is None:
raise DecryptionError('No MAC algorithm set')
hmacfn = get_hmac(algorithm)
if hmacfn is None:
raise DecryptionError(
'Unsupported MAC algorithm: %r' % algorithm)
return hmacfn(key, value)
class MAC(object):
"""Class describing the MAC algorithm to use and how to get the key.
......@@ -69,41 +80,6 @@ class MAC(object):
self.key_cipher_value = None
self.key_algorithm = None
def parse(self, mac_method):
"""Read MAC information from the <MACMethod> XML tree."""
from pskc.xml import find, findtext, findbin
if mac_method is None:
return
self.algorithm = mac_method.get('Algorithm')
mac_key = find(mac_method, 'MACKey')
if mac_key is not None:
self.key_cipher_value = findbin(mac_key, 'CipherData/CipherValue')
encryption_method = find(mac_key, 'EncryptionMethod')
if encryption_method is not None:
self.key_algorithm = encryption_method.attrib.get('Algorithm')
mac_key_reference = findtext(mac_method, 'MACKeyReference')
def make_xml(self, container):
from pskc.xml import mk_elem
if not self.algorithm and not self.key:
return
mac_method = mk_elem(
container, 'pskc:MACMethod', Algorithm=self.algorithm, empty=True)
mac_key = mk_elem(mac_method, 'pskc:MACKey', empty=True)
mk_elem(
mac_key, 'xenc:EncryptionMethod',
Algorithm=self.pskc.encryption.algorithm)
cipher_data = mk_elem(mac_key, 'xenc:CipherData', empty=True)
if self.key_cipher_value:
mk_elem(
cipher_data, 'xenc:CipherValue',
base64.b64encode(self.key_cipher_value).decode())
elif self.key_plain_value:
mk_elem(
cipher_data, 'xenc:CipherValue', base64.b64encode(
self.pskc.encryption.encrypt_value(self.key_plain_value)
).decode())
@property
def key(self):
"""Provides access to the MAC key binary value if available."""
......@@ -112,6 +88,8 @@ class MAC(object):
elif self.key_cipher_value:
return self.pskc.encryption.decrypt_value(
self.key_cipher_value, self.key_algorithm)
# fall back to encryption key
return self.pskc.encryption.key
@key.setter
def key(self, value):
......@@ -126,7 +104,7 @@ class MAC(object):
@algorithm.setter
def algorithm(self, value):
from pskc.encryption import normalise_algorithm
from pskc.algorithms import normalise_algorithm
self._algorithm = normalise_algorithm(value)
@property
......@@ -142,26 +120,7 @@ class MAC(object):
def generate_mac(self, value):
"""Generate the MAC over the specified value."""
from pskc.exceptions import DecryptionError
key = self.key