/usr/lib/python3/dist-packages/pskc/mac.py is in python3-pskc 0.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # mac.py - module for checking value signatures
# coding: utf-8
#
# Copyright (C) 2014-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 provides message authentication for PSKC values.
This module provides a MAC class that is used to store information about
how the MAC should be calculated (including the MAC key) and a ValueMAC
class that provides (H)MAC checking for PSKC key data.
The MAC key is generated specifically for each PSKC file and encrypted
with the PSKC encryption key.
"""
import re
_hmac_url_re = re.compile(r'^.*#hmac-(?P<hash>[a-z0-9]+)$')
def get_hash(algorithm):
"""Return the hash function for the specifies HMAC algorithm."""
import hashlib
match = _hmac_url_re.search(algorithm)
if match:
return getattr(hashlib, match.group('hash'), None)
def get_hmac(algorithm):
"""Return an HMAC function that takes a secret and a value and returns a
digest."""
import hmac
digestmod = get_hash(algorithm)
if digestmod is not None:
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.
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):
self.pskc = pskc
self._algorithm = None
self.key_plain_value = None
self.key_cipher_value = None
self.key_algorithm = None
@property
def key(self):
"""Provides access to the MAC key binary value if available."""
if self.key_plain_value:
return self.key_plain_value
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):
self.key_plain_value = value
self.key_cipher_value = None
@property
def algorithm(self):
"""Provide the MAC algorithm used."""
if self._algorithm:
return self._algorithm
@algorithm.setter
def algorithm(self, value):
from pskc.algorithms import normalise_algorithm
self._algorithm = normalise_algorithm(value)
@property
def algorithm_key_length(self):
"""Recommended minimal key length in bytes for the set algorithm."""
# https://tools.ietf.org/html/rfc2104#section-3
# an HMAC key should be at least as long as the hash output length
hashfn = get_hash(self.algorithm)
if hashfn is not None:
return int(hashfn().digest_size)
else:
return 16
def generate_mac(self, value):
"""Generate the MAC over the specified value."""
return get_mac(self.algorithm, self.key, value)
def setup(self, key=None, algorithm=None):
"""Configure an encrypted MAC key.
The following arguments may be supplied:
key: the MAC key to use
algorithm: MAC algorithm
None of the arguments are required, reasonable defaults will be
chosen for missing arguments.
"""
if key:
self.key = key
if algorithm:
self.algorithm = algorithm
# default to HMAC-SHA1
if not self.algorithm:
self.algorithm = 'hmac-sha1'
# generate an HMAC key
if not self.key:
from Crypto import Random
self.key = Random.get_random_bytes(self.algorithm_key_length)
|