From 95e1596db04fd55d777a1fccf031e86657ab1072 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 11:06:41 +0100 Subject: [implem-python] Passage des clés et nonces par paramètres MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/lilliput.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'python/lilliput.py') diff --git a/python/lilliput.py b/python/lilliput.py index 92d8662..79f14e5 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -53,14 +53,22 @@ def BlockbytesMatrixToBytes(matrix): ############################################ -def mainEnc(plaintext, adata, mode=1, length=128): +def _checkInputs(key, length, nonce): + if len(key) != length//8: + raise ValueError('invalid key size: {} != {}'.format(len(key), length//8)) + + if len(nonce) != N_BYTES: + raise ValueError('nonce must be {}-byte long'.format(N_BYTES)) + + +def mainEnc(plaintext, adata, key, nonce, mode=1, length=128): + _checkInputs(key, length, nonce) (key_bits, tweak_bits, rounds) = GetParameters(mode, length) A = adata M = plaintext - N = [byte for byte in range(0, N_BYTES)] - key = [byte for byte in range(0, int(key_bits/8))] + N = nonce A_BITS = 8 * len(A) M_BITS = 8 * len(M) @@ -76,14 +84,14 @@ def mainEnc(plaintext, adata, mode=1, length=128): return BlockbytesMatrixToBytes(C), bytes(tag) -def mainDec(ciphertext, tag, adata, mode=1, length=128): +def mainDec(ciphertext, tag, adata, key, nonce, mode=1, length=128): + _checkInputs(key, length, nonce) (key_bits, tweak_bits, rounds) = GetParameters(mode, length) A = adata C = ciphertext - N = [byte for byte in range(0, N_BYTES)] - key = [byte for byte in range(0, int(key_bits/8))] + N = nonce tag = list(tag) M_BITS = 8 * len(C) -- cgit v1.2.3 From d8eeb99d9106b93c0a30e3ab8849d7687d2a6f29 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 11:15:35 +0100 Subject: [implem-python] Simplification du contrôle des paramètres MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Encore un peu de duplication sur les longueurs de clés valides. On y travaille. --- python/genkat_aead.py | 4 ++-- python/lilliput.py | 55 ++++++++++++++++++++------------------------- python/parameters_i_128.py | 6 ----- python/parameters_i_192.py | 6 ----- python/parameters_i_256.py | 6 ----- python/parameters_ii_128.py | 6 ----- python/parameters_ii_192.py | 6 ----- python/parameters_ii_256.py | 6 ----- 8 files changed, 26 insertions(+), 69 deletions(-) delete mode 100644 python/parameters_i_128.py delete mode 100644 python/parameters_i_192.py delete mode 100644 python/parameters_i_256.py delete mode 100644 python/parameters_ii_128.py delete mode 100644 python/parameters_ii_192.py delete mode 100644 python/parameters_ii_256.py (limited to 'python/lilliput.py') diff --git a/python/genkat_aead.py b/python/genkat_aead.py index 3a69d72..6d7ca51 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -64,11 +64,11 @@ def generate_test_vectors(mode, keylen): print_bstr(output, 'PT', msg) print_bstr(output, 'AD', ad) - ct, tag = lilliput.mainEnc(msg, ad, key, nonce, mode, keylen) + ct, tag = lilliput.mainEnc(msg, ad, key, nonce, mode) print_bstr(output, 'CT', ct+tag) - msg2 = lilliput.mainDec(ct, tag, ad, key, nonce, mode, keylen) + msg2 = lilliput.mainDec(ct, tag, ad, key, nonce, mode) if msg != msg2: raise DecryptionError(msg, msg2, mode, keylen) diff --git a/python/lilliput.py b/python/lilliput.py index 79f14e5..3fe41bf 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -1,34 +1,23 @@ import lilliput_ae_1 import lilliput_ae_2 -import parameters_i_128 as i_128 -import parameters_i_192 as i_192 -import parameters_i_256 as i_256 -import parameters_ii_128 as ii_128 -import parameters_ii_192 as ii_192 -import parameters_ii_256 as ii_256 - BLOCK_BYTES = 16 N_BYTES = 15 -def GetParameters(mode = 1, length = 128) : - if(mode == 1 and length == 128) : - return (i_128.KEY_BITS, i_128.TWEAK_BITS, i_128.ROUNDS) - - if(mode == 1 and length == 192) : - return (i_192.KEY_BITS, i_192.TWEAK_BITS, i_192.ROUNDS) +def _getParameters(mode=1, key_length=128) : + rounds = { + 128: 32, + 192: 36, + 256: 42 + } - if(mode == 1 and length == 256) : - return (i_256.KEY_BITS, i_256.TWEAK_BITS, i_256.ROUNDS) + tweak_lengths = { + 1: 192, + 2: 128 + } - if(mode == 2 and length == 128) : - return (ii_128.KEY_BITS, ii_128.TWEAK_BITS, ii_128.ROUNDS) + return tweak_lengths[mode], rounds[key_length] - if(mode == 2 and length == 192) : - return (ii_192.KEY_BITS, ii_192.TWEAK_BITS, ii_192.ROUNDS) - - if(mode == 2 and length == 256) : - return (ii_256.KEY_BITS, ii_256.TWEAK_BITS, ii_256.ROUNDS) def ArrayToBlockbytesMatrix(array) : length = len(array) @@ -53,18 +42,21 @@ def BlockbytesMatrixToBytes(matrix): ############################################ -def _checkInputs(key, length, nonce): - if len(key) != length//8: - raise ValueError('invalid key size: {} != {}'.format(len(key), length//8)) +def _checkInputs(key, 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 len(nonce) != N_BYTES: raise ValueError('nonce must be {}-byte long'.format(N_BYTES)) -def mainEnc(plaintext, adata, key, nonce, mode=1, length=128): - _checkInputs(key, length, nonce) +def mainEnc(plaintext, adata, key, nonce, mode): + _checkInputs(key, nonce) - (key_bits, tweak_bits, rounds) = GetParameters(mode, length) + key_bits = len(key)*8 + tweak_bits, rounds = _getParameters(mode, key_bits) A = adata M = plaintext @@ -84,10 +76,11 @@ def mainEnc(plaintext, adata, key, nonce, mode=1, length=128): return BlockbytesMatrixToBytes(C), bytes(tag) -def mainDec(ciphertext, tag, adata, key, nonce, mode=1, length=128): - _checkInputs(key, length, nonce) +def mainDec(ciphertext, tag, adata, key, nonce, mode): + _checkInputs(key, nonce) - (key_bits, tweak_bits, rounds) = GetParameters(mode, length) + key_bits = len(key)*8 + tweak_bits, rounds = _getParameters(mode, key_bits) A = adata C = ciphertext diff --git a/python/parameters_i_128.py b/python/parameters_i_128.py deleted file mode 100644 index 7f0675a..0000000 --- a/python/parameters_i_128.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 128 -TWEAK_BITS = 192 -ROUNDS = 32 diff --git a/python/parameters_i_192.py b/python/parameters_i_192.py deleted file mode 100644 index c513331..0000000 --- a/python/parameters_i_192.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 192 -TWEAK_BITS = 192 -ROUNDS = 36 diff --git a/python/parameters_i_256.py b/python/parameters_i_256.py deleted file mode 100644 index ab81130..0000000 --- a/python/parameters_i_256.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 256 -TWEAK_BITS = 192 -ROUNDS = 42 diff --git a/python/parameters_ii_128.py b/python/parameters_ii_128.py deleted file mode 100644 index 8647a66..0000000 --- a/python/parameters_ii_128.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 128 -TWEAK_BITS = 128 -ROUNDS = 32 diff --git a/python/parameters_ii_192.py b/python/parameters_ii_192.py deleted file mode 100644 index d17d6ec..0000000 --- a/python/parameters_ii_192.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 192 -TWEAK_BITS = 128 -ROUNDS = 36 diff --git a/python/parameters_ii_256.py b/python/parameters_ii_256.py deleted file mode 100644 index 159c78f..0000000 --- a/python/parameters_ii_256.py +++ /dev/null @@ -1,6 +0,0 @@ -""" - Lilliput ae i 128 -""" -KEY_BITS = 256 -TWEAK_BITS = 128 -ROUNDS = 42 -- cgit v1.2.3 From 02eb0c9f257435595889d15577e4641b2242d0a1 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 12:38:36 +0100 Subject: [implem-python] Suppression de paramètres redondants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Création d'un nouveau module "helpers" qui contiendra les fonctions utilisées par les deux modes. --- python/constant.py | 32 ------------------------------ python/constants.py | 35 +++++++++++++++++++++++++++++++++ python/helpers.py | 25 ++++++++++++++++++++++++ python/lilliput.py | 52 ++++++------------------------------------------- python/lilliput_ae_1.py | 28 ++++++++++++++++---------- python/lilliput_ae_2.py | 29 +++++++++++++++++---------- python/lilliput_tbc.py | 4 ++-- 7 files changed, 105 insertions(+), 100 deletions(-) delete mode 100644 python/constant.py create mode 100644 python/constants.py create mode 100644 python/helpers.py (limited to 'python/lilliput.py') diff --git a/python/constant.py b/python/constant.py deleted file mode 100644 index 1bc208c..0000000 --- a/python/constant.py +++ /dev/null @@ -1,32 +0,0 @@ -Sbox = [32, 0, 178, 133, 59, 53, 166, 164, - 48, 228, 106, 44, 255, 89, 226, 14, - 248, 30, 122, 128, 21, 189, 62, 177, - 232, 243, 162, 194, 218, 81, 42, 16, - 33, 1, 35, 120, 92, 36, 39, 181, - 55, 199, 43, 31, 174, 10, 119, 95, - 111, 9, 157, 129, 4, 90, 41, 220, - 57, 156, 5, 87, 151, 116, 121, 23, - 68, 198, 230, 233, 221, 65, 242, 138, - 84, 202, 110, 74, 225, 173, 182, 136, - 28, 152, 126, 206, 99, 73, 58, 93, - 12, 239, 246, 52, 86, 37, 46, 214, - 103, 117, 85, 118, 184, 210, 97, 217, - 113, 139, 205, 11, 114, 108, 49, 75, - 105, 253, 123, 109, 96, 60, 47, 98, - 63, 34, 115, 19, 201, 130, 127, 83, - 50, 18, 160, 124, 2, 135, 132, 134, - 147, 78, 104, 70, 141, 195, 219, 236, - 155, 183, 137, 146, 167, 190, 61, 216, - 234, 80, 145, 241, 51, 56, 224, 169, - 163, 131, 161, 27, 207, 6, 149, 7, - 158, 237, 185, 245, 76, 192, 244, 45, - 22, 250, 180, 3, 38, 179, 144, 79, - 171, 101, 252, 254, 20, 247, 227, 148, - 238, 172, 140, 26, 222, 203, 40, 64, - 125, 200, 196, 72, 107, 223, 165, 82, - 229, 251, 215, 100, 249, 240, 211, 94, - 102, 150, 143, 29, 69, 54, 204, 197, - 77, 159, 191, 15, 209, 8, 235, 67, - 66, 25, 231, 153, 168, 142, 88, 193, - 154, 212, 24, 71, 170, 175, 188, 91, - 213, 17, 208, 176, 112, 187, 13, 186] diff --git a/python/constants.py b/python/constants.py new file mode 100644 index 0000000..acedfa7 --- /dev/null +++ b/python/constants.py @@ -0,0 +1,35 @@ +BLOCK_BYTES = 16 + + +Sbox = [32, 0, 178, 133, 59, 53, 166, 164, + 48, 228, 106, 44, 255, 89, 226, 14, + 248, 30, 122, 128, 21, 189, 62, 177, + 232, 243, 162, 194, 218, 81, 42, 16, + 33, 1, 35, 120, 92, 36, 39, 181, + 55, 199, 43, 31, 174, 10, 119, 95, + 111, 9, 157, 129, 4, 90, 41, 220, + 57, 156, 5, 87, 151, 116, 121, 23, + 68, 198, 230, 233, 221, 65, 242, 138, + 84, 202, 110, 74, 225, 173, 182, 136, + 28, 152, 126, 206, 99, 73, 58, 93, + 12, 239, 246, 52, 86, 37, 46, 214, + 103, 117, 85, 118, 184, 210, 97, 217, + 113, 139, 205, 11, 114, 108, 49, 75, + 105, 253, 123, 109, 96, 60, 47, 98, + 63, 34, 115, 19, 201, 130, 127, 83, + 50, 18, 160, 124, 2, 135, 132, 134, + 147, 78, 104, 70, 141, 195, 219, 236, + 155, 183, 137, 146, 167, 190, 61, 216, + 234, 80, 145, 241, 51, 56, 224, 169, + 163, 131, 161, 27, 207, 6, 149, 7, + 158, 237, 185, 245, 76, 192, 244, 45, + 22, 250, 180, 3, 38, 179, 144, 79, + 171, 101, 252, 254, 20, 247, 227, 148, + 238, 172, 140, 26, 222, 203, 40, 64, + 125, 200, 196, 72, 107, 223, 165, 82, + 229, 251, 215, 100, 249, 240, 211, 94, + 102, 150, 143, 29, 69, 54, 204, 197, + 77, 159, 191, 15, 209, 8, 235, 67, + 66, 25, 231, 153, 168, 142, 88, 193, + 154, 212, 24, 71, 170, 175, 188, 91, + 213, 17, 208, 176, 112, 187, 13, 186] diff --git a/python/helpers.py b/python/helpers.py new file mode 100644 index 0000000..34949a4 --- /dev/null +++ b/python/helpers.py @@ -0,0 +1,25 @@ +from constants import BLOCK_BYTES + + +def ArrayToBlockbytesMatrix(array) : + length = len(array) + pad = 0 + if(length % BLOCK_BYTES == 0) : + number_blocks = int(length / BLOCK_BYTES) + else : + number_blocks = int((length + (BLOCK_BYTES - (length % BLOCK_BYTES))) / BLOCK_BYTES) + pad = 1 + + matrix = [[0] * BLOCK_BYTES for block in range(0, number_blocks - pad)] + if(pad == 1) : + matrix.append([0] * (length % BLOCK_BYTES)) + + for byte in range(0, length) : + matrix[int(byte / BLOCK_BYTES)][byte % BLOCK_BYTES] = array[byte] + + return matrix + + +def BlockbytesMatrixToBytes(matrix): + return bytes(byte for block in matrix for byte in block) + diff --git a/python/lilliput.py b/python/lilliput.py index 3fe41bf..21feb60 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -1,7 +1,6 @@ import lilliput_ae_1 import lilliput_ae_2 -BLOCK_BYTES = 16 N_BYTES = 15 def _getParameters(mode=1, key_length=128) : @@ -19,27 +18,6 @@ def _getParameters(mode=1, key_length=128) : return tweak_lengths[mode], rounds[key_length] -def ArrayToBlockbytesMatrix(array) : - length = len(array) - pad = 0 - if(length % BLOCK_BYTES == 0) : - number_blocks = int(length / BLOCK_BYTES) - else : - number_blocks = int((length + (BLOCK_BYTES - (length % BLOCK_BYTES))) / BLOCK_BYTES) - pad = 1 - - matrix = [[0] * BLOCK_BYTES for block in range(0, number_blocks - pad)] - if(pad == 1) : - matrix.append([0] * (length % BLOCK_BYTES)) - - for byte in range(0, length) : - matrix[int(byte / BLOCK_BYTES)][byte % BLOCK_BYTES] = array[byte] - - return matrix - -def BlockbytesMatrixToBytes(matrix): - return bytes(byte for block in matrix for byte in block) - ############################################ def _checkInputs(key, nonce): @@ -55,47 +33,29 @@ def _checkInputs(key, nonce): def mainEnc(plaintext, adata, key, nonce, mode): _checkInputs(key, nonce) - key_bits = len(key)*8 - tweak_bits, rounds = _getParameters(mode, key_bits) + tweak_bits, rounds = _getParameters(mode, len(key)*8) A = adata M = plaintext N = nonce - A_BITS = 8 * len(A) - M_BITS = 8 * len(M) - - A = ArrayToBlockbytesMatrix(A) - M = ArrayToBlockbytesMatrix(M) - if(mode == 1) : - (C, tag) = lilliput_ae_1.OCB3Enc(A, M, N, A_BITS, M_BITS, key, key_bits, tweak_bits, rounds) + return lilliput_ae_1.OCB3Enc(A, M, N, key, tweak_bits, rounds) if(mode == 2) : - (C, tag) = lilliput_ae_2.SCT2Enc(A, M, N, A_BITS, M_BITS, key, key_bits, tweak_bits, rounds) - - return BlockbytesMatrixToBytes(C), bytes(tag) + return lilliput_ae_2.SCT2Enc(A, M, N, key, tweak_bits, rounds) def mainDec(ciphertext, tag, adata, key, nonce, mode): _checkInputs(key, nonce) - key_bits = len(key)*8 - tweak_bits, rounds = _getParameters(mode, key_bits) + tweak_bits, rounds = _getParameters(mode, len(key)*8) A = adata C = ciphertext N = nonce tag = list(tag) - M_BITS = 8 * len(C) - A_BITS = 8 * len(A) - - A = ArrayToBlockbytesMatrix(A) - C = ArrayToBlockbytesMatrix(C) - if(mode == 1) : - M = lilliput_ae_1.OCB3Dec(A, C, N, tag, A_BITS, M_BITS, key, key_bits, tweak_bits, rounds) + return lilliput_ae_1.OCB3Dec(A, C, N, tag, key, tweak_bits, rounds) if(mode == 2) : - M = lilliput_ae_2.SCT2Dec(A, C, N, tag, A_BITS, M_BITS, key, key_bits, tweak_bits, rounds) - - return BlockbytesMatrixToBytes(M) + return lilliput_ae_2.SCT2Dec(A, C, N, tag, key, tweak_bits, rounds) diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index cd7fc82..3629fec 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -3,6 +3,8 @@ """ import lilliput_tbc as ltbc +from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes + BLOCK_BITS = 128 KEY_BITS = 128 @@ -219,14 +221,17 @@ def TreatMessageDec(C, N, key) : ################################################################################ -def OCB3Enc(A, M, N, associated_data_length_bit, message_length_bit, key, key_bits, tweak_bits, rounds) : - InitParameters(key_bits, tweak_bits, rounds) +def OCB3Enc(A, M, N, key, tweak_bits, rounds) : + InitParameters(len(key)*8, tweak_bits, rounds) global A_BITS global M_BITS - A_BITS = associated_data_length_bit - M_BITS = message_length_bit + A_BITS = len(A)*8 + M_BITS = len(M)*8 + + A = ArrayToBlockbytesMatrix(A) + M = ArrayToBlockbytesMatrix(M) ltbc.KEY_BITS = KEY_BITS ltbc.ROUNDS = ROUNDS @@ -247,17 +252,20 @@ def OCB3Enc(A, M, N, associated_data_length_bit, message_length_bit, key, key_bi (Final, C) = TreatMessageEnc(M, N, key) tag = XorState(Auth, Final) - return (C, tag) + return BlockbytesMatrixToBytes(C), bytes(tag) -def OCB3Dec(A, C, N, tag, associated_data_length_bit, message_length_bit, key, key_bits, tweak_bits, rounds) : - InitParameters(key_bits, tweak_bits, rounds) +def OCB3Dec(A, C, N, tag, key, tweak_bits, rounds) : + InitParameters(len(key)*8, tweak_bits, rounds) global A_BITS global M_BITS - A_BITS = associated_data_length_bit - M_BITS = message_length_bit + A_BITS = len(A)*8 + M_BITS = len(C)*8 + + A = ArrayToBlockbytesMatrix(A) + C = ArrayToBlockbytesMatrix(C) ltbc.KEY_BITS = KEY_BITS ltbc.ROUNDS = ROUNDS @@ -278,4 +286,4 @@ def OCB3Dec(A, C, N, tag, associated_data_length_bit, message_length_bit, key, k tag2 = XorState(Auth, Final) if(tag == tag2) : - return M + return BlockbytesMatrixToBytes(M) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 40ee485..757088d 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -3,6 +3,8 @@ """ import lilliput_tbc as ltbc +from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes + BLOCK_BITS = 128 KEY_BITS = 128 @@ -215,14 +217,17 @@ def MessageEncryption(M, N, tag, key) : return C ################################################################################ -def SCT2Enc(A, M, N, associated_data_length_bit, message_length_bit, key, key_bits, tweak_bits, rounds) : - InitParameters(key_bits, tweak_bits, rounds) +def SCT2Enc(A, M, N, key, tweak_bits, rounds) : + InitParameters(len(key)*8, tweak_bits, rounds) global A_BITS global M_BITS - A_BITS = associated_data_length_bit - M_BITS = message_length_bit + A_BITS = len(A)*8 + M_BITS = len(M)*8 + + A = ArrayToBlockbytesMatrix(A) + M = ArrayToBlockbytesMatrix(M) ltbc.KEY_BITS = KEY_BITS ltbc.ROUNDS = ROUNDS @@ -243,16 +248,20 @@ def SCT2Enc(A, M, N, associated_data_length_bit, message_length_bit, key, key_bi tag = MesssageAuthTag(M, N, Auth, key) C = MessageEncryption(M, N, tag, key) - return (C, tag) + return BlockbytesMatrixToBytes(C), bytes(tag) -def SCT2Dec(A, C, N, tag, associated_data_length_bit, message_length_bit, key, key_bits, tweak_bits, rounds) : - InitParameters(key_bits, tweak_bits, rounds) + +def SCT2Dec(A, C, N, tag, key, tweak_bits, rounds) : + InitParameters(len(key)*8, tweak_bits, rounds) global A_BITS global M_BITS - A_BITS = associated_data_length_bit - M_BITS = message_length_bit + A_BITS = len(A)*8 + M_BITS = len(C)*8 + + A = ArrayToBlockbytesMatrix(A) + C = ArrayToBlockbytesMatrix(C) ltbc.KEY_BITS = KEY_BITS ltbc.ROUNDS = ROUNDS @@ -274,4 +283,4 @@ def SCT2Dec(A, C, N, tag, associated_data_length_bit, message_length_bit, key, k tag2 = MesssageAuthTag(M, N, Auth, key) if(tag == tag2) : - return M + return BlockbytesMatrixToBytes(M) diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 540d956..1ed4d8d 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -2,7 +2,7 @@ Lilliput TBC """ import random -import constant +import constants import multiplications BLOCK_BITS = 128 @@ -19,7 +19,7 @@ KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -Sbox = constant.Sbox +Sbox = constants.Sbox MultiplyM = multiplications.MultiplyM MultiplyM2 = multiplications.MultiplyM2 MultiplyM3 = multiplications.MultiplyM3 -- cgit v1.2.3 From f161a41e1bb1b379335bb658877a8859a64c9d10 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 12:47:41 +0100 Subject: [implem-python] Suppression de paramètres redondants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tweak_bits est constant pour un mode donné ; rounds se déduit de la taille de clé. --- python/constants.py | 9 +++++++++ python/lilliput.py | 29 +++++------------------------ python/lilliput_ae_1.py | 17 +++++++---------- python/lilliput_ae_2.py | 15 +++++++-------- 4 files changed, 28 insertions(+), 42 deletions(-) (limited to 'python/lilliput.py') diff --git a/python/constants.py b/python/constants.py index acedfa7..94a3e0e 100644 --- a/python/constants.py +++ b/python/constants.py @@ -1,6 +1,15 @@ BLOCK_BYTES = 16 +def rounds(key_bits): + r = { + 128: 32, + 192: 36, + 256: 42 + } + return r[key_bits] + + Sbox = [32, 0, 178, 133, 59, 53, 166, 164, 48, 228, 106, 44, 255, 89, 226, 14, 248, 30, 122, 128, 21, 189, 62, 177, diff --git a/python/lilliput.py b/python/lilliput.py index 21feb60..f6679a8 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -1,24 +1,9 @@ import lilliput_ae_1 import lilliput_ae_2 -N_BYTES = 15 - -def _getParameters(mode=1, key_length=128) : - rounds = { - 128: 32, - 192: 36, - 256: 42 - } - - tweak_lengths = { - 1: 192, - 2: 128 - } - - return tweak_lengths[mode], rounds[key_length] +N_BYTES = 15 -############################################ def _checkInputs(key, nonce): valid_key_lengths = (128, 192, 256) @@ -33,29 +18,25 @@ def _checkInputs(key, nonce): def mainEnc(plaintext, adata, key, nonce, mode): _checkInputs(key, nonce) - tweak_bits, rounds = _getParameters(mode, len(key)*8) - A = adata M = plaintext N = nonce if(mode == 1) : - return lilliput_ae_1.OCB3Enc(A, M, N, key, tweak_bits, rounds) + return lilliput_ae_1.OCB3Enc(A, M, N, key) if(mode == 2) : - return lilliput_ae_2.SCT2Enc(A, M, N, key, tweak_bits, rounds) + return lilliput_ae_2.SCT2Enc(A, M, N, key) def mainDec(ciphertext, tag, adata, key, nonce, mode): _checkInputs(key, nonce) - tweak_bits, rounds = _getParameters(mode, len(key)*8) - A = adata C = ciphertext N = nonce tag = list(tag) if(mode == 1) : - return lilliput_ae_1.OCB3Dec(A, C, N, tag, key, tweak_bits, rounds) + return lilliput_ae_1.OCB3Dec(A, C, N, tag, key) if(mode == 2) : - return lilliput_ae_2.SCT2Dec(A, C, N, tag, key, tweak_bits, rounds) + return lilliput_ae_2.SCT2Dec(A, C, N, tag, key) diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 3629fec..688148f 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -3,6 +3,7 @@ """ import lilliput_tbc as ltbc +from constants import rounds from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes @@ -24,23 +25,19 @@ M_BITS = BLOCK_BITS N_BITS = 120 N_BYTES = int(N_BITS / 8) -def InitParameters(key_bits = 128, tweak_bits = 192, rounds = 32) : +def InitParameters(key_bits) : global KEY_BITS global KEY_BYTES - global TWEAK_BITS - global TWEAK_BYTES global TWEAKEY_BITS global TWEAKEY_BYTES global LANES global ROUNDS KEY_BITS = key_bits - TWEAK_BITS = tweak_bits TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANES = int((TWEAKEY_BITS) / LANE_BITS) - ROUNDS = rounds + ROUNDS = rounds(key_bits) KEY_BYTES = int(KEY_BITS / 8) - TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) @@ -221,8 +218,8 @@ def TreatMessageDec(C, N, key) : ################################################################################ -def OCB3Enc(A, M, N, key, tweak_bits, rounds) : - InitParameters(len(key)*8, tweak_bits, rounds) +def OCB3Enc(A, M, N, key) : + InitParameters(len(key)*8) global A_BITS global M_BITS @@ -255,8 +252,8 @@ def OCB3Enc(A, M, N, key, tweak_bits, rounds) : return BlockbytesMatrixToBytes(C), bytes(tag) -def OCB3Dec(A, C, N, tag, key, tweak_bits, rounds) : - InitParameters(len(key)*8, tweak_bits, rounds) +def OCB3Dec(A, C, N, tag, key) : + InitParameters(len(key)*8) global A_BITS global M_BITS diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 757088d..d333be2 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -3,6 +3,7 @@ """ import lilliput_tbc as ltbc +from constants import rounds from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes @@ -25,7 +26,7 @@ N_BITS = 120 N_BYTES = int(N_BITS / 8) -def InitParameters(key_bits = 128, tweak_bits = 128, rounds = 32) : +def InitParameters(key_bits) : global KEY_BITS global KEY_BYTES global TWEAK_BITS @@ -36,12 +37,10 @@ def InitParameters(key_bits = 128, tweak_bits = 128, rounds = 32) : global ROUNDS KEY_BITS = key_bits - TWEAK_BITS = tweak_bits TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANES = int((TWEAKEY_BITS) / LANE_BITS) - ROUNDS = rounds + ROUNDS = rounds(key_bits) KEY_BYTES = int(KEY_BITS / 8) - TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) @@ -217,8 +216,8 @@ def MessageEncryption(M, N, tag, key) : return C ################################################################################ -def SCT2Enc(A, M, N, key, tweak_bits, rounds) : - InitParameters(len(key)*8, tweak_bits, rounds) +def SCT2Enc(A, M, N, key) : + InitParameters(len(key)*8) global A_BITS global M_BITS @@ -251,8 +250,8 @@ def SCT2Enc(A, M, N, key, tweak_bits, rounds) : return BlockbytesMatrixToBytes(C), bytes(tag) -def SCT2Dec(A, C, N, tag, key, tweak_bits, rounds) : - InitParameters(len(key)*8, tweak_bits, rounds) +def SCT2Dec(A, C, N, tag, key) : + InitParameters(len(key)*8) global A_BITS global M_BITS -- cgit v1.2.3 From 504c32f4bd4d6e90864fec066de950a1b8925709 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 13:06:45 +0100 Subject: [implem-python] Ajout de NONCE_BYTES dans constants.py --- python/constants.py | 1 + python/lilliput.py | 6 ++---- python/lilliput_ae_1.py | 15 +++++++-------- python/lilliput_ae_2.py | 2 -- 4 files changed, 10 insertions(+), 14 deletions(-) (limited to 'python/lilliput.py') diff --git a/python/constants.py b/python/constants.py index 94a3e0e..02bbc1f 100644 --- a/python/constants.py +++ b/python/constants.py @@ -1,4 +1,5 @@ BLOCK_BYTES = 16 +NONCE_BYTES = 15 def rounds(key_bits): diff --git a/python/lilliput.py b/python/lilliput.py index f6679a8..e92ed5f 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -1,8 +1,6 @@ import lilliput_ae_1 import lilliput_ae_2 - - -N_BYTES = 15 +from constants import NONCE_BYTES def _checkInputs(key, nonce): @@ -11,7 +9,7 @@ def _checkInputs(key, nonce): if len(key)*8 not in valid_key_lengths: raise ValueError('invalid key size: {} not in {}'.format(len(key)*8, valid_key_lengths)) - if len(nonce) != N_BYTES: + if len(nonce) != NONCE_BYTES: raise ValueError('nonce must be {}-byte long'.format(N_BYTES)) diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 688148f..92cfa6e 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -3,7 +3,7 @@ """ import lilliput_tbc as ltbc -from constants import rounds +from constants import NONCE_BYTES, rounds from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes @@ -22,8 +22,7 @@ TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) A_BITS = BLOCK_BITS M_BITS = BLOCK_BITS -N_BITS = 120 -N_BYTES = int(N_BITS / 8) + def InitParameters(key_bits) : global KEY_BITS @@ -131,12 +130,12 @@ def BuildAuth(A, key) : def TweakMessage(N, j, null = 0, padded = 0, final_padded = 0) : tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(N_BYTES - 1, -1, -1) : - tweak[byte + (TWEAK_BYTES - N_BYTES)] |= (N[byte] & 0xf0) >> 4 - tweak[byte + (TWEAK_BYTES - N_BYTES - 1)] |= (N[byte] & 0x0f) << 4 + 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 - N_BYTES - 1] |= ((j >> 64) & 0xf) - for byte in range(TWEAK_BYTES - N_BYTES - 2, -1, -1) : + 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 if null == 1 : diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index d333be2..d072935 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -22,8 +22,6 @@ TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) A_BITS = BLOCK_BITS M_BITS = BLOCK_BITS -N_BITS = 120 -N_BYTES = int(N_BITS / 8) def InitParameters(key_bits) : -- cgit v1.2.3 From 60707e26d3068a43e0caa7973a4fb88428443738 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:51:11 +0100 Subject: [implem-python] Correction d'un bug sur un chemin d'erreur --- python/lilliput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/lilliput.py') diff --git a/python/lilliput.py b/python/lilliput.py index e92ed5f..f9c1b09 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -10,7 +10,7 @@ def _checkInputs(key, nonce): raise ValueError('invalid key size: {} not in {}'.format(len(key)*8, valid_key_lengths)) if len(nonce) != NONCE_BYTES: - raise ValueError('nonce must be {}-byte long'.format(N_BYTES)) + raise ValueError('nonce must be {}-byte long'.format(NONCE_BYTES)) def mainEnc(plaintext, adata, key, nonce, mode): -- cgit v1.2.3 From 6d62f24fc34dae3c28f1b1cfed664bde3edbb1ec Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 17:17:50 +0100 Subject: [implem-python] Ajustement de l'API externe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utilisation d'une enum, pour que les valeurs possibles soient explicites. Renommage des points d'entrée pour qu'ils soient uniformes et interchangeables. Transformation du tag en liste plus bas pour que lilliput.py ne se soucie pas des détails d'implémentation des fonctions en-dessous. --- python/genkat_aead.py | 16 +++++++++++----- python/lilliput.py | 41 +++++++++++++++++------------------------ python/lilliput_ae_1.py | 5 +++-- python/lilliput_ae_2.py | 5 +++-- 4 files changed, 34 insertions(+), 33 deletions(-) (limited to 'python/lilliput.py') diff --git a/python/genkat_aead.py b/python/genkat_aead.py index 5bce05f..daa48f8 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import lilliput +from lilliput import encrypt, decrypt, LilliputAeMode from os import makedirs, path @@ -10,6 +10,12 @@ MAX_ADATA_LENGTH = 32 CRYPTO_NPUBBYTES = 120//8 +MODE_SUFFIXES = { + LilliputAeMode.lilliput_1: 'i', + LilliputAeMode.lilliput_2: 'ii' +} + + def bstr(buf): return ''.join('{:02X}'.format(b) for b in buf) @@ -37,7 +43,7 @@ def generate_test_vectors(mode, keylen): print('generating for', mode, keylen) directory = 'crypto_aead/lilliputae{mode}{keylen}v1'.format( - mode=mode*'i', keylen=keylen + mode=MODE_SUFFIXES[mode], keylen=keylen ) makedirs(directory, exist_ok=True) @@ -64,11 +70,11 @@ def generate_test_vectors(mode, keylen): print_bstr(output, 'PT', msg) print_bstr(output, 'AD', ad) - ct, tag = lilliput.mainEnc(msg, ad, key, nonce, mode) + ct, tag = encrypt(msg, ad, key, nonce, mode) print_bstr(output, 'CT', ct+tag) - msg2 = lilliput.mainDec(ct, tag, ad, key, nonce, mode) + msg2 = decrypt(ct, tag, ad, key, nonce, mode) if msg != msg2: raise DecryptionError(msg, msg2, mode, keylen) @@ -79,6 +85,6 @@ def generate_test_vectors(mode, keylen): if __name__ == '__main__': - for mode in 1, 2: + for mode in LilliputAeMode: for keylen in 128, 192, 256: generate_test_vectors(mode, keylen) diff --git a/python/lilliput.py b/python/lilliput.py index f9c1b09..90a0ed1 100644 --- a/python/lilliput.py +++ b/python/lilliput.py @@ -1,40 +1,33 @@ +from enum import Enum + import lilliput_ae_1 import lilliput_ae_2 from constants import NONCE_BYTES -def _checkInputs(key, nonce): +class LilliputAeMode(Enum): + lilliput_1 = lilliput_ae_1 + lilliput_2 = lilliput_ae_2 + + +def _checkInputs(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.name not in LilliputAeMode.__members__: + raise ValueError('invalid mode: use a member of the LilliputAeMode enumeration') + if len(nonce) != NONCE_BYTES: raise ValueError('nonce must be {}-byte long'.format(NONCE_BYTES)) -def mainEnc(plaintext, adata, key, nonce, mode): - _checkInputs(key, nonce) - - A = adata - M = plaintext - N = nonce - - if(mode == 1) : - return lilliput_ae_1.OCB3Enc(A, M, N, key) - if(mode == 2) : - return lilliput_ae_2.SCT2Enc(A, M, N, key) - - -def mainDec(ciphertext, tag, adata, key, nonce, mode): - _checkInputs(key, nonce) +def encrypt(plaintext, adata, key, nonce, mode): + _checkInputs(key, mode, nonce) + return mode.value.encrypt(adata, plaintext, nonce, key) - A = adata - C = ciphertext - N = nonce - tag = list(tag) - if(mode == 1) : - return lilliput_ae_1.OCB3Dec(A, C, N, tag, key) - if(mode == 2) : - return lilliput_ae_2.SCT2Dec(A, C, N, tag, key) +def decrypt(ciphertext, tag, adata, key, nonce, mode): + _checkInputs(key, mode, nonce) + return mode.value.decrypt(adata, ciphertext, nonce, tag, key) diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 9de753c..8b618d9 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -129,7 +129,7 @@ def TreatMessageDec(C, N, key) : ################################################################################ -def OCB3Enc(A, M, N, key) : +def encrypt(A, M, N, key) : K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -139,8 +139,9 @@ def OCB3Enc(A, M, N, key) : return BlockbytesMatrixToBytes(C), bytes(tag) -def OCB3Dec(A, C, N, tag, key) : +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) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index cb1d1c4..f455f43 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -98,7 +98,7 @@ def MessageEncryption(M, N, tag, key) : return C ################################################################################ -def SCT2Enc(A, M, N, key) : +def encrypt(A, M, N, key) : K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -108,8 +108,9 @@ def SCT2Enc(A, M, N, key) : return BlockbytesMatrixToBytes(C), bytes(tag) -def SCT2Dec(A, C, N, tag, key) : +def decrypt(A, C, N, tag, key) : K = list(key) + tag = list(tag) M = BlockbytesMatrixToBytes( MessageEncryption(C, N, tag, K) -- cgit v1.2.3 From bac28f498c5fee10720c8ed71988434e05d9197f Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 22 Mar 2019 10:38:19 +0100 Subject: [implem-python] Création d'un paquet "lilliput" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/constants.py | 39 -------- python/helpers.py | 92 ------------------ python/lilliput.py | 33 ------- python/lilliput/__init__.py | 33 +++++++ python/lilliput/constants.py | 39 ++++++++ python/lilliput/helpers.py | 92 ++++++++++++++++++ python/lilliput/lilliput_ae_1.py | 155 +++++++++++++++++++++++++++++++ python/lilliput/lilliput_ae_2.py | 127 +++++++++++++++++++++++++ python/lilliput/multiplications.py | 186 +++++++++++++++++++++++++++++++++++++ python/lilliput/tbc.py | 178 +++++++++++++++++++++++++++++++++++ python/lilliput_ae_1.py | 155 ------------------------------- python/lilliput_ae_2.py | 127 ------------------------- python/multiplications.py | 186 ------------------------------------- python/tbc.py | 178 ----------------------------------- 14 files changed, 810 insertions(+), 810 deletions(-) delete mode 100644 python/constants.py delete mode 100644 python/helpers.py delete mode 100644 python/lilliput.py create mode 100644 python/lilliput/__init__.py create mode 100644 python/lilliput/constants.py create mode 100644 python/lilliput/helpers.py create mode 100644 python/lilliput/lilliput_ae_1.py create mode 100644 python/lilliput/lilliput_ae_2.py create mode 100644 python/lilliput/multiplications.py create mode 100644 python/lilliput/tbc.py delete mode 100644 python/lilliput_ae_1.py delete mode 100644 python/lilliput_ae_2.py delete mode 100644 python/multiplications.py delete mode 100644 python/tbc.py (limited to 'python/lilliput.py') diff --git a/python/constants.py b/python/constants.py deleted file mode 100644 index c61dfe0..0000000 --- a/python/constants.py +++ /dev/null @@ -1,39 +0,0 @@ -BLOCK_BITS = 128 -BLOCK_BYTES = BLOCK_BITS//8 -NONCE_BYTES = 15 - - -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/python/helpers.py b/python/helpers.py deleted file mode 100644 index 321b096..0000000 --- a/python/helpers.py +++ /dev/null @@ -1,92 +0,0 @@ -from constants import BLOCK_BITS, BLOCK_BYTES -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/python/lilliput.py b/python/lilliput.py deleted file mode 100644 index 90a0ed1..0000000 --- a/python/lilliput.py +++ /dev/null @@ -1,33 +0,0 @@ -from enum import Enum - -import lilliput_ae_1 -import lilliput_ae_2 -from constants import NONCE_BYTES - - -class LilliputAeMode(Enum): - lilliput_1 = lilliput_ae_1 - lilliput_2 = lilliput_ae_2 - - -def _checkInputs(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.name not in LilliputAeMode.__members__: - raise ValueError('invalid mode: use a member of the LilliputAeMode enumeration') - - if len(nonce) != NONCE_BYTES: - raise ValueError('nonce must be {}-byte long'.format(NONCE_BYTES)) - - -def encrypt(plaintext, adata, key, nonce, mode): - _checkInputs(key, mode, nonce) - return mode.value.encrypt(adata, plaintext, nonce, key) - - -def decrypt(ciphertext, tag, adata, key, nonce, mode): - _checkInputs(key, mode, nonce) - return mode.value.decrypt(adata, ciphertext, nonce, tag, key) diff --git a/python/lilliput/__init__.py b/python/lilliput/__init__.py new file mode 100644 index 0000000..43179f8 --- /dev/null +++ b/python/lilliput/__init__.py @@ -0,0 +1,33 @@ +from enum import Enum + +from . import lilliput_ae_1 +from . import lilliput_ae_2 +from .constants import NONCE_BYTES + + +class LilliputAeMode(Enum): + lilliput_1 = lilliput_ae_1 + lilliput_2 = lilliput_ae_2 + + +def _checkInputs(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.name not in LilliputAeMode.__members__: + raise ValueError('invalid mode: use a member of the LilliputAeMode enumeration') + + if len(nonce) != NONCE_BYTES: + raise ValueError('nonce must be {}-byte long'.format(NONCE_BYTES)) + + +def encrypt(plaintext, adata, key, nonce, mode): + _checkInputs(key, mode, nonce) + return mode.value.encrypt(adata, plaintext, nonce, key) + + +def decrypt(ciphertext, tag, adata, key, nonce, mode): + _checkInputs(key, mode, nonce) + return mode.value.decrypt(adata, ciphertext, nonce, tag, key) diff --git a/python/lilliput/constants.py b/python/lilliput/constants.py new file mode 100644 index 0000000..c61dfe0 --- /dev/null +++ b/python/lilliput/constants.py @@ -0,0 +1,39 @@ +BLOCK_BITS = 128 +BLOCK_BYTES = BLOCK_BITS//8 +NONCE_BYTES = 15 + + +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/python/lilliput/helpers.py b/python/lilliput/helpers.py new file mode 100644 index 0000000..8677f06 --- /dev/null +++ b/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/python/lilliput/lilliput_ae_1.py b/python/lilliput/lilliput_ae_1.py new file mode 100644 index 0000000..0da2a95 --- /dev/null +++ b/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/python/lilliput/lilliput_ae_2.py b/python/lilliput/lilliput_ae_2.py new file mode 100644 index 0000000..61aa86e --- /dev/null +++ b/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/python/lilliput/multiplications.py b/python/lilliput/multiplications.py new file mode 100644 index 0000000..c5f1e44 --- /dev/null +++ b/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/python/lilliput/tbc.py b/python/lilliput/tbc.py new file mode 100644 index 0000000..5291994 --- /dev/null +++ b/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 diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py deleted file mode 100644 index 8064871..0000000 --- a/python/lilliput_ae_1.py +++ /dev/null @@ -1,155 +0,0 @@ -""" - 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 -) -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/python/lilliput_ae_2.py b/python/lilliput_ae_2.py deleted file mode 100644 index 3c0aa2a..0000000 --- a/python/lilliput_ae_2.py +++ /dev/null @@ -1,127 +0,0 @@ -""" - SCT 2 for lilliput ae 2 -""" - -from constants import BLOCK_BYTES -from helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, - TagValidationError, - XorState -) -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/python/multiplications.py b/python/multiplications.py deleted file mode 100644 index c5f1e44..0000000 --- a/python/multiplications.py +++ /dev/null @@ -1,186 +0,0 @@ - -# 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/python/tbc.py b/python/tbc.py deleted file mode 100644 index ca51649..0000000 --- a/python/tbc.py +++ /dev/null @@ -1,178 +0,0 @@ -""" - 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