diff options
| author | Kévin Le Gouguec <kevin.legouguec@gmail.com> | 2019-03-24 15:19:15 +0100 |
|---|---|---|
| committer | Kévin Le Gouguec <kevin.legouguec@gmail.com> | 2019-03-24 16:10:51 +0100 |
| commit | 33c615feaaf148c099ee4299ad2c8a6f7e1778cf (patch) | |
| tree | 4db814ee709a9ab2800e56bdac9b12cbc0cf2f26 /src/add_python/lilliput/ae_common.py | |
| parent | 1b6e1eb38927633292e934ac314b10e7acc28e3d (diff) | |
| download | lilliput-ae-implem-33c615feaaf148c099ee4299ad2c8a6f7e1778cf.tar.xz | |
[implem-python] Réécriture de certains range() dans tbc.py
IME, itérer sur un range() est rarement la façon la plus expressive de
faire les choses ; les alternatives imposent une structure qui rendent
l'intention plus claire. E.g. quand on voit une compréhension, on
comprend que l'auteur cherche à filtrer et/ou transformer ce sur quoi
il itère.
Réutilisation de xor_state(), renommé xor() puisqu'il sert dans
plusieurs situations.
Séparation de ce xor() et des fonctions communes aux modes
authentifiés pour éviter un import circulaire.
Diffstat (limited to 'src/add_python/lilliput/ae_common.py')
| -rw-r--r-- | src/add_python/lilliput/ae_common.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py new file mode 100644 index 0000000..f212353 --- /dev/null +++ b/src/add_python/lilliput/ae_common.py @@ -0,0 +1,89 @@ +from .constants import BLOCK_BITS, BLOCK_BYTES +from .helpers import xor +from . import tbc + + +def bytes_to_block_matrix(array): + vector = list(array) + + blocks_nb = len(vector)//BLOCK_BYTES + + block_starts = ( + i*BLOCK_BYTES for i in range(blocks_nb) + ) + + matrix = [ + vector[start:start+BLOCK_BYTES] for start in block_starts + ] + + padding_len = len(vector)%BLOCK_BYTES + + if padding_len > 0: + padding = vector[-padding_len:] + matrix.append(padding) + + return matrix + + +def block_matrix_to_bytes(matrix): + return bytes(byte for block in matrix for byte in block) + + +def pad10(X): + zeroes = [0] * (BLOCK_BYTES-len(X)-1) + return zeroes + [0b10000000] + X + + +def _tweak_associated_data(t, i, padded): + t_bytes = t//8 + tweak = [0]*(t_bytes) + + mask = 0xff + for byte in range(t_bytes-1): + tweak[byte] = (i & mask) >> (byte * 8) + mask = mask << 8 + + mask = (0xf << (8 * t_bytes-1)) + tweak[-1] = (i & mask) >> ((t_bytes-1)*8) + if not padded: + tweak[-1] |= 0x20 + else: + tweak[-1] |= 0x60 + + return tweak + + +def build_auth(t, A, key): + Auth = [0 for byte in range(0, BLOCK_BYTES)] + l_a = len(A)//BLOCK_BYTES + need_padding = len(A)%BLOCK_BYTES > 0 + + A = bytes_to_block_matrix(A) + + for i in range(0, l_a): + tweak = _tweak_associated_data(t, i, padded=False) + enc = tbc.encrypt(tweak, key, A[i]) + Auth = xor(Auth, enc) + + if not need_padding: + return Auth + + tweak = _tweak_associated_data(t, l_a, padded=True) + ad_padded = pad10(A[l_a]) + enc = tbc.encrypt(tweak, key, ad_padded) + Auth = xor(Auth, enc) + + return Auth + + +class TagValidationError(Exception): + def __init__(self, announced, computed): + msg = '\n'.join(( + 'Invalid tag:', + announced.hex().upper()+' (announced)', + computed.hex().upper()+' (computed)' + )) + + super().__init__(msg) + self._announced = announced + self._computed = computed |
