summaryrefslogtreecommitdiff
path: root/src/add_python/lilliput/ae_mode_2.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/add_python/lilliput/ae_mode_2.py')
-rw-r--r--src/add_python/lilliput/ae_mode_2.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py
new file mode 100644
index 0000000..79d1bcd
--- /dev/null
+++ b/src/add_python/lilliput/ae_mode_2.py
@@ -0,0 +1,127 @@
+# 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/
+
+"""Lilliput-II Authenticated Encryption mode.
+
+This module provides the functions for authenticated encryption and decryption
+using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2.
+"""
+
+from .constants import BLOCK_BYTES
+from .ae_common import (
+ bytes_to_block_matrix,
+ block_matrix_to_bytes,
+ integer_to_byte_array,
+ build_auth,
+ pad10,
+ TagValidationError,
+ xor
+)
+from . import tbc
+
+
+TWEAK_BITS = 128
+TWEAK_BYTES = TWEAK_BITS//8
+
+
+def _tweak_tag(j, padded):
+ tweak = integer_to_byte_array(j, TWEAK_BYTES)
+
+ prefix = 0b0100 if padded else 0b0000
+
+ # Clear upper 4 bits and set them to prefix.
+ tweak[-1] &= 0b00001111
+ tweak[-1] = prefix << 4
+
+ return tweak
+
+
+def _add_tag_j(tag, j):
+ array_j = integer_to_byte_array(j, TWEAK_BYTES)
+ tweak = xor(tag, array_j)
+ tweak[-1] |= 0b10000000
+
+ return tweak
+
+
+def _message_auth_tag(M, N, Auth, key):
+ l = len(M)//BLOCK_BYTES
+ need_padding = len(M)%BLOCK_BYTES > 0
+
+ tag = list(Auth)
+ M = bytes_to_block_matrix(M)
+
+ for j in range(0, l):
+ tweak = _tweak_tag(j, False)
+ encryption = tbc.encrypt(tweak, key, M[j])
+ tag = xor(tag, encryption)
+
+ if need_padding:
+ tweak = _tweak_tag(l, True)
+ encryption = tbc.encrypt(tweak, key, pad10(M[l]))
+ tag = xor(tag, encryption)
+
+ tweak = N + [0b00010000]
+ encryption = tbc.encrypt(tweak, key, tag)
+ tag = encryption
+
+ return tag
+
+
+def _message_encryption(M, N, tag, key):
+ l = len(M)//BLOCK_BYTES
+ need_padding = len(M)%BLOCK_BYTES > 0
+
+ M = bytes_to_block_matrix(M)
+ C = []
+
+ for j in range(0, l):
+ tweak = _add_tag_j(tag, j)
+ encryption = tbc.encrypt(tweak, key, N+[0b00000000])
+ C.append(xor(M[j], encryption))
+
+ if need_padding:
+ tweak = _add_tag_j(tag, l)
+ encryption = tbc.encrypt(tweak, key, N+[0b00000000])
+ C.append(xor(M[l], encryption))
+
+ return C
+
+
+def encrypt(A, M, N, key):
+ K = list(key)
+ N = list(N)
+
+ Auth = build_auth(TWEAK_BITS, A, K)
+ tag = _message_auth_tag(M, N, Auth, K)
+ C = _message_encryption(M, N, tag, K)
+
+ return block_matrix_to_bytes(C), bytes(tag)
+
+
+def decrypt(A, C, N, tag, key):
+ K = list(key)
+ N = list(N)
+ tag = list(tag)
+
+ M = block_matrix_to_bytes(
+ _message_encryption(C, N, tag, K)
+ )
+ Auth = build_auth(TWEAK_BITS, A, K)
+ tag2 = _message_auth_tag(M, N, Auth, K)
+
+ if tag != tag2:
+ raise TagValidationError(tag, tag2)
+
+ return M