ae_common.py (2453B)
1 # Implementation of the Lilliput-AE tweakable block cipher. 2 # 3 # Authors, hereby denoted as "the implementer": 4 # Kévin Le Gouguec, 5 # Léo Reynaud 6 # 2019. 7 # 8 # For more information, feedback or questions, refer to our website: 9 # https://paclido.fr/lilliput-ae 10 # 11 # To the extent possible under law, the implementer has waived all copyright 12 # and related or neighboring rights to the source code in this file. 13 # http://creativecommons.org/publicdomain/zero/1.0/ 14 15 """Helper functions used in both Lilliput-I and Lilliput-II.""" 16 17 18 from .constants import BLOCK_BYTES 19 from .helpers import xor 20 from . import tbc 21 22 23 def bytes_to_block_matrix(array): 24 vector = list(array) 25 26 blocks_nb = len(vector)//BLOCK_BYTES 27 28 block_starts = ( 29 i*BLOCK_BYTES for i in range(blocks_nb) 30 ) 31 32 matrix = [ 33 vector[start:start+BLOCK_BYTES] for start in block_starts 34 ] 35 36 padding_len = len(vector)%BLOCK_BYTES 37 38 if padding_len > 0: 39 padding = vector[-padding_len:] 40 matrix.append(padding) 41 42 return matrix 43 44 45 def block_matrix_to_bytes(matrix): 46 return bytes(byte for block in matrix for byte in block) 47 48 49 def pad10(X): 50 zeroes = [0] * (BLOCK_BYTES-len(X)-1) 51 return X + [0b10000000] + zeroes 52 53 54 def integer_to_byte_array(i, n): 55 return list(i.to_bytes(n, 'big')) 56 57 58 def _tweak_associated_data(t, i, padded): 59 tweak = integer_to_byte_array(i, t//8) 60 61 prefix = 0b0110 if padded else 0b0010 62 63 # Clear upper 4 bits and set them to prefix. 64 tweak[0] &= 0b00001111 65 tweak[0] |= prefix << 4 66 67 return tweak 68 69 70 def build_auth(t, A, key): 71 Auth = [0]*BLOCK_BYTES 72 73 l_a = len(A)//BLOCK_BYTES 74 need_padding = len(A)%BLOCK_BYTES > 0 75 76 A = bytes_to_block_matrix(A) 77 78 for i in range(l_a): 79 tweak = _tweak_associated_data(t, i, padded=False) 80 enc = tbc.encrypt(tweak, key, A[i]) 81 Auth = xor(Auth, enc) 82 83 if not need_padding: 84 return Auth 85 86 tweak = _tweak_associated_data(t, l_a, padded=True) 87 ad_padded = pad10(A[l_a]) 88 enc = tbc.encrypt(tweak, key, ad_padded) 89 Auth = xor(Auth, enc) 90 91 return Auth 92 93 94 class TagValidationError(Exception): 95 def __init__(self, announced, computed): 96 msg = '\n'.join(( 97 'Invalid tag:', 98 announced.hex().upper()+' (announced)', 99 computed.hex().upper()+' (computed)' 100 )) 101 102 super().__init__(msg) 103 self._announced = announced 104 self._computed = computed