summaryrefslogtreecommitdiff
path: root/src/add_python
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
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')
-rw-r--r--src/add_python/lilliput/ae_common.py89
-rw-r--r--src/add_python/lilliput/ae_mode_1.py20
-rw-r--r--src/add_python/lilliput/ae_mode_2.py14
-rw-r--r--src/add_python/lilliput/helpers.py94
-rw-r--r--src/add_python/lilliput/tbc.py98
5 files changed, 140 insertions, 175 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
diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py
index cc550e8..efa0b6f 100644
--- a/src/add_python/lilliput/ae_mode_1.py
+++ b/src/add_python/lilliput/ae_mode_1.py
@@ -21,13 +21,13 @@ using Lilliput-AE's nonce-respecting mode based on ΘCB3.
from enum import Enum
from .constants import BLOCK_BYTES, NONCE_BYTES
-from .helpers import (
+from .ae_common import (
bytes_to_block_matrix,
block_matrix_to_bytes,
build_auth,
pad10,
TagValidationError,
- xor_state
+ xor
)
from . import tbc
@@ -92,7 +92,7 @@ def _treat_message_enc(M, N, key):
C = []
for j in range(0, l):
- checksum = xor_state(checksum, M[j])
+ checksum = xor(checksum, M[j])
tweak = _tweak_message(N, j, _MessageTweak.BLOCK)
C.append(tbc.encrypt(tweak, key, M[j]))
@@ -102,12 +102,12 @@ def _treat_message_enc(M, N, key):
else:
m_padded = pad10(M[l])
- checksum = xor_state(checksum, m_padded)
+ checksum = xor(checksum, m_padded)
tweak = _tweak_message(N, l, _MessageTweak.PAD)
pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)])
lower_part = _low_part(pad, padding_bytes*8)
- C.append(xor_state(M[l], lower_part))
+ C.append(xor(M[l], lower_part))
tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL)
Final = tbc.encrypt(tweak_final, key, checksum)
@@ -126,7 +126,7 @@ def _treat_message_dec(C, N, key):
for j in range(0, l):
tweak = _tweak_message(N, j, _MessageTweak.BLOCK)
M.append(tbc.decrypt(tweak, key, C[j]))
- checksum = xor_state(checksum, M[j])
+ checksum = xor(checksum, M[j])
if padding_bytes == 0:
tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING)
@@ -136,10 +136,10 @@ def _treat_message_dec(C, N, key):
tweak = _tweak_message(N, l, _MessageTweak.PAD)
pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)])
lower_part = _low_part(pad, padding_bytes*8)
- M.append(xor_state(C[l], lower_part))
+ M.append(xor(C[l], lower_part))
m_padded = pad10(M[l])
- checksum = xor_state(checksum, m_padded)
+ checksum = xor(checksum, m_padded)
tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL)
Final = tbc.encrypt(tweak_final, key, checksum)
@@ -151,7 +151,7 @@ def encrypt(A, M, N, key):
Auth = build_auth(TWEAK_BITS, A, K)
(Final, C) = _treat_message_enc(M, N, K)
- tag = xor_state(Auth, Final)
+ tag = xor(Auth, Final)
return block_matrix_to_bytes(C), bytes(tag)
@@ -162,7 +162,7 @@ def decrypt(A, C, N, tag, key):
Auth = build_auth(TWEAK_BITS, A, K)
(Final, M) = _treat_message_dec(C, N, K)
- tag2 = xor_state(Auth, Final)
+ tag2 = xor(Auth, Final)
if tag != tag2:
raise TagValidationError(tag, tag2)
diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py
index 4d5e499..91c53f3 100644
--- a/src/add_python/lilliput/ae_mode_2.py
+++ b/src/add_python/lilliput/ae_mode_2.py
@@ -19,13 +19,13 @@ using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2.
"""
from .constants import BLOCK_BYTES
-from .helpers import (
+from .ae_common import (
bytes_to_block_matrix,
block_matrix_to_bytes,
build_auth,
pad10,
TagValidationError,
- xor_state
+ xor
)
from . import tbc
@@ -62,7 +62,7 @@ def _add_tag_j(tag, j):
for byte in range(0, TWEAK_BYTES):
array_j[byte] = (j >> (byte * 8))
- xorr = xor_state(tag, array_j)
+ xorr = xor(tag, array_j)
xorr[TWEAK_BYTES - 1] |= 0x80
@@ -79,13 +79,13 @@ def _message_auth_tag(M, N, Auth, key):
for j in range(0, l):
tweak = _tweak_tag(j, False)
encryption = tbc.encrypt(tweak, key, M[j])
- tag = xor_state(tag, encryption)
+ tag = xor(tag, encryption)
if need_padding:
tweak = _tweak_tag(l, True)
m_padded = pad10(M[l])
encryption = tbc.encrypt(tweak, key, m_padded)
- tag = xor_state(tag, encryption)
+ tag = xor(tag, encryption)
tweak = _tweak_tag_end(N)
encryption = tbc.encrypt(tweak, key, tag)
@@ -105,13 +105,13 @@ def _message_encryption(M, N, tag, key):
tweak = _add_tag_j(tag, j)
padded_nonce = list(N) + [0x00]
encryption = tbc.encrypt(tweak, key, padded_nonce)
- C.append(xor_state(M[j], encryption))
+ C.append(xor(M[j], encryption))
if need_padding:
tweak = _add_tag_j(tag, l)
padded_nonce = list(N) + [0x00]
encryption = tbc.encrypt(tweak, key, padded_nonce)
- C.append(xor_state(M[l], encryption))
+ C.append(xor(M[l], encryption))
return C
diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py
index 65989d0..048aac7 100644
--- a/src/add_python/lilliput/helpers.py
+++ b/src/add_python/lilliput/helpers.py
@@ -1,92 +1,2 @@
-from .constants import BLOCK_BITS, BLOCK_BYTES
-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 xor_state(state1, state2):
- return [s1^s2 for (s1, s2) in zip(state1, state2)]
-
-
-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_state(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_state(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
+def xor(array1, array2):
+ return [a1^a2 for (a1, a2) in zip(array1, array2)]
diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py
index c607e45..0772853 100644
--- a/src/add_python/lilliput/tbc.py
+++ b/src/add_python/lilliput/tbc.py
@@ -18,6 +18,7 @@ This module provides functions to encrypt and decrypt blocks of 128 bits.
"""
from .constants import BLOCK_BYTES, SBOX
+from .helpers import xor
from .multiplications import ALPHAS
@@ -25,6 +26,13 @@ _PERMUTATION = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7]
_PERMUTATION_INV = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7]
+_ROUNDS = {
+ 128: 32,
+ 192: 36,
+ 256: 42
+}
+
+
def _build_tweakey(tweak, key):
return tweak+key
@@ -55,8 +63,6 @@ def _subtweakey_extract(tweakey, Ci):
def _tweakey_schedule_whole(tweakey, r):
- # Store the initial tweakey in TKs[0], and the corresponding round tweakey
- # in RTKs[0].
TKs = [tweakey]
RTKs = [_subtweakey_extract(TKs[0], 0)]
@@ -68,28 +74,21 @@ def _tweakey_schedule_whole(tweakey, r):
def _non_linear_layer(state, subtweakey):
+ variables_xored = xor(state, subtweakey)
- variables_xored = [0 for byte in range(0, 8)]
- for byte in range(0,8):
- variables_xored[byte] = state[byte] ^ subtweakey[byte]
-
- variables_sboxed = [0 for byte in range(0, 8)]
- for byte in range(0, 8):
- variables_sboxed[byte] = SBOX[variables_xored[byte]]
+ variables_sboxed = [
+ SBOX[variables_xored[i]] for i in range(8)
+ ]
- state_output = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0,BLOCK_BYTES):
- state_output[byte] = state[byte]
- for byte in range(0, 8):
- state_output[15 - byte] ^= variables_sboxed[byte]
+ state_output = state
+ for i in range(8):
+ state_output[15-i] ^= variables_sboxed[i]
return state_output
def _linear_layer(state):
- state_output = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0, BLOCK_BYTES):
- state_output[byte] = state[byte]
+ state_output = state
for byte in range(1, 8):
state_output[15] ^= state[byte]
@@ -100,26 +99,16 @@ def _linear_layer(state):
return state_output
-def _permutation_layer_enc(state):
- state_output = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0, BLOCK_BYTES):
- state_output[byte] = state[_PERMUTATION[byte]]
-
- return state_output
-
-
-def _permutation_layer_dec(state):
- state_output = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0, BLOCK_BYTES):
- state_output[byte] = state[_PERMUTATION_INV[byte]]
-
- return state_output
+def _permutation_layer(state, p):
+ return [
+ state[p[i]] for i in range(BLOCK_BYTES)
+ ]
def _one_round_egfn_enc(state, subtweakey):
state_non_linear = _non_linear_layer(state, subtweakey)
state_linear = _linear_layer(state_non_linear)
- state_permutation = _permutation_layer_enc(state_linear)
+ state_permutation = _permutation_layer(state_linear, _PERMUTATION)
return state_permutation
@@ -134,57 +123,34 @@ def _last_round_egfn(state, subtweakey):
def _one_round_egfn_dec(state, subtweakey):
state_non_linear = _non_linear_layer(state, subtweakey)
state_linear = _linear_layer(state_non_linear)
- state_permutation = _permutation_layer_dec(state_linear)
+ state_permutation = _permutation_layer(state_linear, _PERMUTATION_INV)
return state_permutation
-def _rounds(key_bytes):
- rounds = {
- 128: 32,
- 192: 36,
- 256: 42
- }
- return rounds[key_bytes*8]
-
-
def encrypt(tweak, key, message):
- r = _rounds(len(key))
+ r = _ROUNDS[8*len(key)]
tweakey = _build_tweakey(tweak, key)
RTKs = _tweakey_schedule_whole(tweakey, r)
- state = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0, BLOCK_BYTES):
- state[byte] = message[byte]
-
- for i in range(0, r-1):
- state_output = _one_round_egfn_enc(state, RTKs[i])
-
- for byte in range(0, BLOCK_BYTES):
- state[byte] = state_output[byte]
+ state = message
- state_output = _last_round_egfn(state, RTKs[r-1])
+ for i in range(r-1):
+ state = _one_round_egfn_enc(state, RTKs[i])
- return state_output
+ return _last_round_egfn(state, RTKs[r-1])
def decrypt(tweak, key, cipher):
- r = _rounds(len(key))
+ r = _ROUNDS[8*len(key)]
tweakey = _build_tweakey(tweak, key)
RTKs = _tweakey_schedule_whole(tweakey, r)
- state = [0 for byte in range(0, BLOCK_BYTES)]
- for byte in range(0, BLOCK_BYTES):
- state[byte] = cipher[byte]
-
- for i in range(0, r-1):
- state_output = _one_round_egfn_dec(state, RTKs[r-i-1])
+ state = cipher
- for byte in range(0, BLOCK_BYTES):
- state[byte] = state_output[byte]
+ for i in range(r-1):
+ state = _one_round_egfn_dec(state, RTKs[r-i-1])
- state_output = _last_round_egfn(state, RTKs[0])
-
- return state_output
+ return _last_round_egfn(state, RTKs[0])