summaryrefslogtreecommitdiff
path: root/src/add_python/lilliput/ae_common.py
diff options
context:
space:
mode:
authorKévin Le Gouguec <kevin.legouguec@gmail.com>2019-03-24 15:19:15 +0100
committerKévin Le Gouguec <kevin.legouguec@gmail.com>2019-03-24 16:10:51 +0100
commit33c615feaaf148c099ee4299ad2c8a6f7e1778cf (patch)
tree4db814ee709a9ab2800e56bdac9b12cbc0cf2f26 /src/add_python/lilliput/ae_common.py
parent1b6e1eb38927633292e934ac314b10e7acc28e3d (diff)
downloadlilliput-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.py89
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