From e83abe9fdbab07e6df80443240d4d649303a3dd4 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 22 Mar 2019 16:41:34 +0100 Subject: [implem-python] Déplacement dans le dossier SOUMISSION_NIST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et ajout d'un métascript pour vérifier la conformité. Il ne reste plus qu'à… (bis) --- src/add_python/lilliput/__init__.py | 31 +++++ src/add_python/lilliput/constants.py | 40 +++++++ src/add_python/lilliput/helpers.py | 92 ++++++++++++++ src/add_python/lilliput/lilliput_ae_1.py | 155 ++++++++++++++++++++++++ src/add_python/lilliput/lilliput_ae_2.py | 127 ++++++++++++++++++++ src/add_python/lilliput/multiplications.py | 186 +++++++++++++++++++++++++++++ src/add_python/lilliput/tbc.py | 178 +++++++++++++++++++++++++++ 7 files changed, 809 insertions(+) create mode 100644 src/add_python/lilliput/__init__.py create mode 100644 src/add_python/lilliput/constants.py create mode 100644 src/add_python/lilliput/helpers.py create mode 100644 src/add_python/lilliput/lilliput_ae_1.py create mode 100644 src/add_python/lilliput/lilliput_ae_2.py create mode 100644 src/add_python/lilliput/multiplications.py create mode 100644 src/add_python/lilliput/tbc.py (limited to 'src/add_python') diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py new file mode 100644 index 0000000..5fbc0de --- /dev/null +++ b/src/add_python/lilliput/__init__.py @@ -0,0 +1,31 @@ +from . import lilliput_ae_1 +from . import lilliput_ae_2 +from .constants import NONCE_BYTES + + +_AE_MODES = { + 1: lilliput_ae_1, + 2: lilliput_ae_2 +} + + +def _check_inputs(key, mode, nonce): + valid_key_lengths = (128, 192, 256) + if len(key)*8 not in valid_key_lengths: + raise ValueError('invalid key size: {} not in {}'.format(len(key)*8, valid_key_lengths)) + + if mode not in _AE_MODES: + raise ValueError('invalid mode: {} not in {}'.format(mode, tuple(_AE_MODES))) + + if len(nonce) != NONCE_BYTES: + raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BYTES, len(nonce))) + + +def encrypt(plaintext, adata, key, nonce, mode): + _check_inputs(key, mode, nonce) + return _AE_MODES[mode].encrypt(adata, plaintext, nonce, key) + + +def decrypt(ciphertext, tag, adata, key, nonce, mode): + _check_inputs(key, mode, nonce) + return _AE_MODES[mode].decrypt(adata, ciphertext, nonce, tag, key) diff --git a/src/add_python/lilliput/constants.py b/src/add_python/lilliput/constants.py new file mode 100644 index 0000000..0c9b89f --- /dev/null +++ b/src/add_python/lilliput/constants.py @@ -0,0 +1,40 @@ +BLOCK_BITS = 128 +BLOCK_BYTES = BLOCK_BITS//8 +NONCE_BYTES = 15 +TAG_BYTES = 16 + + +Sbox = [ + 0x20, 0x00, 0xb2, 0x85, 0x3b, 0x35, 0xa6, 0xa4, + 0x30, 0xe4, 0x6a, 0x2c, 0xff, 0x59, 0xe2, 0x0e, + 0xf8, 0x1e, 0x7a, 0x80, 0x15, 0xbd, 0x3e, 0xb1, + 0xe8, 0xf3, 0xa2, 0xc2, 0xda, 0x51, 0x2a, 0x10, + 0x21, 0x01, 0x23, 0x78, 0x5c, 0x24, 0x27, 0xb5, + 0x37, 0xc7, 0x2b, 0x1f, 0xae, 0x0a, 0x77, 0x5f, + 0x6f, 0x09, 0x9d, 0x81, 0x04, 0x5a, 0x29, 0xdc, + 0x39, 0x9c, 0x05, 0x57, 0x97, 0x74, 0x79, 0x17, + 0x44, 0xc6, 0xe6, 0xe9, 0xdd, 0x41, 0xf2, 0x8a, + 0x54, 0xca, 0x6e, 0x4a, 0xe1, 0xad, 0xb6, 0x88, + 0x1c, 0x98, 0x7e, 0xce, 0x63, 0x49, 0x3a, 0x5d, + 0x0c, 0xef, 0xf6, 0x34, 0x56, 0x25, 0x2e, 0xd6, + 0x67, 0x75, 0x55, 0x76, 0xb8, 0xd2, 0x61, 0xd9, + 0x71, 0x8b, 0xcd, 0x0b, 0x72, 0x6c, 0x31, 0x4b, + 0x69, 0xfd, 0x7b, 0x6d, 0x60, 0x3c, 0x2f, 0x62, + 0x3f, 0x22, 0x73, 0x13, 0xc9, 0x82, 0x7f, 0x53, + 0x32, 0x12, 0xa0, 0x7c, 0x02, 0x87, 0x84, 0x86, + 0x93, 0x4e, 0x68, 0x46, 0x8d, 0xc3, 0xdb, 0xec, + 0x9b, 0xb7, 0x89, 0x92, 0xa7, 0xbe, 0x3d, 0xd8, + 0xea, 0x50, 0x91, 0xf1, 0x33, 0x38, 0xe0, 0xa9, + 0xa3, 0x83, 0xa1, 0x1b, 0xcf, 0x06, 0x95, 0x07, + 0x9e, 0xed, 0xb9, 0xf5, 0x4c, 0xc0, 0xf4, 0x2d, + 0x16, 0xfa, 0xb4, 0x03, 0x26, 0xb3, 0x90, 0x4f, + 0xab, 0x65, 0xfc, 0xfe, 0x14, 0xf7, 0xe3, 0x94, + 0xee, 0xac, 0x8c, 0x1a, 0xde, 0xcb, 0x28, 0x40, + 0x7d, 0xc8, 0xc4, 0x48, 0x6b, 0xdf, 0xa5, 0x52, + 0xe5, 0xfb, 0xd7, 0x64, 0xf9, 0xf0, 0xd3, 0x5e, + 0x66, 0x96, 0x8f, 0x1d, 0x45, 0x36, 0xcc, 0xc5, + 0x4d, 0x9f, 0xbf, 0x0f, 0xd1, 0x08, 0xeb, 0x43, + 0x42, 0x19, 0xe7, 0x99, 0xa8, 0x8e, 0x58, 0xc1, + 0x9a, 0xd4, 0x18, 0x47, 0xaa, 0xaf, 0xbc, 0x5b, + 0xd5, 0x11, 0xd0, 0xb0, 0x70, 0xbb, 0x0d, 0xba +] diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py new file mode 100644 index 0000000..8677f06 --- /dev/null +++ b/src/add_python/lilliput/helpers.py @@ -0,0 +1,92 @@ +from .constants import BLOCK_BITS, BLOCK_BYTES +from . import tbc + + +def ArrayToBlockbytesMatrix(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 BlockbytesMatrixToBytes(matrix): + return bytes(byte for block in matrix for byte in block) + + +def XorState(state1, state2): + return [s1^s2 for (s1, s2) in zip(state1, state2)] + + +def Padding10LSB(X): + zeroes = [0] * (BLOCK_BYTES-len(X)-1) + return zeroes + [0b10000000] + X + + +def _tweakAssociatedData(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 BuildAuth(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 = ArrayToBlockbytesMatrix(A) + + for i in range(0, l_a): + tweak = _tweakAssociatedData(t, i, padded=False) + enc = tbc.encrypt(tweak, key, A[i]) + Auth = XorState(Auth, enc) + + if not need_padding: + return Auth + + tweak = _tweakAssociatedData(t, l_a, padded=True) + ad_padded = Padding10LSB(A[l_a]) + enc = tbc.encrypt(tweak, key, ad_padded) + Auth = XorState(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/lilliput_ae_1.py b/src/add_python/lilliput/lilliput_ae_1.py new file mode 100644 index 0000000..0da2a95 --- /dev/null +++ b/src/add_python/lilliput/lilliput_ae_1.py @@ -0,0 +1,155 @@ +""" + OCB 3 for lilliput ae i +""" + +from enum import Enum + +from .constants import BLOCK_BYTES, NONCE_BYTES +from .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 192 +TWEAK_BYTES = TWEAK_BITS//8 + + +def LowPart(array, number_bits): + shifted = 0 + for byte in range(0, len(array)): + shifted |= (array[byte] << (8 * byte)) + + mask = 0 + for bit in range(0, number_bits): + mask |= (0x1 << bit) + + lower_part = shifted & mask + + will_pad = 0 + if number_bits % 8 != 0: + will_pad = 1 + + lower_part_byte = [] + nb_bytes = number_bits//8 + will_pad + for byte in range(nb_bytes): + lower_part_byte.append(lower_part & 0xff) + lower_part = lower_part >> 8 + + return lower_part_byte + + +class _MessageTweak(Enum): + BLOCK = 0b000 + NO_PADDING = 0b0001 + PAD = 0b0100 + FINAL = 0b0101 + + +def TweakMessage(N, j, padding): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(NONCE_BYTES-1, -1, -1): + tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 + tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 + + tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) + for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + tweak[-1] |= padding.value<<4 + + return tweak + + +def TreatMessageEnc(M, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + checksum = XorState(checksum, M[j]) + tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + C.append(tbc.encrypt(tweak, key, M[j])) + + if padding_bytes == 0: + tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak = TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + + lower_part = LowPart(pad, padding_bytes*8) + C.append(XorState(M[l], lower_part)) + tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, C) + + +def TreatMessageDec(C, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(C)//BLOCK_BYTES + padding_bytes = len(C)%BLOCK_BYTES + + C = ArrayToBlockbytesMatrix(C) + M = [] + + for j in range(0, l): + tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + M.append(tbc.decrypt(tweak, key, C[j])) + checksum = XorState(checksum, M[j]) + + if padding_bytes == 0: + tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + tweak = TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + lower_part = LowPart(pad, padding_bytes*8) + M.append(XorState(C[l], lower_part)) + + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, M) + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, C) = TreatMessageEnc(M, N, K) + tag = XorState(Auth, Final) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, M) = TreatMessageDec(C, N, K) + tag2 = XorState(Auth, Final) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return BlockbytesMatrixToBytes(M) diff --git a/src/add_python/lilliput/lilliput_ae_2.py b/src/add_python/lilliput/lilliput_ae_2.py new file mode 100644 index 0000000..61aa86e --- /dev/null +++ b/src/add_python/lilliput/lilliput_ae_2.py @@ -0,0 +1,127 @@ +""" + SCT 2 for lilliput ae 2 +""" + +from .constants import BLOCK_BYTES +from .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 128 +TWEAK_BYTES = TWEAK_BITS//8 + + +def TweakTag(j, padded): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) + for byte in range(TWEAK_BYTES - 2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + if padded: + tweak[TWEAK_BYTES - 1] |= 0x40 + + return tweak + + +def TweakTagEnd(N): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + for byte in range(0, TWEAK_BYTES - 1): + tweak[byte] = N[byte] + tweak[TWEAK_BYTES - 1] = 0x10 + + return tweak + + +def AddTagJ(tag, j): + array_j = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(0, TWEAK_BYTES): + array_j[byte] = (j >> (byte * 8)) + + xorr = XorState(tag, array_j) + + xorr[TWEAK_BYTES - 1] |= 0x80 + + return xorr + + +def MesssageAuthTag(M, N, Auth, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + tag = list(Auth) + M = ArrayToBlockbytesMatrix(M) + + for j in range(0, l): + tweak = TweakTag(j, False) + encryption = tbc.encrypt(tweak, key, M[j]) + tag = XorState(tag, encryption) + + if need_padding: + tweak = TweakTag(l, True) + m_padded = Padding10LSB(M[l]) + encryption = tbc.encrypt(tweak, key, m_padded) + tag = XorState(tag, encryption) + + tweak = TweakTagEnd(N) + encryption = tbc.encrypt(tweak, key, tag) + tag = encryption + + return tag + + +def MessageEncryption(M, N, tag, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + tweak = AddTagJ(tag, j) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[j], encryption)) + + if need_padding: + tweak = AddTagJ(tag, l) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[l], encryption)) + + return C + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + tag = MesssageAuthTag(M, N, Auth, K) + C = MessageEncryption(M, N, tag, K) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + M = BlockbytesMatrixToBytes( + MessageEncryption(C, N, tag, K) + ) + Auth = BuildAuth(TWEAK_BITS, A, K) + tag2 = MesssageAuthTag(M, N, Auth, K) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return M diff --git a/src/add_python/lilliput/multiplications.py b/src/add_python/lilliput/multiplications.py new file mode 100644 index 0000000..c5f1e44 --- /dev/null +++ b/src/add_python/lilliput/multiplications.py @@ -0,0 +1,186 @@ + +# Multiply by matrix M +def _multiplyM(lane): + multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)] + + multiplied_lane[2] ^= ((lane[6] << 2) & 0xff) + multiplied_lane[4] ^= ((lane[4] >> 3) & 0xff) + multiplied_lane[5] ^= ((lane[5] << 3) & 0xff) + + return multiplied_lane + +def _multiplyM2(lane): + multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)] + + multiplied_lane[2] ^= ((lane[5] << 2) & 0xff) + multiplied_lane[3] ^= ((lane[6] << 2) & 0xff) + multiplied_lane[4] ^= ((lane[3] >> 3) & 0xff) ^ ((lane[4] >> 6) & 0xff) + multiplied_lane[5] ^= ((lane[5] << 6) & 0xff) + multiplied_lane[6] ^= ((lane[5] << 3) & 0xff) + + # binary matrix M1 + multi_mat_l4_m1 = 0 + l4 = lane[4] + multi_mat_l4_m1 ^= ((l4 & 0x8) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x10) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x20) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x40) >> 3) ^ ((l4 & 0x1) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x80) >> 3) ^ ((l4 & 0x2) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x04) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x08) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x10) << 3) + + multiplied_lane[5] ^= multi_mat_l4_m1 + + return multiplied_lane + + +def _multiplyM3(lane): + multiplied_lane = [lane[(byte-3) % 8] for byte in range(0, 8)] + + multiplied_lane[2] ^= ((lane[4] << 2) & 0xff) ^ ((lane[5] << 5) & 0xff) + multiplied_lane[3] ^= ((lane[5] << 2) & 0xff) + multiplied_lane[4] ^= ((lane[2] >> 3) & 0xff) ^ ((lane[3] >> 6) & 0xff) ^ ((lane[6] << 2) & 0xff) + multiplied_lane[6] ^= ((lane[5] << 6) & 0xff) + multiplied_lane[7] ^= ((lane[5] << 3) & 0xff) + + # binary matrix M1 + multi_mat_l3_m1 = 0 + l3 = lane[3] + multi_mat_l3_m1 ^= ((l3 & 0x8) >> 3) + multi_mat_l3_m1 ^= ((l3 & 0x10) >> 3) + multi_mat_l3_m1 ^= ((l3 & 0x20) >> 3) + multi_mat_l3_m1 ^= ((l3 & 0x40) >> 3) ^ ((l3 & 0x1) << 3) + multi_mat_l3_m1 ^= ((l3 & 0x80) >> 3) ^ ((l3 & 0x2) << 3) + multi_mat_l3_m1 ^= ((l3 & 0x04) << 3) + multi_mat_l3_m1 ^= ((l3 & 0x08) << 3) + multi_mat_l3_m1 ^= ((l3 & 0x10) << 3) + + # binary matrix M1 + multi_mat_l4_m1 = 0 + l4 = lane[4] + multi_mat_l4_m1 ^= ((l4 & 0x8) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x10) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x20) >> 3) + multi_mat_l4_m1 ^= ((l4 & 0x40) >> 3) ^ ((l4 & 0x1) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x80) >> 3) ^ ((l4 & 0x2) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x04) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x08) << 3) + multi_mat_l4_m1 ^= ((l4 & 0x10) << 3) + + # binary matrix M2 + multi_mat_l4_m2 = 0 + l4 = lane[4] + multi_mat_l4_m2 ^= ((l4 & 0x40) >> 6) + multi_mat_l4_m2 ^= ((l4 & 0x80) >> 6) + multi_mat_l4_m2 ^= (l4 & 0x08) + multi_mat_l4_m2 ^= (l4 & 0x10) + multi_mat_l4_m2 ^= (l4 & 0x20) + multi_mat_l4_m2 ^= (l4 & 0x40) ^ ((l4 & 0x1) << 6) + multi_mat_l4_m2 ^= (l4 & 0x80) ^ ((l4 & 0x2) << 6) + + + multiplied_lane[5] ^= multi_mat_l3_m1 ^ multi_mat_l4_m2 + multiplied_lane[6] ^= multi_mat_l4_m1 + + return multiplied_lane + + +def _multiplyMR(lane): + multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)] + + multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff) + multiplied_lane[4] ^= ((lane[6] << 3) & 0xff) + multiplied_lane[5] ^= ((lane[3] << 2) & 0xff) + + return multiplied_lane + + +def _multiplyMR2(lane): + multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)] + + multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff) + multiplied_lane[2] ^= ((lane[5] >> 3) & 0xff) + multiplied_lane[3] ^= ((lane[6] << 3) & 0xff) + multiplied_lane[4] ^= ((lane[3] << 2) & 0xff) ^ ((lane[7] << 3) & 0xff) + multiplied_lane[5] ^= ((lane[4] << 2) & 0xff) + + + # binary matrix m3 + multi_mat_l6_m3 = 0 + l6 = lane[6] + multi_mat_l6_m3 ^= (l6 & 0x1) + multi_mat_l6_m3 ^= (l6 & 0x2) + multi_mat_l6_m3 ^= (l6 & 0x4) + multi_mat_l6_m3 ^= (l6 & 0x8) + multi_mat_l6_m3 ^= (l6 & 0x10) + + + multiplied_lane[2] ^= multi_mat_l6_m3 + + return multiplied_lane + +def _multiplyMR3(lane): + multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)] + + multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff) + multiplied_lane[1] ^= ((lane[5] >> 3) & 0xff) + multiplied_lane[3] ^= ((lane[3] << 2) & 0xff) ^ ((lane[7] << 3) & 0xff) + multiplied_lane[4] ^= ((lane[0] << 3) & 0xff) ^ ((lane[4] << 2) & 0xff) + multiplied_lane[5] ^= ((lane[5] << 2) & 0xff) ^ ((lane[6] << 5) & 0xff) + + # binary matrix m3 + multi_mat_l6_m3 = 0 + l6 = lane[6] + multi_mat_l6_m3 ^= (l6 & 0x1) + multi_mat_l6_m3 ^= (l6 & 0x2) + multi_mat_l6_m3 ^= (l6 & 0x4) + multi_mat_l6_m3 ^= (l6 & 0x8) + multi_mat_l6_m3 ^= (l6 & 0x10) + + # binary matrix m3 + multi_mat_l7_m3 = 0 + l7 = lane[7] + multi_mat_l7_m3 ^= (l7 & 0x1) + multi_mat_l7_m3 ^= (l7 & 0x2) + multi_mat_l7_m3 ^= (l7 & 0x4) + multi_mat_l7_m3 ^= (l7 & 0x8) + multi_mat_l7_m3 ^= (l7 & 0x10) + + # binary matrix m4 + multi_mat_l3_m4 = 0 + l3 = lane[3] + multi_mat_l3_m4 ^= ((l3 & 0x2) >> 1) + multi_mat_l3_m4 ^= ((l3 & 0x4) >> 1) + multi_mat_l3_m4 ^= ((l3 & 0x8) >> 1) + multi_mat_l3_m4 ^= ((l3 & 0x10) >> 1) + multi_mat_l3_m4 ^= ((l3 & 0x20) >> 1) + + # binary matrix m1 for MR + multi_mat_l6_m1 = 0 + l6 = lane[6] + multi_mat_l6_m1 ^= ((l6 & 0x8) >> 3) + multi_mat_l6_m1 ^= ((l6 & 0x10) >> 3) + multi_mat_l6_m1 ^= ((l6 & 0x20) >> 3) + multi_mat_l6_m1 ^= ((l6 & 0x40) >> 3) ^ ((l6 & 0x1) << 3) + multi_mat_l6_m1 ^= ((l6 & 0x80) >> 3) ^ ((l6 & 0x2) << 3) + multi_mat_l6_m1 ^= ((l6 & 0x4) << 3) + multi_mat_l6_m1 ^= ((l6 & 0x8) << 3) + multi_mat_l6_m1 ^= ((l6 & 0x10) << 3) + + + multiplied_lane[1] ^= multi_mat_l6_m3 + multiplied_lane[2] ^= multi_mat_l3_m4 ^ multi_mat_l6_m1 ^ multi_mat_l7_m3 + + return multiplied_lane + + +ALPHAS = ( + list, # Identity. + _multiplyM, + _multiplyM2, + _multiplyM3, + _multiplyMR, + _multiplyMR2, + _multiplyMR3 +) diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py new file mode 100644 index 0000000..5291994 --- /dev/null +++ b/src/add_python/lilliput/tbc.py @@ -0,0 +1,178 @@ +""" + Lilliput TBC +""" +from .constants import BLOCK_BYTES, Sbox +from .multiplications import ALPHAS + + +permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] +permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] + +################################################################################ + +def BuildTweakey(tweak, key): + return tweak+key + +############################# + +def _lane(TK, j): + return TK[j*8:(j+1)*8] + +def RoundTweakeySchedule(tweakey): + p = len(tweakey)//8 + + multiplied_lanes = ( + ALPHAS[j](_lane(tweakey, j)) for j in range(p) + ) + + return [byte for lane in multiplied_lanes for byte in lane] + + +def SubTweakeyExtract(tweakey, Ci): + RTKi = [0]*8 + + for j, byte in enumerate(tweakey): + RTKi[j%8] ^= byte + + RTKi[0] ^= Ci + + return RTKi + + +def TweakeyScheduleWhole(tweakey, r): + # store main tweakey in TKs[0] + # and corresponding round tweakey in RTKs[0] + TKs = [tweakey] + RTKs = [SubTweakeyExtract(TKs[0], 0)] + + for i in range(1, r): + TKs.append(RoundTweakeySchedule(TKs[i-1])) + RTKs.append(SubTweakeyExtract(TKs[i], i)) + + return RTKs + + +################################################################################ + +def NonLinearLayer(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]] + + 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] + + return state_output + + +def LinearLayer(state): + 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(1, 8): + state_output[15] ^= state[byte] + + for byte in range(9, 15): + state_output[byte] ^= state[7] + + return state_output + + +def PermutationLayerEnc(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 PermutationLayerDec(state): + state_output = [0 for byte in range(0, BLOCK_BYTES)] + for byte in range(0, BLOCK_BYTES): + state_output[byte] = state[permutationInv[byte]] + + return state_output + + +def OneRoundEGFNEnc(state, subtweakey): + state_non_linear = NonLinearLayer(state, subtweakey) + state_linear = LinearLayer(state_non_linear) + state_permutation = PermutationLayerEnc(state_linear) + + return state_permutation + +def LastRoundEGFN(state, subtweakey): + state_non_linear = NonLinearLayer(state, subtweakey) + state_linear = LinearLayer(state_non_linear) + + return state_linear + + +def OneRoundEGFNDec(state, subtweakey): + state_non_linear = NonLinearLayer(state, subtweakey) + state_linear = LinearLayer(state_non_linear) + state_permutation = PermutationLayerDec(state_linear) + + return state_permutation + + +def _rounds(key_bytes): + rounds = { + 128: 32, + 192: 36, + 256: 42 + } + return rounds[key_bytes*8] + + +################################################################################ +# Lilliput TBC + +def encrypt(tweak, key, message): + r = _rounds(len(key)) + + tweakey = BuildTweakey(tweak, key) + RTKs = TweakeyScheduleWhole(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 = OneRoundEGFNEnc(state, RTKs[i]) + + for byte in range(0, BLOCK_BYTES): + state[byte] = state_output[byte] + + state_output = LastRoundEGFN(state, RTKs[r-1]) + + return state_output + + +def decrypt(tweak, key, cipher): + r = _rounds(len(key)) + + tweakey = BuildTweakey(tweak, key) + RTKs = TweakeyScheduleWhole(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 = OneRoundEGFNDec(state, RTKs[r-i-1]) + + for byte in range(0, BLOCK_BYTES): + state[byte] = state_output[byte] + + state_output = LastRoundEGFN(state, RTKs[0]) + + return state_output -- cgit v1.2.3 From d1bc581b1923537e7410254d91890565f08d50ca Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 20:04:22 +0100 Subject: [implem-python] Documentation du paquet "lilliput" --- src/add_python/lilliput/__init__.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index 5fbc0de..b1bad58 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -1,3 +1,29 @@ +# 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-AE tweakable block cipher. + +This module provides the high-level functions for authenticated encryption and +decryption. Both functions take and return bytestring values. + +The "mode" argument can be either of the following integers: + +- 1, for the ΘCB3 nonce-respecting mode, +- 2, for the SCT-2 nonce-misuse-resistant mode. +""" + + from . import lilliput_ae_1 from . import lilliput_ae_2 from .constants import NONCE_BYTES -- cgit v1.2.3 From 01957e0fa098071e10b074dfe477fcc7d687bb99 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 23:32:04 +0100 Subject: [implem-python] Documentation du mode authentifié Lilliput-Ⅱ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout d'un souligné devant les fonctions privées ; de cette façon, >>> from lilliput import lilliput_ae_1 >>> help(lilliput_ae_1) … ne montre que les fonctions "publiques", i.e. celles que l'utilisateur est censé appeler. --- src/add_python/lilliput/lilliput_ae_2.py | 48 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/lilliput_ae_2.py b/src/add_python/lilliput/lilliput_ae_2.py index 61aa86e..fb6feff 100644 --- a/src/add_python/lilliput/lilliput_ae_2.py +++ b/src/add_python/lilliput/lilliput_ae_2.py @@ -1,5 +1,21 @@ -""" - SCT 2 for lilliput ae 2 +# 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 @@ -18,7 +34,7 @@ TWEAK_BITS = 128 TWEAK_BYTES = TWEAK_BITS//8 -def TweakTag(j, padded): +def _TweakTag(j, padded): tweak = [0 for byte in range(0, TWEAK_BYTES)] tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) @@ -31,7 +47,7 @@ def TweakTag(j, padded): return tweak -def TweakTagEnd(N): +def _TweakTagEnd(N): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES - 1): @@ -41,7 +57,7 @@ def TweakTagEnd(N): return tweak -def AddTagJ(tag, j): +def _AddTagJ(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) @@ -53,7 +69,7 @@ def AddTagJ(tag, j): return xorr -def MesssageAuthTag(M, N, Auth, key): +def _MesssageAuthTag(M, N, Auth, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 @@ -61,24 +77,24 @@ def MesssageAuthTag(M, N, Auth, key): M = ArrayToBlockbytesMatrix(M) for j in range(0, l): - tweak = TweakTag(j, False) + tweak = _TweakTag(j, False) encryption = tbc.encrypt(tweak, key, M[j]) tag = XorState(tag, encryption) if need_padding: - tweak = TweakTag(l, True) + tweak = _TweakTag(l, True) m_padded = Padding10LSB(M[l]) encryption = tbc.encrypt(tweak, key, m_padded) tag = XorState(tag, encryption) - tweak = TweakTagEnd(N) + tweak = _TweakTagEnd(N) encryption = tbc.encrypt(tweak, key, tag) tag = encryption return tag -def MessageEncryption(M, N, tag, key): +def _MessageEncryption(M, N, tag, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 @@ -86,13 +102,13 @@ def MessageEncryption(M, N, tag, key): C = [] for j in range(0, l): - tweak = AddTagJ(tag, j) + tweak = _AddTagJ(tag, j) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(XorState(M[j], encryption)) if need_padding: - tweak = AddTagJ(tag, l) + tweak = _AddTagJ(tag, l) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(XorState(M[l], encryption)) @@ -105,8 +121,8 @@ def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) - tag = MesssageAuthTag(M, N, Auth, K) - C = MessageEncryption(M, N, tag, K) + tag = _MesssageAuthTag(M, N, Auth, K) + C = _MessageEncryption(M, N, tag, K) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -116,10 +132,10 @@ def decrypt(A, C, N, tag, key): tag = list(tag) M = BlockbytesMatrixToBytes( - MessageEncryption(C, N, tag, K) + _MessageEncryption(C, N, tag, K) ) Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = MesssageAuthTag(M, N, Auth, K) + tag2 = _MesssageAuthTag(M, N, Auth, K) if tag != tag2: raise TagValidationError(tag, tag2) -- cgit v1.2.3 From b46dd7acc86295d3072945f4a8098649d87504a2 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 23:54:35 +0100 Subject: [implem-python] Documentation de Lilliput-Ⅰ et Lilliput-TBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Idem, renommage des fonctions privées avec un souligné pour que l'API soit plus simple à comprendre. ⚠ Pas testé, ça prend littéralement 20 minutes à l'implémentation Python de générer les vecteurs de test, et c'est l'heure du dodo… --- src/add_python/lilliput/lilliput_ae_1.py | 52 +++++++++------ src/add_python/lilliput/tbc.py | 105 ++++++++++++++++++------------- 2 files changed, 95 insertions(+), 62 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/lilliput_ae_1.py b/src/add_python/lilliput/lilliput_ae_1.py index 0da2a95..1429002 100644 --- a/src/add_python/lilliput/lilliput_ae_1.py +++ b/src/add_python/lilliput/lilliput_ae_1.py @@ -1,5 +1,21 @@ -""" - OCB 3 for lilliput ae i +# 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-I Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. """ from enum import Enum @@ -20,7 +36,7 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def LowPart(array, number_bits): +def _LowPart(array, number_bits): shifted = 0 for byte in range(0, len(array)): shifted |= (array[byte] << (8 * byte)) @@ -51,7 +67,7 @@ class _MessageTweak(Enum): FINAL = 0b0101 -def TweakMessage(N, j, padding): +def _TweakMessage(N, j, padding): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(NONCE_BYTES-1, -1, -1): tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 @@ -66,7 +82,7 @@ def TweakMessage(N, j, padding): return tweak -def TreatMessageEnc(M, N, key): +def _TreatMessageEnc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(M)//BLOCK_BYTES @@ -77,28 +93,28 @@ def TreatMessageEnc(M, N, key): for j in range(0, l): checksum = XorState(checksum, M[j]) - tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) C.append(tbc.encrypt(tweak, key, M[j])) if padding_bytes == 0: - tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) - tweak = TweakMessage(N, l, _MessageTweak.PAD) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, padding_bytes*8) + lower_part = _LowPart(pad, padding_bytes*8) C.append(XorState(M[l], lower_part)) - tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, C) -def TreatMessageDec(C, N, key): +def _TreatMessageDec(C, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(C)//BLOCK_BYTES @@ -108,23 +124,23 @@ def TreatMessageDec(C, N, key): M = [] for j in range(0, l): - tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) M.append(tbc.decrypt(tweak, key, C[j])) checksum = XorState(checksum, M[j]) if padding_bytes == 0: - tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - tweak = TweakMessage(N, l, _MessageTweak.PAD) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, padding_bytes*8) + lower_part = _LowPart(pad, padding_bytes*8) M.append(XorState(C[l], lower_part)) m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) - tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, M) @@ -135,7 +151,7 @@ def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = TreatMessageEnc(M, N, K) + (Final, C) = _TreatMessageEnc(M, N, K) tag = XorState(Auth, Final) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -146,7 +162,7 @@ def decrypt(A, C, N, tag, key): tag = list(tag) Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = TreatMessageDec(C, N, K) + (Final, M) = _TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) if tag != tag2: diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py index 5291994..50f9e2f 100644 --- a/src/add_python/lilliput/tbc.py +++ b/src/add_python/lilliput/tbc.py @@ -1,34 +1,51 @@ +# 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-TBC tweakable block cipher. + +This module provides functions to encrypt and decrypt blocks of 128 bits. """ - Lilliput TBC -""" + from .constants import BLOCK_BYTES, Sbox from .multiplications import ALPHAS -permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] -permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] +_permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] +_permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] ################################################################################ -def BuildTweakey(tweak, key): +def _BuildTweakey(tweak, key): return tweak+key ############################# -def _lane(TK, j): +def _Lane(TK, j): return TK[j*8:(j+1)*8] -def RoundTweakeySchedule(tweakey): + +def _RoundTweakeySchedule(tweakey): p = len(tweakey)//8 multiplied_lanes = ( - ALPHAS[j](_lane(tweakey, j)) for j in range(p) + ALPHAS[j](_Lane(tweakey, j)) for j in range(p) ) return [byte for lane in multiplied_lanes for byte in lane] -def SubTweakeyExtract(tweakey, Ci): +def _SubTweakeyExtract(tweakey, Ci): RTKi = [0]*8 for j, byte in enumerate(tweakey): @@ -39,22 +56,22 @@ def SubTweakeyExtract(tweakey, Ci): return RTKi -def TweakeyScheduleWhole(tweakey, r): - # store main tweakey in TKs[0] - # and corresponding round tweakey in RTKs[0] +def _TweakeyScheduleWhole(tweakey, r): + # Store the initial tweakey in TKs[0], and the corresponding round tweakey + # in RTKs[0]. TKs = [tweakey] - RTKs = [SubTweakeyExtract(TKs[0], 0)] + RTKs = [_SubTweakeyExtract(TKs[0], 0)] for i in range(1, r): - TKs.append(RoundTweakeySchedule(TKs[i-1])) - RTKs.append(SubTweakeyExtract(TKs[i], i)) + TKs.append(_RoundTweakeySchedule(TKs[i-1])) + RTKs.append(_SubTweakeyExtract(TKs[i], i)) return RTKs ################################################################################ -def NonLinearLayer(state, subtweakey): +def _NonLinearLayer(state, subtweakey): variables_xored = [0 for byte in range(0, 8)] for byte in range(0,8): @@ -73,7 +90,7 @@ def NonLinearLayer(state, subtweakey): return state_output -def LinearLayer(state): +def _LinearLayer(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state_output[byte] = state[byte] @@ -87,44 +104,44 @@ def LinearLayer(state): return state_output -def PermutationLayerEnc(state): +def _PermutationLayerEnc(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[permutation[byte]] + state_output[byte] = state[_permutation[byte]] return state_output -def PermutationLayerDec(state): +def _PermutationLayerDec(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[permutationInv[byte]] + state_output[byte] = state[_permutationInv[byte]] return state_output -def OneRoundEGFNEnc(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) - state_permutation = PermutationLayerEnc(state_linear) +def _OneRoundEGFNEnc(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) + state_permutation = _PermutationLayerEnc(state_linear) return state_permutation -def LastRoundEGFN(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) +def _LastRoundEGFN(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) return state_linear -def OneRoundEGFNDec(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) - state_permutation = PermutationLayerDec(state_linear) +def _OneRoundEGFNDec(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) + state_permutation = _PermutationLayerDec(state_linear) return state_permutation -def _rounds(key_bytes): +def _Rounds(key_bytes): rounds = { 128: 32, 192: 36, @@ -134,45 +151,45 @@ def _rounds(key_bytes): ################################################################################ -# Lilliput TBC + def encrypt(tweak, key, message): - r = _rounds(len(key)) + r = _Rounds(len(key)) - tweakey = BuildTweakey(tweak, key) - RTKs = TweakeyScheduleWhole(tweakey, r) + tweakey = _BuildTweakey(tweak, key) + RTKs = _TweakeyScheduleWhole(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 = OneRoundEGFNEnc(state, RTKs[i]) + state_output = _OneRoundEGFNEnc(state, RTKs[i]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = LastRoundEGFN(state, RTKs[r-1]) + state_output = _LastRoundEGFN(state, RTKs[r-1]) return state_output def decrypt(tweak, key, cipher): - r = _rounds(len(key)) + r = _Rounds(len(key)) - tweakey = BuildTweakey(tweak, key) - RTKs = TweakeyScheduleWhole(tweakey, r) + tweakey = _BuildTweakey(tweak, key) + RTKs = _TweakeyScheduleWhole(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 = OneRoundEGFNDec(state, RTKs[r-i-1]) + state_output = _OneRoundEGFNDec(state, RTKs[r-i-1]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = LastRoundEGFN(state, RTKs[0]) + state_output = _LastRoundEGFN(state, RTKs[0]) return state_output -- cgit v1.2.3 From 099eac536457b12fa1919abffdb06a147d2cafde Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 00:02:27 +0100 Subject: [implem-python] Renommage des modules des modes authentifiés MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On bénéficie déjà de l'espace de nommage "lilliput". --- src/add_python/lilliput/__init__.py | 8 +- src/add_python/lilliput/ae_mode_1.py | 171 +++++++++++++++++++++++++++++++ src/add_python/lilliput/ae_mode_2.py | 143 ++++++++++++++++++++++++++ src/add_python/lilliput/lilliput_ae_1.py | 171 ------------------------------- src/add_python/lilliput/lilliput_ae_2.py | 143 -------------------------- 5 files changed, 318 insertions(+), 318 deletions(-) create mode 100644 src/add_python/lilliput/ae_mode_1.py create mode 100644 src/add_python/lilliput/ae_mode_2.py delete mode 100644 src/add_python/lilliput/lilliput_ae_1.py delete mode 100644 src/add_python/lilliput/lilliput_ae_2.py (limited to 'src/add_python') diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index b1bad58..dc193c6 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -24,14 +24,14 @@ The "mode" argument can be either of the following integers: """ -from . import lilliput_ae_1 -from . import lilliput_ae_2 +from . import ae_mode_1 +from . import ae_mode_2 from .constants import NONCE_BYTES _AE_MODES = { - 1: lilliput_ae_1, - 2: lilliput_ae_2 + 1: ae_mode_1, + 2: ae_mode_2 } diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py new file mode 100644 index 0000000..1429002 --- /dev/null +++ b/src/add_python/lilliput/ae_mode_1.py @@ -0,0 +1,171 @@ +# 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-I Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. +""" + +from enum import Enum + +from .constants import BLOCK_BYTES, NONCE_BYTES +from .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 192 +TWEAK_BYTES = TWEAK_BITS//8 + + +def _LowPart(array, number_bits): + shifted = 0 + for byte in range(0, len(array)): + shifted |= (array[byte] << (8 * byte)) + + mask = 0 + for bit in range(0, number_bits): + mask |= (0x1 << bit) + + lower_part = shifted & mask + + will_pad = 0 + if number_bits % 8 != 0: + will_pad = 1 + + lower_part_byte = [] + nb_bytes = number_bits//8 + will_pad + for byte in range(nb_bytes): + lower_part_byte.append(lower_part & 0xff) + lower_part = lower_part >> 8 + + return lower_part_byte + + +class _MessageTweak(Enum): + BLOCK = 0b000 + NO_PADDING = 0b0001 + PAD = 0b0100 + FINAL = 0b0101 + + +def _TweakMessage(N, j, padding): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(NONCE_BYTES-1, -1, -1): + tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 + tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 + + tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) + for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + tweak[-1] |= padding.value<<4 + + return tweak + + +def _TreatMessageEnc(M, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + checksum = XorState(checksum, M[j]) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + C.append(tbc.encrypt(tweak, key, M[j])) + + if padding_bytes == 0: + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + + lower_part = _LowPart(pad, padding_bytes*8) + C.append(XorState(M[l], lower_part)) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, C) + + +def _TreatMessageDec(C, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(C)//BLOCK_BYTES + padding_bytes = len(C)%BLOCK_BYTES + + C = ArrayToBlockbytesMatrix(C) + M = [] + + for j in range(0, l): + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + M.append(tbc.decrypt(tweak, key, C[j])) + checksum = XorState(checksum, M[j]) + + if padding_bytes == 0: + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + tweak = _TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + lower_part = _LowPart(pad, padding_bytes*8) + M.append(XorState(C[l], lower_part)) + + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, M) + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, C) = _TreatMessageEnc(M, N, K) + tag = XorState(Auth, Final) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, M) = _TreatMessageDec(C, N, K) + tag2 = XorState(Auth, Final) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return BlockbytesMatrixToBytes(M) 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..fb6feff --- /dev/null +++ b/src/add_python/lilliput/ae_mode_2.py @@ -0,0 +1,143 @@ +# 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 .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 128 +TWEAK_BYTES = TWEAK_BITS//8 + + +def _TweakTag(j, padded): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) + for byte in range(TWEAK_BYTES - 2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + if padded: + tweak[TWEAK_BYTES - 1] |= 0x40 + + return tweak + + +def _TweakTagEnd(N): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + for byte in range(0, TWEAK_BYTES - 1): + tweak[byte] = N[byte] + tweak[TWEAK_BYTES - 1] = 0x10 + + return tweak + + +def _AddTagJ(tag, j): + array_j = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(0, TWEAK_BYTES): + array_j[byte] = (j >> (byte * 8)) + + xorr = XorState(tag, array_j) + + xorr[TWEAK_BYTES - 1] |= 0x80 + + return xorr + + +def _MesssageAuthTag(M, N, Auth, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + tag = list(Auth) + M = ArrayToBlockbytesMatrix(M) + + for j in range(0, l): + tweak = _TweakTag(j, False) + encryption = tbc.encrypt(tweak, key, M[j]) + tag = XorState(tag, encryption) + + if need_padding: + tweak = _TweakTag(l, True) + m_padded = Padding10LSB(M[l]) + encryption = tbc.encrypt(tweak, key, m_padded) + tag = XorState(tag, encryption) + + tweak = _TweakTagEnd(N) + encryption = tbc.encrypt(tweak, key, tag) + tag = encryption + + return tag + + +def _MessageEncryption(M, N, tag, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + tweak = _AddTagJ(tag, j) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[j], encryption)) + + if need_padding: + tweak = _AddTagJ(tag, l) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[l], encryption)) + + return C + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + tag = _MesssageAuthTag(M, N, Auth, K) + C = _MessageEncryption(M, N, tag, K) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + M = BlockbytesMatrixToBytes( + _MessageEncryption(C, N, tag, K) + ) + Auth = BuildAuth(TWEAK_BITS, A, K) + tag2 = _MesssageAuthTag(M, N, Auth, K) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return M diff --git a/src/add_python/lilliput/lilliput_ae_1.py b/src/add_python/lilliput/lilliput_ae_1.py deleted file mode 100644 index 1429002..0000000 --- a/src/add_python/lilliput/lilliput_ae_1.py +++ /dev/null @@ -1,171 +0,0 @@ -# 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-I Authenticated Encryption mode. - -This module provides the functions for authenticated encryption and decryption -using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. -""" - -from enum import Enum - -from .constants import BLOCK_BYTES, NONCE_BYTES -from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, - TagValidationError, - XorState -) -from . import tbc - - -TWEAK_BITS = 192 -TWEAK_BYTES = TWEAK_BITS//8 - - -def _LowPart(array, number_bits): - shifted = 0 - for byte in range(0, len(array)): - shifted |= (array[byte] << (8 * byte)) - - mask = 0 - for bit in range(0, number_bits): - mask |= (0x1 << bit) - - lower_part = shifted & mask - - will_pad = 0 - if number_bits % 8 != 0: - will_pad = 1 - - lower_part_byte = [] - nb_bytes = number_bits//8 + will_pad - for byte in range(nb_bytes): - lower_part_byte.append(lower_part & 0xff) - lower_part = lower_part >> 8 - - return lower_part_byte - - -class _MessageTweak(Enum): - BLOCK = 0b000 - NO_PADDING = 0b0001 - PAD = 0b0100 - FINAL = 0b0101 - - -def _TweakMessage(N, j, padding): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(NONCE_BYTES-1, -1, -1): - tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 - tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 - - tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) - for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff - - tweak[-1] |= padding.value<<4 - - return tweak - - -def _TreatMessageEnc(M, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] - - l = len(M)//BLOCK_BYTES - padding_bytes = len(M)%BLOCK_BYTES - - M = ArrayToBlockbytesMatrix(M) - C = [] - - for j in range(0, l): - checksum = XorState(checksum, M[j]) - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) - C.append(tbc.encrypt(tweak, key, M[j])) - - if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) - Final = tbc.encrypt(tweak, key, checksum) - - else: - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak = _TweakMessage(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - - lower_part = _LowPart(pad, padding_bytes*8) - C.append(XorState(M[l], lower_part)) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) - Final = tbc.encrypt(tweak_final, key, checksum) - - return (Final, C) - - -def _TreatMessageDec(C, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] - - l = len(C)//BLOCK_BYTES - padding_bytes = len(C)%BLOCK_BYTES - - C = ArrayToBlockbytesMatrix(C) - M = [] - - for j in range(0, l): - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) - M.append(tbc.decrypt(tweak, key, C[j])) - checksum = XorState(checksum, M[j]) - - if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) - Final = tbc.encrypt(tweak, key, checksum) - - else: - tweak = _TweakMessage(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _LowPart(pad, padding_bytes*8) - M.append(XorState(C[l], lower_part)) - - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) - Final = tbc.encrypt(tweak_final, key, checksum) - - return (Final, M) - - -################################################################################ -def encrypt(A, M, N, key): - K = list(key) - - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = _TreatMessageEnc(M, N, K) - tag = XorState(Auth, Final) - - return BlockbytesMatrixToBytes(C), bytes(tag) - - -def decrypt(A, C, N, tag, key): - K = list(key) - tag = list(tag) - - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = _TreatMessageDec(C, N, K) - tag2 = XorState(Auth, Final) - - if tag != tag2: - raise TagValidationError(tag, tag2) - - return BlockbytesMatrixToBytes(M) diff --git a/src/add_python/lilliput/lilliput_ae_2.py b/src/add_python/lilliput/lilliput_ae_2.py deleted file mode 100644 index fb6feff..0000000 --- a/src/add_python/lilliput/lilliput_ae_2.py +++ /dev/null @@ -1,143 +0,0 @@ -# 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 .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, - TagValidationError, - XorState -) -from . import tbc - - -TWEAK_BITS = 128 -TWEAK_BYTES = TWEAK_BITS//8 - - -def _TweakTag(j, padded): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) - for byte in range(TWEAK_BYTES - 2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff - - if padded: - tweak[TWEAK_BYTES - 1] |= 0x40 - - return tweak - - -def _TweakTagEnd(N): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - for byte in range(0, TWEAK_BYTES - 1): - tweak[byte] = N[byte] - tweak[TWEAK_BYTES - 1] = 0x10 - - return tweak - - -def _AddTagJ(tag, j): - array_j = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(0, TWEAK_BYTES): - array_j[byte] = (j >> (byte * 8)) - - xorr = XorState(tag, array_j) - - xorr[TWEAK_BYTES - 1] |= 0x80 - - return xorr - - -def _MesssageAuthTag(M, N, Auth, key): - l = len(M)//BLOCK_BYTES - need_padding = len(M)%BLOCK_BYTES > 0 - - tag = list(Auth) - M = ArrayToBlockbytesMatrix(M) - - for j in range(0, l): - tweak = _TweakTag(j, False) - encryption = tbc.encrypt(tweak, key, M[j]) - tag = XorState(tag, encryption) - - if need_padding: - tweak = _TweakTag(l, True) - m_padded = Padding10LSB(M[l]) - encryption = tbc.encrypt(tweak, key, m_padded) - tag = XorState(tag, encryption) - - tweak = _TweakTagEnd(N) - encryption = tbc.encrypt(tweak, key, tag) - tag = encryption - - return tag - - -def _MessageEncryption(M, N, tag, key): - l = len(M)//BLOCK_BYTES - need_padding = len(M)%BLOCK_BYTES > 0 - - M = ArrayToBlockbytesMatrix(M) - C = [] - - for j in range(0, l): - tweak = _AddTagJ(tag, j) - padded_nonce = list(N) + [0x00] - encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[j], encryption)) - - if need_padding: - tweak = _AddTagJ(tag, l) - padded_nonce = list(N) + [0x00] - encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[l], encryption)) - - return C - - -################################################################################ -def encrypt(A, M, N, key): - K = list(key) - - Auth = BuildAuth(TWEAK_BITS, A, K) - tag = _MesssageAuthTag(M, N, Auth, K) - C = _MessageEncryption(M, N, tag, K) - - return BlockbytesMatrixToBytes(C), bytes(tag) - - -def decrypt(A, C, N, tag, key): - K = list(key) - tag = list(tag) - - M = BlockbytesMatrixToBytes( - _MessageEncryption(C, N, tag, K) - ) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = _MesssageAuthTag(M, N, Auth, K) - - if tag != tag2: - raise TagValidationError(tag, tag2) - - return M -- cgit v1.2.3 From cac916e13cc39b95a95b90352fe0f7a6fa6734f7 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 13:26:08 +0100 Subject: [implem-python] Correction de la documentation de Lilliput-Ⅰ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 1429002..c2fdd9e 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -15,7 +15,7 @@ """Lilliput-I Authenticated Encryption mode. This module provides the functions for authenticated encryption and decryption -using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. +using Lilliput-AE's nonce-respecting mode based on ΘCB3. """ from enum import Enum -- cgit v1.2.3 From 1b6e1eb38927633292e934ac314b10e7acc28e3d Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 14:17:25 +0100 Subject: [implem-python] Conformité PEP8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surtout la capitalisation des noms de fonction. Retrait des lignes de '#' ; si il y a des séparations à faire, autant ajouter des modules. Correction de _MessageTweak.BLOCK en passant. --- src/add_python/lilliput/ae_mode_1.py | 77 +++++++++++++------------ src/add_python/lilliput/ae_mode_2.py | 62 ++++++++++---------- src/add_python/lilliput/constants.py | 2 +- src/add_python/lilliput/helpers.py | 24 ++++---- src/add_python/lilliput/multiplications.py | 28 ++++----- src/add_python/lilliput/tbc.py | 91 ++++++++++++++---------------- 6 files changed, 140 insertions(+), 144 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index c2fdd9e..cc550e8 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -22,12 +22,12 @@ from enum import Enum from .constants import BLOCK_BYTES, NONCE_BYTES from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, + bytes_to_block_matrix, + block_matrix_to_bytes, + build_auth, + pad10, TagValidationError, - XorState + xor_state ) from . import tbc @@ -36,7 +36,7 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def _LowPart(array, number_bits): +def _low_part(array, number_bits): shifted = 0 for byte in range(0, len(array)): shifted |= (array[byte] << (8 * byte)) @@ -61,13 +61,13 @@ def _LowPart(array, number_bits): class _MessageTweak(Enum): - BLOCK = 0b000 + BLOCK = 0b0000 NO_PADDING = 0b0001 PAD = 0b0100 FINAL = 0b0101 -def _TweakMessage(N, j, padding): +def _tweak_message(N, j, padding): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(NONCE_BYTES-1, -1, -1): tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 @@ -82,90 +82,89 @@ def _TweakMessage(N, j, padding): return tweak -def _TreatMessageEnc(M, N, key): +def _treat_message_enc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) C = [] for j in range(0, l): - checksum = XorState(checksum, M[j]) - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + checksum = xor_state(checksum, M[j]) + tweak = _tweak_message(N, j, _MessageTweak.BLOCK) C.append(tbc.encrypt(tweak, key, M[j])) if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak = _TweakMessage(N, l, _MessageTweak.PAD) + m_padded = pad10(M[l]) + checksum = xor_state(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 = _LowPart(pad, padding_bytes*8) - C.append(XorState(M[l], lower_part)) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + lower_part = _low_part(pad, padding_bytes*8) + C.append(xor_state(M[l], lower_part)) + tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, C) -def _TreatMessageDec(C, N, key): +def _treat_message_dec(C, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(C)//BLOCK_BYTES padding_bytes = len(C)%BLOCK_BYTES - C = ArrayToBlockbytesMatrix(C) + C = bytes_to_block_matrix(C) M = [] for j in range(0, l): - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _tweak_message(N, j, _MessageTweak.BLOCK) M.append(tbc.decrypt(tweak, key, C[j])) - checksum = XorState(checksum, M[j]) + checksum = xor_state(checksum, M[j]) if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - tweak = _TweakMessage(N, l, _MessageTweak.PAD) + tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _LowPart(pad, padding_bytes*8) - M.append(XorState(C[l], lower_part)) + lower_part = _low_part(pad, padding_bytes*8) + M.append(xor_state(C[l], lower_part)) - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + m_padded = pad10(M[l]) + checksum = xor_state(checksum, m_padded) + tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, M) -################################################################################ def encrypt(A, M, N, key): K = list(key) - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = _TreatMessageEnc(M, N, K) - tag = XorState(Auth, Final) + Auth = build_auth(TWEAK_BITS, A, K) + (Final, C) = _treat_message_enc(M, N, K) + tag = xor_state(Auth, Final) - return BlockbytesMatrixToBytes(C), bytes(tag) + return block_matrix_to_bytes(C), bytes(tag) def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = _TreatMessageDec(C, N, K) - tag2 = XorState(Auth, Final) + Auth = build_auth(TWEAK_BITS, A, K) + (Final, M) = _treat_message_dec(C, N, K) + tag2 = xor_state(Auth, Final) if tag != tag2: raise TagValidationError(tag, tag2) - return BlockbytesMatrixToBytes(M) + return block_matrix_to_bytes(M) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index fb6feff..4d5e499 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -20,12 +20,12 @@ using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. from .constants import BLOCK_BYTES from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, + bytes_to_block_matrix, + block_matrix_to_bytes, + build_auth, + pad10, TagValidationError, - XorState + xor_state ) from . import tbc @@ -34,7 +34,7 @@ TWEAK_BITS = 128 TWEAK_BYTES = TWEAK_BITS//8 -def _TweakTag(j, padded): +def _tweak_tag(j, padded): tweak = [0 for byte in range(0, TWEAK_BYTES)] tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) @@ -47,7 +47,7 @@ def _TweakTag(j, padded): return tweak -def _TweakTagEnd(N): +def _tweak_tag_end(N): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES - 1): @@ -57,61 +57,61 @@ def _TweakTagEnd(N): return tweak -def _AddTagJ(tag, j): +def _add_tag_j(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) - xorr = XorState(tag, array_j) + xorr = xor_state(tag, array_j) xorr[TWEAK_BYTES - 1] |= 0x80 return xorr -def _MesssageAuthTag(M, N, Auth, key): +def _message_auth_tag(M, N, Auth, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 tag = list(Auth) - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) for j in range(0, l): - tweak = _TweakTag(j, False) + tweak = _tweak_tag(j, False) encryption = tbc.encrypt(tweak, key, M[j]) - tag = XorState(tag, encryption) + tag = xor_state(tag, encryption) if need_padding: - tweak = _TweakTag(l, True) - m_padded = Padding10LSB(M[l]) + tweak = _tweak_tag(l, True) + m_padded = pad10(M[l]) encryption = tbc.encrypt(tweak, key, m_padded) - tag = XorState(tag, encryption) + tag = xor_state(tag, encryption) - tweak = _TweakTagEnd(N) + tweak = _tweak_tag_end(N) encryption = tbc.encrypt(tweak, key, tag) tag = encryption return tag -def _MessageEncryption(M, N, tag, key): +def _message_encryption(M, N, tag, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) C = [] for j in range(0, l): - tweak = _AddTagJ(tag, j) + tweak = _add_tag_j(tag, j) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[j], encryption)) + C.append(xor_state(M[j], encryption)) if need_padding: - tweak = _AddTagJ(tag, l) + tweak = _add_tag_j(tag, l) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[l], encryption)) + C.append(xor_state(M[l], encryption)) return C @@ -120,22 +120,22 @@ def _MessageEncryption(M, N, tag, key): def encrypt(A, M, N, key): K = list(key) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag = _MesssageAuthTag(M, N, Auth, K) - C = _MessageEncryption(M, N, tag, K) + Auth = build_auth(TWEAK_BITS, A, K) + tag = _message_auth_tag(M, N, Auth, K) + C = _message_encryption(M, N, tag, K) - return BlockbytesMatrixToBytes(C), bytes(tag) + return block_matrix_to_bytes(C), bytes(tag) def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) - M = BlockbytesMatrixToBytes( - _MessageEncryption(C, N, tag, K) + M = block_matrix_to_bytes( + _message_encryption(C, N, tag, K) ) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = _MesssageAuthTag(M, N, Auth, K) + Auth = build_auth(TWEAK_BITS, A, K) + tag2 = _message_auth_tag(M, N, Auth, K) if tag != tag2: raise TagValidationError(tag, tag2) diff --git a/src/add_python/lilliput/constants.py b/src/add_python/lilliput/constants.py index 0c9b89f..5e07e96 100644 --- a/src/add_python/lilliput/constants.py +++ b/src/add_python/lilliput/constants.py @@ -4,7 +4,7 @@ NONCE_BYTES = 15 TAG_BYTES = 16 -Sbox = [ +SBOX = [ 0x20, 0x00, 0xb2, 0x85, 0x3b, 0x35, 0xa6, 0xa4, 0x30, 0xe4, 0x6a, 0x2c, 0xff, 0x59, 0xe2, 0x0e, 0xf8, 0x1e, 0x7a, 0x80, 0x15, 0xbd, 0x3e, 0xb1, diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py index 8677f06..65989d0 100644 --- a/src/add_python/lilliput/helpers.py +++ b/src/add_python/lilliput/helpers.py @@ -2,7 +2,7 @@ from .constants import BLOCK_BITS, BLOCK_BYTES from . import tbc -def ArrayToBlockbytesMatrix(array): +def bytes_to_block_matrix(array): vector = list(array) blocks_nb = len(vector)//BLOCK_BYTES @@ -24,20 +24,20 @@ def ArrayToBlockbytesMatrix(array): return matrix -def BlockbytesMatrixToBytes(matrix): +def block_matrix_to_bytes(matrix): return bytes(byte for block in matrix for byte in block) -def XorState(state1, state2): +def xor_state(state1, state2): return [s1^s2 for (s1, s2) in zip(state1, state2)] -def Padding10LSB(X): +def pad10(X): zeroes = [0] * (BLOCK_BYTES-len(X)-1) return zeroes + [0b10000000] + X -def _tweakAssociatedData(t, i, padded): +def _tweak_associated_data(t, i, padded): t_bytes = t//8 tweak = [0]*(t_bytes) @@ -56,25 +56,25 @@ def _tweakAssociatedData(t, i, padded): return tweak -def BuildAuth(t, A, key): +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 = ArrayToBlockbytesMatrix(A) + A = bytes_to_block_matrix(A) for i in range(0, l_a): - tweak = _tweakAssociatedData(t, i, padded=False) + tweak = _tweak_associated_data(t, i, padded=False) enc = tbc.encrypt(tweak, key, A[i]) - Auth = XorState(Auth, enc) + Auth = xor_state(Auth, enc) if not need_padding: return Auth - tweak = _tweakAssociatedData(t, l_a, padded=True) - ad_padded = Padding10LSB(A[l_a]) + tweak = _tweak_associated_data(t, l_a, padded=True) + ad_padded = pad10(A[l_a]) enc = tbc.encrypt(tweak, key, ad_padded) - Auth = XorState(Auth, enc) + Auth = xor_state(Auth, enc) return Auth diff --git a/src/add_python/lilliput/multiplications.py b/src/add_python/lilliput/multiplications.py index c5f1e44..dfdc3cb 100644 --- a/src/add_python/lilliput/multiplications.py +++ b/src/add_python/lilliput/multiplications.py @@ -1,6 +1,6 @@ -# Multiply by matrix M -def _multiplyM(lane): + +def _multiply_M(lane): multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[6] << 2) & 0xff) @@ -9,7 +9,8 @@ def _multiplyM(lane): return multiplied_lane -def _multiplyM2(lane): + +def _multiply_M2(lane): multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[5] << 2) & 0xff) @@ -35,7 +36,7 @@ def _multiplyM2(lane): return multiplied_lane -def _multiplyM3(lane): +def _multiply_M3(lane): multiplied_lane = [lane[(byte-3) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] << 2) & 0xff) ^ ((lane[5] << 5) & 0xff) @@ -86,7 +87,7 @@ def _multiplyM3(lane): return multiplied_lane -def _multiplyMR(lane): +def _multiply_MR(lane): multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff) @@ -96,7 +97,7 @@ def _multiplyMR(lane): return multiplied_lane -def _multiplyMR2(lane): +def _multiply_MR2(lane): multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)] multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff) @@ -120,7 +121,8 @@ def _multiplyMR2(lane): return multiplied_lane -def _multiplyMR3(lane): + +def _multiply_MR3(lane): multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)] multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff) @@ -177,10 +179,10 @@ def _multiplyMR3(lane): ALPHAS = ( list, # Identity. - _multiplyM, - _multiplyM2, - _multiplyM3, - _multiplyMR, - _multiplyMR2, - _multiplyMR3 + _multiply_M, + _multiply_M2, + _multiply_M3, + _multiply_MR, + _multiply_MR2, + _multiply_MR3 ) diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py index 50f9e2f..c607e45 100644 --- a/src/add_python/lilliput/tbc.py +++ b/src/add_python/lilliput/tbc.py @@ -17,35 +17,33 @@ This module provides functions to encrypt and decrypt blocks of 128 bits. """ -from .constants import BLOCK_BYTES, Sbox +from .constants import BLOCK_BYTES, SBOX from .multiplications import ALPHAS -_permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] -_permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] +_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] -################################################################################ -def _BuildTweakey(tweak, key): +def _build_tweakey(tweak, key): return tweak+key -############################# -def _Lane(TK, j): +def _lane(TK, j): return TK[j*8:(j+1)*8] -def _RoundTweakeySchedule(tweakey): +def _round_tweakey_schedule(tweakey): p = len(tweakey)//8 multiplied_lanes = ( - ALPHAS[j](_Lane(tweakey, j)) for j in range(p) + ALPHAS[j](_lane(tweakey, j)) for j in range(p) ) return [byte for lane in multiplied_lanes for byte in lane] -def _SubTweakeyExtract(tweakey, Ci): +def _subtweakey_extract(tweakey, Ci): RTKi = [0]*8 for j, byte in enumerate(tweakey): @@ -56,22 +54,20 @@ def _SubTweakeyExtract(tweakey, Ci): return RTKi -def _TweakeyScheduleWhole(tweakey, r): +def _tweakey_schedule_whole(tweakey, r): # Store the initial tweakey in TKs[0], and the corresponding round tweakey # in RTKs[0]. TKs = [tweakey] - RTKs = [_SubTweakeyExtract(TKs[0], 0)] + RTKs = [_subtweakey_extract(TKs[0], 0)] for i in range(1, r): - TKs.append(_RoundTweakeySchedule(TKs[i-1])) - RTKs.append(_SubTweakeyExtract(TKs[i], i)) + TKs.append(_round_tweakey_schedule(TKs[i-1])) + RTKs.append(_subtweakey_extract(TKs[i], i)) return RTKs -################################################################################ - -def _NonLinearLayer(state, subtweakey): +def _non_linear_layer(state, subtweakey): variables_xored = [0 for byte in range(0, 8)] for byte in range(0,8): @@ -79,7 +75,7 @@ def _NonLinearLayer(state, subtweakey): variables_sboxed = [0 for byte in range(0, 8)] for byte in range(0, 8): - variables_sboxed[byte] = Sbox[variables_xored[byte]] + variables_sboxed[byte] = SBOX[variables_xored[byte]] state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0,BLOCK_BYTES): @@ -90,7 +86,7 @@ def _NonLinearLayer(state, subtweakey): return state_output -def _LinearLayer(state): +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] @@ -104,44 +100,46 @@ def _LinearLayer(state): return state_output -def _PermutationLayerEnc(state): +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]] + state_output[byte] = state[_PERMUTATION[byte]] return state_output -def _PermutationLayerDec(state): + +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[_permutationInv[byte]] + state_output[byte] = state[_PERMUTATION_INV[byte]] return state_output -def _OneRoundEGFNEnc(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) - state_permutation = _PermutationLayerEnc(state_linear) +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) return state_permutation -def _LastRoundEGFN(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) + +def _last_round_egfn(state, subtweakey): + state_non_linear = _non_linear_layer(state, subtweakey) + state_linear = _linear_layer(state_non_linear) return state_linear -def _OneRoundEGFNDec(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) - state_permutation = _PermutationLayerDec(state_linear) +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) return state_permutation -def _Rounds(key_bytes): +def _rounds(key_bytes): rounds = { 128: 32, 192: 36, @@ -150,46 +148,43 @@ def _Rounds(key_bytes): return rounds[key_bytes*8] -################################################################################ - - def encrypt(tweak, key, message): - r = _Rounds(len(key)) + r = _rounds(len(key)) - tweakey = _BuildTweakey(tweak, key) - RTKs = _TweakeyScheduleWhole(tweakey, r) + 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 = _OneRoundEGFNEnc(state, RTKs[i]) + state_output = _one_round_egfn_enc(state, RTKs[i]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = _LastRoundEGFN(state, RTKs[r-1]) + state_output = _last_round_egfn(state, RTKs[r-1]) return state_output def decrypt(tweak, key, cipher): - r = _Rounds(len(key)) + r = _rounds(len(key)) - tweakey = _BuildTweakey(tweak, key) - RTKs = _TweakeyScheduleWhole(tweakey, r) + 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 = _OneRoundEGFNDec(state, RTKs[r-i-1]) + state_output = _one_round_egfn_dec(state, RTKs[r-i-1]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = _LastRoundEGFN(state, RTKs[0]) + state_output = _last_round_egfn(state, RTKs[0]) return state_output -- cgit v1.2.3 From 33c615feaaf148c099ee4299ad2c8a6f7e1778cf Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 15:19:15 +0100 Subject: [implem-python] Réécriture de certains range() dans tbc.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/add_python/lilliput/ae_common.py | 89 ++++++++++++++++++++++++++++++++ src/add_python/lilliput/ae_mode_1.py | 20 ++++---- src/add_python/lilliput/ae_mode_2.py | 14 +++--- src/add_python/lilliput/helpers.py | 94 +--------------------------------- src/add_python/lilliput/tbc.py | 98 ++++++++++++------------------------ 5 files changed, 140 insertions(+), 175 deletions(-) create mode 100644 src/add_python/lilliput/ae_common.py (limited to 'src/add_python') 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]) -- cgit v1.2.3 From 482091fe1812cf68789a65d7a8b8df9d1be551d2 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 16:38:18 +0100 Subject: [implem-python] Réécriture de certains range() dans ae_common.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et réutilisation de fonctions Python natives. --- src/add_python/lilliput/ae_common.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index f212353..033b5b0 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -35,32 +35,26 @@ def pad10(X): def _tweak_associated_data(t, i, padded): - t_bytes = t//8 - tweak = [0]*(t_bytes) + tweak = list(i.to_bytes(t//8, 'little')) - mask = 0xff - for byte in range(t_bytes-1): - tweak[byte] = (i & mask) >> (byte * 8) - mask = mask << 8 + prefix = 0b0110 if padded else 0b0010 - mask = (0xf << (8 * t_bytes-1)) - tweak[-1] = (i & mask) >> ((t_bytes-1)*8) - if not padded: - tweak[-1] |= 0x20 - else: - tweak[-1] |= 0x60 + # 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 for byte in range(0, BLOCK_BYTES)] + 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(0, l_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) -- cgit v1.2.3 From 62cff183e2e9e67549db0461589a05138ce2ed00 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 17:33:38 +0100 Subject: [implem-python] Remplacement de _low_part par du "tranchage" natif --- src/add_python/lilliput/ae_mode_1.py | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index efa0b6f..a5ba7c8 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -36,30 +36,6 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def _low_part(array, number_bits): - shifted = 0 - for byte in range(0, len(array)): - shifted |= (array[byte] << (8 * byte)) - - mask = 0 - for bit in range(0, number_bits): - mask |= (0x1 << bit) - - lower_part = shifted & mask - - will_pad = 0 - if number_bits % 8 != 0: - will_pad = 1 - - lower_part_byte = [] - nb_bytes = number_bits//8 + will_pad - for byte in range(nb_bytes): - lower_part_byte.append(lower_part & 0xff) - lower_part = lower_part >> 8 - - return lower_part_byte - - class _MessageTweak(Enum): BLOCK = 0b0000 NO_PADDING = 0b0001 @@ -106,7 +82,7 @@ def _treat_message_enc(M, 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) + lower_part = pad[:padding_bytes] C.append(xor(M[l], lower_part)) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -135,7 +111,7 @@ def _treat_message_dec(C, N, key): else: 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) + lower_part = pad[:padding_bytes] M.append(xor(C[l], lower_part)) m_padded = pad10(M[l]) -- cgit v1.2.3 From 07af965f2687105324e0142270a9e194a5ae6af5 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 08:38:01 +0100 Subject: [implem-python] Ajout des entêtes manquants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_common.py | 17 +++++++++++++++ src/add_python/lilliput/helpers.py | 17 +++++++++++++++ src/add_python/lilliput/multiplications.py | 19 +++++++++++++++++ test/python/crypto_aead.py | 33 +++++++++++++++++++++++------- test/python/genkat_aead.py | 17 ++++++++++++++- 5 files changed, 95 insertions(+), 8 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index 033b5b0..83db056 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -1,3 +1,20 @@ +# 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 diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py index 048aac7..41f75a6 100644 --- a/src/add_python/lilliput/helpers.py +++ b/src/add_python/lilliput/helpers.py @@ -1,2 +1,19 @@ +# 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 Lilliput-AE.""" + + def xor(array1, array2): return [a1^a2 for (a1, a2) in zip(array1, array2)] diff --git a/src/add_python/lilliput/multiplications.py b/src/add_python/lilliput/multiplications.py index dfdc3cb..2dea948 100644 --- a/src/add_python/lilliput/multiplications.py +++ b/src/add_python/lilliput/multiplications.py @@ -1,3 +1,22 @@ +# 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/ + +"""Multiplications for Lilliput-TBC's tweakey schedule. + +This module provides a list of functions implementing lane multiplications, +from ALPHAS[0] = α₀ = I to ALPHAS[6] = α₆ = M_R³. +""" def _multiply_M(lane): diff --git a/test/python/crypto_aead.py b/test/python/crypto_aead.py index 792369c..6a9b328 100644 --- a/test/python/crypto_aead.py +++ b/test/python/crypto_aead.py @@ -1,9 +1,29 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# 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/ + +"""Python port of the crypto_aead API for Lilliput-AE.""" + import lilliput -from lilliput.constants import NONCE_BYTES as NPUBBYTES, TAG_BYTES -# Import KEYBYTES to expose it to genkat_aead. -# Import MODE to provide it to lilliput. -from parameters import KEYBYTES, MODE +from lilliput.constants import ( + NONCE_BYTES as NPUBBYTES, # Expose to genkat_aead. + TAG_BYTES +) + +from parameters import ( + KEYBYTES, # Expose to genkat_aead. + MODE +) def encrypt(m, ad, npub, k): @@ -12,7 +32,6 @@ def encrypt(m, ad, npub, k): def decrypt(c, ad, npub, k): - clen = len(c)-TAG_BYTES - ctext = c[:clen] - tag = c[clen:] + ctext = c[:-TAG_BYTES] + tag = c[-TAG_BYTES:] return lilliput.decrypt(ctext, tag, ad, k, npub, MODE) diff --git a/test/python/genkat_aead.py b/test/python/genkat_aead.py index 5e953c4..db3a89c 100755 --- a/test/python/genkat_aead.py +++ b/test/python/genkat_aead.py @@ -1,11 +1,26 @@ #!/usr/bin/env python3 +# Python port of genkat_aead.c. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# 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/ + +"""Python port of the genkat_aead.c program.""" + import crypto_aead class DecryptionError(Exception): def __init__(self): - super().__init__('crypto_aead_decrypt did not recover the plaintext') + super().__init__('crypto_aead.decrypt did not recover the plaintext') MAX_MESSAGE_LENGTH = 32 -- cgit v1.2.3 From 0d0ecee46d6e5d47ff390cbaa254bf0d560d504f Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:10:33 +0100 Subject: [implem-python] Ajustements de forme --- src/add_python/lilliput/ae_common.py | 6 +++++- src/add_python/lilliput/ae_mode_1.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index 83db056..b94be1b 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -51,8 +51,12 @@ def pad10(X): 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 = list(i.to_bytes(t//8, 'little')) + tweak = integer_to_byte_array(i, t//8) prefix = 0b0110 if padded else 0b0010 diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index a5ba7c8..b07adf6 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -87,7 +87,7 @@ def _treat_message_enc(M, N, key): tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) - return (Final, C) + return Final, C def _treat_message_dec(C, N, key): @@ -119,7 +119,7 @@ def _treat_message_dec(C, N, key): tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) - return (Final, M) + return Final, M def encrypt(A, M, N, key): -- cgit v1.2.3 From 2cdc379dc0d4a260c5ca20619c892bdfbb6c0248 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:30:23 +0100 Subject: [implem-python] Remplacement de _tweak_tag_end par une concaténation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_2.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 91c53f3..bf09731 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -47,16 +47,6 @@ def _tweak_tag(j, padded): return tweak -def _tweak_tag_end(N): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - for byte in range(0, TWEAK_BYTES - 1): - tweak[byte] = N[byte] - tweak[TWEAK_BYTES - 1] = 0x10 - - return tweak - - def _add_tag_j(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): @@ -87,7 +77,7 @@ def _message_auth_tag(M, N, Auth, key): encryption = tbc.encrypt(tweak, key, m_padded) tag = xor(tag, encryption) - tweak = _tweak_tag_end(N) + tweak = N + [0b00010000] encryption = tbc.encrypt(tweak, key, tag) tag = encryption @@ -103,13 +93,13 @@ def _message_encryption(M, N, tag, key): for j in range(0, l): tweak = _add_tag_j(tag, j) - padded_nonce = list(N) + [0x00] + padded_nonce = N + [0b00000000] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(xor(M[j], encryption)) if need_padding: tweak = _add_tag_j(tag, l) - padded_nonce = list(N) + [0x00] + padded_nonce = N + [0b00000000] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(xor(M[l], encryption)) @@ -119,6 +109,7 @@ def _message_encryption(M, N, tag, key): ################################################################################ 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) @@ -129,6 +120,7 @@ def encrypt(A, M, N, key): def decrypt(A, C, N, tag, key): K = list(key) + N = list(N) tag = list(tag) M = block_matrix_to_bytes( -- cgit v1.2.3 From e96df775be1ab1553588bb0b81d02b9f6a3d19af Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:35:19 +0100 Subject: [implem-python] Simplification de _add_tag_j --- src/add_python/lilliput/ae_mode_2.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index bf09731..1878060 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -22,6 +22,7 @@ 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, @@ -48,15 +49,11 @@ def _tweak_tag(j, padded): def _add_tag_j(tag, j): - array_j = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(0, TWEAK_BYTES): - array_j[byte] = (j >> (byte * 8)) + array_j = integer_to_byte_array(j, TWEAK_BYTES) + tweak = xor(tag, array_j) + tweak[-1] |= 0b10000000 - xorr = xor(tag, array_j) - - xorr[TWEAK_BYTES - 1] |= 0x80 - - return xorr + return tweak def _message_auth_tag(M, N, Auth, key): -- cgit v1.2.3 From b6186739572125788c9ae0c528458eaaa7361ce9 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:42:23 +0100 Subject: [implem-python] Simplification de _tweak_tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Très similaire à ae_common._tweak_associated_data. --- src/add_python/lilliput/ae_mode_2.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 1878060..a486bc9 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -36,14 +36,13 @@ TWEAK_BYTES = TWEAK_BITS//8 def _tweak_tag(j, padded): - tweak = [0 for byte in range(0, TWEAK_BYTES)] + tweak = integer_to_byte_array(j, TWEAK_BYTES) - tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) - for byte in range(TWEAK_BYTES - 2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff + prefix = 0b0100 if padded else 0b0000 - if padded: - tweak[TWEAK_BYTES - 1] |= 0x40 + # Clear upper 4 bits and set them to prefix. + tweak[-1] &= 0b00001111 + tweak[-1] = prefix << 4 return tweak -- cgit v1.2.3 From d6164fddbb09f0dc5248b341e97610957f80f8f8 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:45:24 +0100 Subject: [implem-python] Suppression de variables intermédiaires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le code résultant ressemble plus à ce qui est décrit dans les algorithmes 3 et 4. --- src/add_python/lilliput/ae_mode_2.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index a486bc9..2349757 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -69,8 +69,7 @@ def _message_auth_tag(M, N, Auth, key): if need_padding: tweak = _tweak_tag(l, True) - m_padded = pad10(M[l]) - encryption = tbc.encrypt(tweak, key, m_padded) + encryption = tbc.encrypt(tweak, key, pad10(M[l])) tag = xor(tag, encryption) tweak = N + [0b00010000] @@ -89,14 +88,12 @@ def _message_encryption(M, N, tag, key): for j in range(0, l): tweak = _add_tag_j(tag, j) - padded_nonce = N + [0b00000000] - encryption = tbc.encrypt(tweak, key, padded_nonce) + encryption = tbc.encrypt(tweak, key, N+[0b00000000]) C.append(xor(M[j], encryption)) if need_padding: tweak = _add_tag_j(tag, l) - padded_nonce = N + [0b00000000] - encryption = tbc.encrypt(tweak, key, padded_nonce) + encryption = tbc.encrypt(tweak, key, N+[0b00000000]) C.append(xor(M[l], encryption)) return C -- cgit v1.2.3 From e9682e5ff9946a018e00f513f58b7c7651708a63 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:35:27 +0100 Subject: [implem-python] Construction de _tweak_message par concaténation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et petits nettoyages par-ci par-là. --- src/add_python/lilliput/__init__.py | 6 +++--- src/add_python/lilliput/ae_mode_1.py | 41 +++++++++++++++++++++++++----------- src/add_python/lilliput/constants.py | 2 +- test/python/crypto_aead.py | 5 ++++- 4 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index dc193c6..870e485 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -26,7 +26,7 @@ The "mode" argument can be either of the following integers: from . import ae_mode_1 from . import ae_mode_2 -from .constants import NONCE_BYTES +from .constants import NONCE_BITS _AE_MODES = { @@ -43,8 +43,8 @@ def _check_inputs(key, mode, nonce): if mode not in _AE_MODES: raise ValueError('invalid mode: {} not in {}'.format(mode, tuple(_AE_MODES))) - if len(nonce) != NONCE_BYTES: - raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BYTES, len(nonce))) + if len(nonce)*8 != NONCE_BITS: + raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BITS, len(nonce)*8)) def encrypt(plaintext, adata, key, nonce, mode): diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index b07adf6..1a3c39e 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -20,11 +20,12 @@ using Lilliput-AE's nonce-respecting mode based on ΘCB3. from enum import Enum -from .constants import BLOCK_BYTES, NONCE_BYTES +from .constants import BLOCK_BYTES, NONCE_BITS from .ae_common import ( bytes_to_block_matrix, block_matrix_to_bytes, build_auth, + integer_to_byte_array, pad10, TagValidationError, xor @@ -43,19 +44,33 @@ class _MessageTweak(Enum): FINAL = 0b0101 +def _upper_nibble(i): + return i >> 4 + + +def _lower_nibble(i): + return i & 0b00001111 + + +def _byte_from_nibbles(lower, upper): + return upper<<4 | lower + + def _tweak_message(N, j, padding): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(NONCE_BYTES-1, -1, -1): - tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 - tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 + j = integer_to_byte_array(j, (TWEAK_BITS-NONCE_BITS-4)//8+1) + + middle_byte = _byte_from_nibbles( + _lower_nibble(j[-1]), _lower_nibble(N[0]) + ) - tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) - for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff + shifted_N = [ + _byte_from_nibbles(_upper_nibble(N[i-1]), _lower_nibble(N[i])) + for i in range(1, NONCE_BITS//8) + ] - tweak[-1] |= padding.value<<4 + last_byte = _byte_from_nibbles(_upper_nibble(N[-1]), padding.value) - return tweak + return j[:-1] + [middle_byte] + shifted_N + [last_byte] def _treat_message_enc(M, N, key): @@ -124,9 +139,10 @@ def _treat_message_dec(C, N, key): def encrypt(A, M, N, key): K = list(key) + N = list(N) Auth = build_auth(TWEAK_BITS, A, K) - (Final, C) = _treat_message_enc(M, N, K) + Final, C = _treat_message_enc(M, N, K) tag = xor(Auth, Final) return block_matrix_to_bytes(C), bytes(tag) @@ -134,10 +150,11 @@ def encrypt(A, M, N, key): def decrypt(A, C, N, tag, key): K = list(key) + N = list(N) tag = list(tag) Auth = build_auth(TWEAK_BITS, A, K) - (Final, M) = _treat_message_dec(C, N, K) + Final, M = _treat_message_dec(C, N, K) tag2 = xor(Auth, Final) if tag != tag2: diff --git a/src/add_python/lilliput/constants.py b/src/add_python/lilliput/constants.py index 5e07e96..e69ca46 100644 --- a/src/add_python/lilliput/constants.py +++ b/src/add_python/lilliput/constants.py @@ -1,6 +1,6 @@ BLOCK_BITS = 128 BLOCK_BYTES = BLOCK_BITS//8 -NONCE_BYTES = 15 +NONCE_BITS = 120 TAG_BYTES = 16 diff --git a/test/python/crypto_aead.py b/test/python/crypto_aead.py index 6a9b328..d2f1896 100644 --- a/test/python/crypto_aead.py +++ b/test/python/crypto_aead.py @@ -16,7 +16,7 @@ import lilliput from lilliput.constants import ( - NONCE_BYTES as NPUBBYTES, # Expose to genkat_aead. + NONCE_BITS, TAG_BYTES ) @@ -26,6 +26,9 @@ from parameters import ( ) +NPUBBYTES = NONCE_BITS//8 + + def encrypt(m, ad, npub, k): c, tag = lilliput.encrypt(m, ad, k, npub, MODE) return c+tag -- cgit v1.2.3 From f468f2ca79e480fc058d37c338eb756ef88779f6 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:36:21 +0100 Subject: [implem-python] Suppression d'une ligne de '#' --- src/add_python/lilliput/ae_mode_2.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 2349757..79d1bcd 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -99,7 +99,6 @@ def _message_encryption(M, N, tag, key): return C -################################################################################ def encrypt(A, M, N, key): K = list(key) N = list(N) -- cgit v1.2.3 From 5949f01e728c11990280f6b1d1a35c2153db4578 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:41:02 +0100 Subject: [implem-python] Retrait de range()s et variables intermédiaires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_1.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 1a3c39e..23f4c7b 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -74,7 +74,7 @@ def _tweak_message(N, j, padding): def _treat_message_enc(M, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] + checksum = [0]*BLOCK_BYTES l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES @@ -95,10 +95,9 @@ def _treat_message_enc(M, N, key): m_padded = pad10(M[l]) 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)]) + pad = tbc.encrypt(tweak, key, [0]*BLOCK_BYTES) - lower_part = pad[:padding_bytes] - C.append(xor(M[l], lower_part)) + C.append(xor(M[l], pad[:padding_bytes])) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -106,7 +105,7 @@ def _treat_message_enc(M, N, key): def _treat_message_dec(C, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] + checksum = [0]*BLOCK_BYTES l = len(C)//BLOCK_BYTES padding_bytes = len(C)%BLOCK_BYTES @@ -125,9 +124,8 @@ def _treat_message_dec(C, N, key): else: tweak = _tweak_message(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = pad[:padding_bytes] - M.append(xor(C[l], lower_part)) + pad = tbc.encrypt(tweak, key, [0]*BLOCK_BYTES) + M.append(xor(C[l], pad[:padding_bytes])) m_padded = pad10(M[l]) checksum = xor(checksum, m_padded) -- cgit v1.2.3 From fc64da017336c553a345fdb690a2e496a4aefff3 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:59:24 +0100 Subject: [implem-python] Ajustements dans _tweak_message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hopefully, le résultat est plus clair en construisant le tweak par concaténations progressives. --- src/add_python/lilliput/ae_mode_1.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'src/add_python') diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 23f4c7b..4a40b78 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -56,21 +56,25 @@ def _byte_from_nibbles(lower, upper): return upper<<4 | lower -def _tweak_message(N, j, padding): - j = integer_to_byte_array(j, (TWEAK_BITS-NONCE_BITS-4)//8+1) - - middle_byte = _byte_from_nibbles( - _lower_nibble(j[-1]), _lower_nibble(N[0]) - ) - - shifted_N = [ +def _tweak_message(N, j, prefix): + # j is encoded on 68 bits; get 72 and clear the upper 4. + j_len = (TWEAK_BITS-NONCE_BITS-4)//8 + 1 + tweak = integer_to_byte_array(j, j_len) + tweak[-1] &= 0b00001111 + + # Add nonce. + tweak[-1] |= _lower_nibble(N[0]) << 4 + tweak.extend( _byte_from_nibbles(_upper_nibble(N[i-1]), _lower_nibble(N[i])) for i in range(1, NONCE_BITS//8) - ] + ) - last_byte = _byte_from_nibbles(_upper_nibble(N[-1]), padding.value) + # Add last nibble from nonce and prefix. + tweak.append( + _byte_from_nibbles(_upper_nibble(N[-1]), prefix.value) + ) - return j[:-1] + [middle_byte] + shifted_N + [last_byte] + return tweak def _treat_message_enc(M, N, key): -- cgit v1.2.3