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
|
# Implementation of the Lilliput-AE tweakable block cipher.
#
# Authors, hereby denoted as "the implementer":
# Kévin Le Gouguec,
# Léo Reynaud
# 2019.
#
# For more information, feedback or questions, refer to our website:
# https://paclido.fr/lilliput-ae
#
# To the extent possible under law, the implementer has waived all copyright
# and related or neighboring rights to the source code in this file.
# http://creativecommons.org/publicdomain/zero/1.0/
"""Helper functions used in both Lilliput-I and Lilliput-II."""
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 integer_to_byte_array(i, n):
return list(i.to_bytes(n, 'little'))
def _tweak_associated_data(t, i, padded):
tweak = integer_to_byte_array(i, t//8)
prefix = 0b0110 if padded else 0b0010
# Clear upper 4 bits and set them to prefix.
tweak[-1] &= 0b00001111
tweak[-1] = prefix << 4
return tweak
def build_auth(t, A, key):
Auth = [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(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
|