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/genkat_aead.py | 11 +++++++---- python/lilliput.py | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'python') diff --git a/python/genkat_aead.py b/python/genkat_aead.py index e9f9101..3a69d72 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -46,6 +46,9 @@ def generate_test_vectors(mode, keylen): directory, 'LWC_AEAD_KAT_{keylen}_120.txt'.format(keylen=keylen) ) + nonce = bytes(range(CRYPTO_NPUBBYTES)) + key = bytes(range(keylen//8)) + with open(output_path, 'w') as output: count = 1 @@ -56,16 +59,16 @@ def generate_test_vectors(mode, keylen): msg = bytes(range(mlen)) ad = bytes(range(adlen)) - print_bstr(output, 'Key', bytes(range(keylen//8))) - print_bstr(output, 'Nonce', bytes(range(CRYPTO_NPUBBYTES))) + print_bstr(output, 'Key', key) + print_bstr(output, 'Nonce', nonce) print_bstr(output, 'PT', msg) print_bstr(output, 'AD', ad) - ct, tag = lilliput.mainEnc(msg, ad, mode, keylen) + ct, tag = lilliput.mainEnc(msg, ad, key, nonce, mode, keylen) print_bstr(output, 'CT', ct+tag) - msg2 = lilliput.mainDec(ct, tag, ad, mode, keylen) + msg2 = lilliput.mainDec(ct, tag, ad, key, nonce, mode, keylen) if msg != msg2: raise DecryptionError(msg, msg2, mode, keylen) 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') 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') 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') 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') 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 a1d3889f48a3fffd38a855fc433a9a3d3f649434 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 13:31:50 +0100 Subject: [implem-python] Retrait du main commenté MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/lilliput_tbc.py | 51 -------------------------------------------------- 1 file changed, 51 deletions(-) (limited to 'python') diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 1ed4d8d..78389f9 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -1,7 +1,6 @@ """ Lilliput TBC """ -import random import constants import multiplications @@ -223,53 +222,3 @@ def LilliputTBCDec(tweak, key, cipher) : state_output = LastRoundEGFN(state, RTKs[0], round = ROUNDS - 1) return state_output - -################################################################################ - - -# def main() : -# -# """tweak = [random.randint(0,255) for byte in range(0, number_bytes_tweak)] -# key = [random.randint(0,255) for byte in range(0, number_bytes_key)] -# message = [random.randint(0,255) for byte in range(0, 16)]""" -# #cipher = [204, 93, 118, 73, 153, 116, 241, 228, 56, 160, 234, 207, 42, 199, 19, 147] # null -# #cipher = [104, 79, 113, 74, 255, 166, 160, 78, 195, 74, 93, 105, 73, 157, 113, 228] # order -# #message = [188, 215, 240, 41, 132, 182, 200, 249, 156, 157, 29, 189, 13, 48, 148, 11] -# #cipher = [245, 195, 174, 174, 35, 1, 31, 176, 201, 93, 83, 38, 103, 211, 216, 223] -# #tweak = [168, 67, 243, 16, 129, 17, 28, 132, 223, 248, 46, 250, 144, 144, 38, 33, 125, 141, 67, 18, 42, 179, 210, 77] -# #key = [193, 150, 198, 10, 2, 115, 145, 104, 127, 244, 35, 77, 61, 213, 249, 155] -# global KEY_BITS -# global TWEAK_BITS -# global LANES -# global ROUNDS -# global TWEAKEY_BITS -# global KEY_BYTES -# global TWEAK_BYTES -# global TWEAKEY_BYTES -# KEY_BITS = 256 -# TWEAK_BITS = 128 -# TWEAKEY_BITS = KEY_BITS + TWEAK_BITS -# LANES = int((TWEAKEY_BITS) / LANE_BITS) -# ROUNDS = 42 -# KEY_BYTES = int(KEY_BITS / 8) -# TWEAK_BYTES = int(TWEAK_BITS / 8) -# TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -# -# tweak = [byte for byte in range(0, TWEAK_BYTES)] -# key = [byte for byte in range(0, KEY_BYTES)] -# message = [byte for byte in range(0, BLOCK_BYTES)] -# -# -# -# cipher = LilliputTBCEnc(tweak, key, message) -# print(message) -# print(cipher) -# print(tweak) -# print(key) -# for index,byte in enumerate(cipher) : -# print("%02x "%(cipher[15-index]), end="") -# print() -# #deciphered = LilliputTBCDec(tweak, key, cipher, verbose = 0) -# #print(deciphered) -# -# #main() -- cgit v1.2.3 From 9f999131bc6798e320432e71f3bfbcfbf20dc295 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 13:47:25 +0100 Subject: [implem-python] Confinement de la gestion des tours au module TBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retrait de quelques variables globales par la même occasion. Renommage de "round" en "i" pour 1) coller à la spec 2) éviter le conflit avec le builtin "round". --- python/constants.py | 9 ------ python/lilliput_ae_1.py | 16 +---------- python/lilliput_ae_2.py | 16 ----------- python/lilliput_tbc.py | 73 ++++++++++++++++++++++--------------------------- 4 files changed, 34 insertions(+), 80 deletions(-) (limited to 'python') diff --git a/python/constants.py b/python/constants.py index 02bbc1f..e8d8d03 100644 --- a/python/constants.py +++ b/python/constants.py @@ -2,15 +2,6 @@ BLOCK_BYTES = 16 NONCE_BYTES = 15 -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_ae_1.py b/python/lilliput_ae_1.py index 92cfa6e..9eb5460 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 NONCE_BYTES, rounds +from constants import NONCE_BYTES from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes @@ -13,7 +13,6 @@ TWEAK_BITS = 192 TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANE_BITS = 64 LANES = int((TWEAKEY_BITS) / LANE_BITS) -ROUNDS = 32 BLOCK_BYTES = int(BLOCK_BITS / 8) KEY_BYTES = int(KEY_BITS / 8) @@ -30,12 +29,10 @@ def InitParameters(key_bits) : global TWEAKEY_BITS global TWEAKEY_BYTES global LANES - global ROUNDS KEY_BITS = key_bits TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANES = int((TWEAKEY_BITS) / LANE_BITS) - ROUNDS = rounds(key_bits) KEY_BYTES = int(KEY_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) @@ -230,7 +227,6 @@ def OCB3Enc(A, M, N, key) : M = ArrayToBlockbytesMatrix(M) ltbc.KEY_BITS = KEY_BITS - ltbc.ROUNDS = ROUNDS ltbc.TWEAK_BITS = TWEAK_BITS ltbc.LANES = LANES @@ -239,11 +235,6 @@ def OCB3Enc(A, M, N, key) : ltbc.TWEAK_BYTES = TWEAK_BYTES ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - ltbc.TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - ltbc.RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - ltbc.States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] - - Auth = BuildAuth(A, key) (Final, C) = TreatMessageEnc(M, N, key) tag = XorState(Auth, Final) @@ -264,7 +255,6 @@ def OCB3Dec(A, C, N, tag, key) : C = ArrayToBlockbytesMatrix(C) ltbc.KEY_BITS = KEY_BITS - ltbc.ROUNDS = ROUNDS ltbc.TWEAK_BITS = TWEAK_BITS ltbc.LANES = LANES @@ -273,10 +263,6 @@ def OCB3Dec(A, C, N, tag, key) : ltbc.TWEAK_BYTES = TWEAK_BYTES ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - ltbc.TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - ltbc.RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - ltbc.States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] - Auth = BuildAuth(A, key) (Final, M) = TreatMessageDec(C, N, key) tag2 = XorState(Auth, Final) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index d072935..ed57cdf 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -3,7 +3,6 @@ """ import lilliput_tbc as ltbc -from constants import rounds from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes @@ -13,7 +12,6 @@ TWEAK_BITS = 128 TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANE_BITS = 64 LANES = int((TWEAKEY_BITS) / LANE_BITS) -ROUNDS = 32 BLOCK_BYTES = int(BLOCK_BITS / 8) KEY_BYTES = int(KEY_BITS / 8) @@ -32,12 +30,10 @@ def InitParameters(key_bits) : global TWEAKEY_BITS global TWEAKEY_BYTES global LANES - global ROUNDS KEY_BITS = key_bits TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANES = int((TWEAKEY_BITS) / LANE_BITS) - ROUNDS = rounds(key_bits) KEY_BYTES = int(KEY_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) @@ -227,7 +223,6 @@ def SCT2Enc(A, M, N, key) : M = ArrayToBlockbytesMatrix(M) ltbc.KEY_BITS = KEY_BITS - ltbc.ROUNDS = ROUNDS ltbc.TWEAK_BITS = TWEAK_BITS ltbc.LANES = LANES @@ -236,11 +231,6 @@ def SCT2Enc(A, M, N, key) : ltbc.TWEAK_BYTES = TWEAK_BYTES ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - ltbc.TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - ltbc.RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - ltbc.States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] - - Auth = BuildAuth(A, key) tag = MesssageAuthTag(M, N, Auth, key) C = MessageEncryption(M, N, tag, key) @@ -261,7 +251,6 @@ def SCT2Dec(A, C, N, tag, key) : C = ArrayToBlockbytesMatrix(C) ltbc.KEY_BITS = KEY_BITS - ltbc.ROUNDS = ROUNDS ltbc.TWEAK_BITS = TWEAK_BITS ltbc.LANES = LANES @@ -270,11 +259,6 @@ def SCT2Dec(A, C, N, tag, key) : ltbc.TWEAK_BYTES = TWEAK_BYTES ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - ltbc.TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - ltbc.RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - ltbc.States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] - - M = MessageEncryption(C, N, tag, key) Auth = BuildAuth(A, key) tag2 = MesssageAuthTag(M, N, Auth, key) diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 78389f9..12df2dc 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -10,7 +10,6 @@ TWEAK_BITS = 192 LANE_BITS = 64 LANE_BYTES = LANE_BITS / 8 LANES = int((TWEAK_BITS+KEY_BITS) / LANE_BITS) -ROUNDS = 32 BLOCK_BYTES = int(BLOCK_BITS / 8) TWEAKEY_BITS = KEY_BITS + TWEAK_BITS @@ -29,12 +28,6 @@ MultiplyMR3 = multiplications.MultiplyMR3 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] -# Personnal global variables to check better -TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] -RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] -States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] - - ################################################################################ def BuildTweakey(tweak, key) : @@ -74,26 +67,29 @@ def RoundTweakeySchedule(tweakey) : return tweakey_multiplied ; -def SubTweakeyExtract(tweakey, round) : +def SubTweakeyExtract(tweakey, Ci): subtweakey = [0 for byte in range(0, 8)] for byte in range(0, TWEAKEY_BYTES) : subtweakey[byte % 8] ^= tweakey[byte] - subtweakey[0] ^= round + subtweakey[0] ^= Ci return subtweakey -def TweakeyScheduleWhole(tweakey) : +def TweakeyScheduleWhole(tweakey, r): # store main tweakey in TKs[0] # and corresponding RTKs[0] - TKs[0] = tweakey - RTKs[0] = SubTweakeyExtract(TKs[0], 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 - for round in range(1, ROUNDS) : - TKs[round] = RoundTweakeySchedule(TKs[round - 1]) - RTKs[round] = SubTweakeyExtract(TKs[round], round) ################################################################################ @@ -145,21 +141,21 @@ def PermutationLayerDec(state) : return state_output -def OneRoundEGFNEnc(state, subtweakey, round) : +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, round) : +def LastRoundEGFN(state, subtweakey) : state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) return state_linear -def OneRoundEGFNDec(state, subtweakey, round) : +def OneRoundEGFNDec(state, subtweakey) : state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) state_permutation = PermutationLayerDec(state_linear) @@ -167,58 +163,55 @@ def OneRoundEGFNDec(state, subtweakey, round) : return state_permutation +def _rounds(key_bytes): + rounds = { + 128: 32, + 192: 36, + 256: 42 + } + return rounds[key_bytes*8] + + ################################################################################ # Lilliput TBC def LilliputTBCEnc(tweak, key, message) : - - global TKs - global RTKs - global states - TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] + r = _rounds(len(key)) tweakey = BuildTweakey(tweak, key) - TweakeyScheduleWhole(tweakey) + 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 round in range(0, ROUNDS - 1) : - state_output = OneRoundEGFNEnc(state, RTKs[round], round = round) + 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[ROUNDS - 1], round = ROUNDS - 1) + state_output = LastRoundEGFN(state, RTKs[r-1]) return state_output def LilliputTBCDec(tweak, key, cipher) : - - global TKs - global RTKs - global states - TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] - RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] - States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] + r = _rounds(len(key)) tweakey = BuildTweakey(tweak, key) - TweakeyScheduleWhole(tweakey) + 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 round in range(0, ROUNDS - 1) : - state_output = OneRoundEGFNDec(state, RTKs[ROUNDS - round - 1], round = round) + 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], round = ROUNDS - 1) + state_output = LastRoundEGFN(state, RTKs[0]) return state_output -- cgit v1.2.3 From 864e0bc2a83297bbea069f3fcc6cb333dbc2de19 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 13:51:24 +0100 Subject: [implem-python] Dé-duplication de constantes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/lilliput_tbc.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'python') diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 12df2dc..515a671 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -1,23 +1,20 @@ """ Lilliput TBC """ -import constants +from constants import BLOCK_BYTES, Sbox import multiplications -BLOCK_BITS = 128 KEY_BITS = 128 TWEAK_BITS = 192 LANE_BITS = 64 LANE_BYTES = LANE_BITS / 8 LANES = int((TWEAK_BITS+KEY_BITS) / LANE_BITS) -BLOCK_BYTES = int(BLOCK_BITS / 8) TWEAKEY_BITS = KEY_BITS + TWEAK_BITS KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -Sbox = constants.Sbox MultiplyM = multiplications.MultiplyM MultiplyM2 = multiplications.MultiplyM2 MultiplyM3 = multiplications.MultiplyM3 -- cgit v1.2.3 From dc5efdfce750c02d4f3c4b35d5137342002fd78d Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 14:21:39 +0100 Subject: [implem-python] Retrait des variables globales de lilliput_tbc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On peut tout déduire de len(tweak) / len(key) ; la seule raison d'utiliser autant de constantes en C est que les tableaux se dégradent en pointeurs, donc c'est où les constantes, où une tétrachiée d'arguments. --- python/lilliput_ae_1.py | 28 +++++------------------ python/lilliput_ae_2.py | 32 +++++++------------------- python/lilliput_tbc.py | 61 +++++++++++++++++-------------------------------- 3 files changed, 35 insertions(+), 86 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 9eb5460..4d2d2dc 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -225,18 +225,10 @@ def OCB3Enc(A, M, N, key) : A = ArrayToBlockbytesMatrix(A) M = ArrayToBlockbytesMatrix(M) + K = list(key) - ltbc.KEY_BITS = KEY_BITS - ltbc.TWEAK_BITS = TWEAK_BITS - ltbc.LANES = LANES - - ltbc.TWEAKEY_BITS = TWEAKEY_BITS - ltbc.KEY_BYTES = KEY_BYTES - ltbc.TWEAK_BYTES = TWEAK_BYTES - ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - - Auth = BuildAuth(A, key) - (Final, C) = TreatMessageEnc(M, N, key) + Auth = BuildAuth(A, K) + (Final, C) = TreatMessageEnc(M, N, K) tag = XorState(Auth, Final) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -253,18 +245,10 @@ def OCB3Dec(A, C, N, tag, key) : A = ArrayToBlockbytesMatrix(A) C = ArrayToBlockbytesMatrix(C) + K = list(key) - ltbc.KEY_BITS = KEY_BITS - ltbc.TWEAK_BITS = TWEAK_BITS - ltbc.LANES = LANES - - ltbc.TWEAKEY_BITS = TWEAKEY_BITS - ltbc.KEY_BYTES = KEY_BYTES - ltbc.TWEAK_BYTES = TWEAK_BYTES - ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - - Auth = BuildAuth(A, key) - (Final, M) = TreatMessageDec(C, N, key) + Auth = BuildAuth(A, K) + (Final, M) = TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) if(tag == tag2) : diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index ed57cdf..aeebe27 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -221,19 +221,11 @@ def SCT2Enc(A, M, N, key) : A = ArrayToBlockbytesMatrix(A) M = ArrayToBlockbytesMatrix(M) + K = list(key) - ltbc.KEY_BITS = KEY_BITS - ltbc.TWEAK_BITS = TWEAK_BITS - ltbc.LANES = LANES - - ltbc.TWEAKEY_BITS = TWEAKEY_BITS - ltbc.KEY_BYTES = KEY_BYTES - ltbc.TWEAK_BYTES = TWEAK_BYTES - ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - - Auth = BuildAuth(A, key) - tag = MesssageAuthTag(M, N, Auth, key) - C = MessageEncryption(M, N, tag, key) + Auth = BuildAuth(A, K) + tag = MesssageAuthTag(M, N, Auth, K) + C = MessageEncryption(M, N, tag, K) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -249,19 +241,11 @@ def SCT2Dec(A, C, N, tag, key) : A = ArrayToBlockbytesMatrix(A) C = ArrayToBlockbytesMatrix(C) + K = list(key) - ltbc.KEY_BITS = KEY_BITS - ltbc.TWEAK_BITS = TWEAK_BITS - ltbc.LANES = LANES - - ltbc.TWEAKEY_BITS = TWEAKEY_BITS - ltbc.KEY_BYTES = KEY_BYTES - ltbc.TWEAK_BYTES = TWEAK_BYTES - ltbc.TWEAKEY_BYTES = TWEAKEY_BYTES - - M = MessageEncryption(C, N, tag, key) - Auth = BuildAuth(A, key) - tag2 = MesssageAuthTag(M, N, Auth, key) + M = MessageEncryption(C, N, tag, K) + Auth = BuildAuth(A, K) + tag2 = MesssageAuthTag(M, N, Auth, K) if(tag == tag2) : return BlockbytesMatrixToBytes(M) diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 515a671..0dbfb31 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -4,17 +4,6 @@ from constants import BLOCK_BYTES, Sbox import multiplications -KEY_BITS = 128 -TWEAK_BITS = 192 -LANE_BITS = 64 -LANE_BYTES = LANE_BITS / 8 -LANES = int((TWEAK_BITS+KEY_BITS) / LANE_BITS) - -TWEAKEY_BITS = KEY_BITS + TWEAK_BITS -KEY_BYTES = int(KEY_BITS / 8) -TWEAK_BYTES = int(TWEAK_BITS / 8) -TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) - MultiplyM = multiplications.MultiplyM MultiplyM2 = multiplications.MultiplyM2 MultiplyM3 = multiplications.MultiplyM3 @@ -28,46 +17,38 @@ permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] ################################################################################ def BuildTweakey(tweak, key) : - - tweakey = [0 for byte in range(0, TWEAKEY_BYTES)] - for byte in range(0, TWEAK_BYTES) : - tweakey[byte] = tweak[byte] - - for byte in range(0, KEY_BYTES) : - tweakey[byte + TWEAK_BYTES] = key[byte] - - return tweakey + return tweak+key ############################# +def _lane(TK, j): + return TK[j*8:(j+1)*8] + def RoundTweakeySchedule(tweakey) : + p = len(tweakey)//8 # Multiplication - lanes = [tweakey[word * 8:(word+1) * 8] for word in range(0, LANES)] - tweakey_multiplied = [] - for word in range(0, LANES) : - if word == 0 : - tweakey_multiplied += list(lanes[0]) - elif word == 1 : - tweakey_multiplied += MultiplyM(lanes[1]) - elif word == 2 : - tweakey_multiplied += MultiplyM2(lanes[2]) - elif word == 3 : - tweakey_multiplied += MultiplyM3(lanes[3]) - elif word == 4 : - tweakey_multiplied += MultiplyMR(lanes[4]) - elif word == 5 : - tweakey_multiplied += MultiplyMR2(lanes[5]) - elif word == 6 : - tweakey_multiplied += MultiplyMR3(lanes[6]) - - return tweakey_multiplied ; + alphas = ( + list, # Identity. + MultiplyM, + MultiplyM2, + MultiplyM3, + MultiplyMR, + MultiplyMR2, + MultiplyMR3 + ) + + return [ + byte + for j in range(p) + for byte in alphas[j](_lane(tweakey, j)) + ] def SubTweakeyExtract(tweakey, Ci): subtweakey = [0 for byte in range(0, 8)] - for byte in range(0, TWEAKEY_BYTES) : + for byte in range(len(tweakey)): subtweakey[byte % 8] ^= tweakey[byte] subtweakey[0] ^= Ci -- cgit v1.2.3 From 11a1e33e41858d87692a8b6d726d654e292455ec Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 14:40:42 +0100 Subject: [implem-python] Déclaration de "alphas" dans multiplications.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/lilliput_tbc.py | 25 ++++--------------------- python/multiplications.py | 23 +++++++++++++++++------ 2 files changed, 21 insertions(+), 27 deletions(-) (limited to 'python') diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 0dbfb31..fbd1fb3 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -2,14 +2,8 @@ Lilliput TBC """ from constants import BLOCK_BYTES, Sbox -import multiplications +from multiplications import ALPHAS -MultiplyM = multiplications.MultiplyM -MultiplyM2 = multiplications.MultiplyM2 -MultiplyM3 = multiplications.MultiplyM3 -MultiplyMR = multiplications.MultiplyMR -MultiplyMR2 = multiplications.MultiplyMR2 -MultiplyMR3 = multiplications.MultiplyMR3 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] @@ -27,22 +21,11 @@ def _lane(TK, j): def RoundTweakeySchedule(tweakey) : p = len(tweakey)//8 - # Multiplication - alphas = ( - list, # Identity. - MultiplyM, - MultiplyM2, - MultiplyM3, - MultiplyMR, - MultiplyMR2, - MultiplyMR3 + multiplied_lanes = ( + ALPHAS[j](_lane(tweakey, j)) for j in range(p) ) - return [ - byte - for j in range(p) - for byte in alphas[j](_lane(tweakey, j)) - ] + return [byte for lane in multiplied_lanes for byte in lane] def SubTweakeyExtract(tweakey, Ci): diff --git a/python/multiplications.py b/python/multiplications.py index e753c68..7babd50 100644 --- a/python/multiplications.py +++ b/python/multiplications.py @@ -1,6 +1,6 @@ # Multiply by matrix M -def MultiplyM(lane) : +def _multiplyM(lane) : multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[6] << 2) & 0xff) @@ -9,7 +9,7 @@ def MultiplyM(lane) : return multiplied_lane -def MultiplyM2(lane) : +def _multiplyM2(lane) : multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[5] << 2) & 0xff) @@ -35,7 +35,7 @@ def MultiplyM2(lane) : return multiplied_lane -def MultiplyM3(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) @@ -86,7 +86,7 @@ def MultiplyM3(lane) : return multiplied_lane -def MultiplyMR(lane) : +def _multiplyMR(lane) : multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff) @@ -96,7 +96,7 @@ def MultiplyMR(lane) : return multiplied_lane -def MultiplyMR2(lane) : +def _multiplyMR2(lane) : multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)] multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff) @@ -120,7 +120,7 @@ def MultiplyMR2(lane) : return multiplied_lane -def MultiplyMR3(lane) : +def _multiplyMR3(lane) : multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)] multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff) @@ -173,3 +173,14 @@ def MultiplyMR3(lane) : 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 +) -- cgit v1.2.3 From 99c63c6699e6da600348a476ebbc52b783002d1b Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 14:47:10 +0100 Subject: [implem-python] Renommage de variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pour que le lien soit plus facile à faire avec la spec. --- python/lilliput_tbc.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'python') diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index fbd1fb3..418d083 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -29,19 +29,19 @@ def RoundTweakeySchedule(tweakey) : def SubTweakeyExtract(tweakey, Ci): - subtweakey = [0 for byte in range(0, 8)] + RTKi = [0]*8 - for byte in range(len(tweakey)): - subtweakey[byte % 8] ^= tweakey[byte] + for j, byte in enumerate(tweakey): + RTKi[j%8] ^= byte - subtweakey[0] ^= Ci + RTKi[0] ^= Ci - return subtweakey + return RTKi def TweakeyScheduleWhole(tweakey, r): # store main tweakey in TKs[0] - # and corresponding RTKs[0] + # and corresponding round tweakey in RTKs[0] TKs = [tweakey] RTKs = [SubTweakeyExtract(TKs[0], 0)] -- cgit v1.2.3 From 6bb0c4369ec43c6c3a83e58c1906f4c1f0d3a0dd Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 15:42:29 +0100 Subject: [implem-python] Retrait de A_BITS/M_BITS (1/2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En passant : - remplacement de paramètres 0/1 par des booléens/des enums (pour TweakMessage en particulier, ça simplifie pas mal la logique) - construction de M (resp. C pour le déchiffrement) au fur et à mesure, i.e. avec des listes vides, plutôt qu'en pré-allouant des tableaux potentiellement trop gros en cas de padding --- python/constants.py | 3 +- python/lilliput_ae_1.py | 119 ++++++++++++++++++++++-------------------------- 2 files changed, 57 insertions(+), 65 deletions(-) (limited to 'python') diff --git a/python/constants.py b/python/constants.py index e8d8d03..764febb 100644 --- a/python/constants.py +++ b/python/constants.py @@ -1,4 +1,5 @@ -BLOCK_BYTES = 16 +BLOCK_BITS = 128 +BLOCK_BYTES = BLOCK_BITS//8 NONCE_BYTES = 15 diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 4d2d2dc..6ab0cc3 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -3,25 +3,21 @@ """ import lilliput_tbc as ltbc -from constants import NONCE_BYTES +from constants import BLOCK_BITS, BLOCK_BYTES, NONCE_BYTES +from enum import Enum from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes -BLOCK_BITS = 128 KEY_BITS = 128 TWEAK_BITS = 192 TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANE_BITS = 64 LANES = int((TWEAKEY_BITS) / LANE_BITS) -BLOCK_BYTES = int(BLOCK_BITS / 8) KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -A_BITS = BLOCK_BITS -M_BITS = BLOCK_BITS - def InitParameters(key_bits) : global KEY_BITS @@ -83,7 +79,7 @@ def LowPart(array, number_bits) : ############################################################################### -def TweakAssociatedData(i, padded = 0) : +def TweakAssociatedData(i, padded) : tweak = [0 for byte in range(0, TWEAK_BYTES)] mask = 0xff @@ -93,7 +89,7 @@ def TweakAssociatedData(i, padded = 0) : mask = (0xf << (8 * (TWEAK_BYTES - 1))) tweak[TWEAK_BYTES - 1] = (i & mask) >> ((TWEAK_BYTES - 1) * 8) - if padded == 0 : + if not padded: tweak[TWEAK_BYTES - 1] |= 0x20 else : tweak[TWEAK_BYTES - 1] |= 0x60 @@ -102,22 +98,22 @@ def TweakAssociatedData(i, padded = 0) : def BuildAuth(A, key) : Auth = [0 for byte in range(0, BLOCK_BYTES)] - l_a = int(A_BITS / BLOCK_BITS) - if int(A_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 + l_a = len(A)//BLOCK_BYTES + + padding_bytes = len(A)%BLOCK_BYTES + + A = ArrayToBlockbytesMatrix(A) for i in range(0, l_a) : - tweak = TweakAssociatedData(i, padded = 0) + tweak = TweakAssociatedData(i, padded=False) enc = ltbc.LilliputTBCEnc(tweak, key, A[i]) Auth = XorState(Auth, enc) - if (A_BITS % BLOCK_BITS) == 0 : + if padding_bytes == 0: return Auth - tweak = TweakAssociatedData(l_a, padded = 1) - ad_padded = Padding10LSB(A[l_a], (A_BITS % BLOCK_BITS)) + tweak = TweakAssociatedData(l_a, padded=True) + ad_padded = Padding10LSB(A[l_a], padding_bytes*8) enc = ltbc.LilliputTBCEnc(tweak, key, ad_padded) Auth = XorState(Auth, enc) @@ -125,7 +121,14 @@ def BuildAuth(A, key) : ################################################################################ -def TweakMessage(N, j, null = 0, padded = 0, final_padded = 0) : +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 @@ -135,44 +138,38 @@ def TweakMessage(N, j, null = 0, padded = 0, final_padded = 0) : for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1) : tweak[byte] = (j >> (8 * byte)) & 0xff - if null == 1 : - tweak[TWEAK_BYTES - 1] |= 0x10 - if padded == 1 : - tweak[TWEAK_BYTES - 1] |= 0x40 - if final_padded == 1 : - tweak[TWEAK_BYTES - 1] |= 0x50 + tweak[-1] |= padding.value<<4 return tweak -def TreatMessageEnc(M, N, key) : +def TreatMessageEnc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] - l = int(M_BITS / BLOCK_BITS) - if int(M_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES - C = [[0 for byte in range(0, BLOCK_BYTES)] for j in range(0, l + will_padd)] + M = ArrayToBlockbytesMatrix(M) + C = [] - for j in range(0, l) : + for j in range(0, l): checksum = XorState(checksum, M[j]) - tweak = TweakMessage(N, j, padded = 0) - C[j] = ltbc.LilliputTBCEnc(tweak, key, M[j]) + tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + C.append(ltbc.LilliputTBCEnc(tweak, key, M[j])) - if will_padd == 0 : - tweak = TweakMessage(N, l, null = 1) + if padding_bytes == 0: + tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = ltbc.LilliputTBCEnc(tweak, key, checksum) - else : - m_padded = Padding10LSB(M[l], M_BITS % BLOCK_BITS) + else: + m_padded = Padding10LSB(M[l], padding_bytes*8) checksum = XorState(checksum, m_padded) - tweak = TweakMessage(N, l, padded = 1) + tweak = TweakMessage(N, l, _MessageTweak.PAD) pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, M_BITS % BLOCK_BITS) - C[l] = XorState(M[l], lower_part) - tweak_final = TweakMessage(N, l+1, final_padded = 1) + + lower_part = LowPart(pad, padding_bytes*8) + C.append(XorState(M[l], lower_part)) + tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) Final = ltbc.LilliputTBCEnc(tweak_final, key, checksum) return (Final, C) @@ -181,32 +178,30 @@ def TreatMessageEnc(M, N, key) : def TreatMessageDec(C, N, key) : checksum = [0 for byte in range(0, BLOCK_BYTES)] - l = int(M_BITS / BLOCK_BITS) - if int(M_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 + l = len(C)//BLOCK_BYTES + padding_bytes = len(C)%BLOCK_BYTES - M = [[0 for byte in range(0, BLOCK_BYTES)] for j in range(0, l + will_padd)] + C = ArrayToBlockbytesMatrix(C) + M = [] - for j in range(0, l) : - tweak = TweakMessage(N, j, padded = 0) - M[j] = ltbc.LilliputTBCDec(tweak, key, C[j]) + for j in range(0, l): + tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + M.append(ltbc.LilliputTBCDec(tweak, key, C[j])) checksum = XorState(checksum, M[j]) - - if will_padd == 0 : - tweak = TweakMessage(N, l, null = 1) + if padding_bytes == 0: + tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = ltbc.LilliputTBCEnc(tweak, key, checksum) - else : - tweak = TweakMessage(N, l, padded = 1) + else: + tweak = TweakMessage(N, l, _MessageTweak.PAD) pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, M_BITS % BLOCK_BITS) - M[l] = XorState(C[l], lower_part) - m_padded = Padding10LSB(M[l], M_BITS % BLOCK_BITS) + lower_part = LowPart(pad, padding_bytes*8) + M.append(XorState(C[l], lower_part)) + + m_padded = Padding10LSB(M[l], padding_bytes*8) checksum = XorState(checksum, m_padded) - tweak_final = TweakMessage(N, l+1, final_padded = 1) + tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) Final = ltbc.LilliputTBCEnc(tweak_final, key, checksum) return (Final, M) @@ -223,8 +218,6 @@ def OCB3Enc(A, M, N, key) : A_BITS = len(A)*8 M_BITS = len(M)*8 - A = ArrayToBlockbytesMatrix(A) - M = ArrayToBlockbytesMatrix(M) K = list(key) Auth = BuildAuth(A, K) @@ -243,8 +236,6 @@ def OCB3Dec(A, C, N, tag, key) : A_BITS = len(A)*8 M_BITS = len(C)*8 - A = ArrayToBlockbytesMatrix(A) - C = ArrayToBlockbytesMatrix(C) K = list(key) Auth = BuildAuth(A, K) -- cgit v1.2.3 From 5f19c30d2fee032b8fd07ec5bfe40f6599bf3eb7 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 15:48:14 +0100 Subject: [implem-python] Suppression d'affectations redondantes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aurais dû les enlever dans 23d2fea280302c01a818e46e4a43c884eac03865. --- python/lilliput_ae_2.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index aeebe27..161598e 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -25,8 +25,6 @@ M_BITS = BLOCK_BITS def InitParameters(key_bits) : global KEY_BITS global KEY_BYTES - global TWEAK_BITS - global TWEAK_BYTES global TWEAKEY_BITS global TWEAKEY_BYTES global LANES -- cgit v1.2.3 From c55465fc5cbe004bdca1cbd6990fed3c798d5f1b Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 15:51:31 +0100 Subject: [implem-python] Retrait de A_BITS/M_BITS (1.1/2) --- python/lilliput_ae_1.py | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 6ab0cc3..c9a731e 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -212,12 +212,6 @@ def TreatMessageDec(C, N, key) : def OCB3Enc(A, M, N, key) : InitParameters(len(key)*8) - global A_BITS - global M_BITS - - A_BITS = len(A)*8 - M_BITS = len(M)*8 - K = list(key) Auth = BuildAuth(A, K) @@ -230,12 +224,6 @@ def OCB3Enc(A, M, N, key) : def OCB3Dec(A, C, N, tag, key) : InitParameters(len(key)*8) - global A_BITS - global M_BITS - - A_BITS = len(A)*8 - M_BITS = len(C)*8 - K = list(key) Auth = BuildAuth(A, K) -- cgit v1.2.3 From 52c8c1a2b72e11f8814215034139e8991f1aeb63 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:11:26 +0100 Subject: [implem-python] Extraction de fonctions communes aux deux modes --- python/helpers.py | 66 ++++++++++++++++++++++++++++++++++++++++++- python/lilliput_ae_1.py | 75 ++++++++----------------------------------------- 2 files changed, 77 insertions(+), 64 deletions(-) (limited to 'python') diff --git a/python/helpers.py b/python/helpers.py index 34949a4..3d741b0 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -1,4 +1,5 @@ -from constants import BLOCK_BYTES +from constants import BLOCK_BITS, BLOCK_BYTES +from lilliput_tbc import LilliputTBCEnc def ArrayToBlockbytesMatrix(array) : @@ -23,3 +24,66 @@ def ArrayToBlockbytesMatrix(array) : def BlockbytesMatrixToBytes(matrix): return bytes(byte for block in matrix for byte in block) + +def XorState(state1, state2): + return list( + s1^s2 for (s1, s2) in zip(state1, state2) + ) + + +def Padding10LSB(array, number_bits): + shifted = 0 + for byte in range(0, len(array)): + shifted |= (array[byte] << (8 * byte)) + shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff + + padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1)) + + array_padded = [0 for byte in range(0, BLOCK_BYTES)] + for byte in range(0, BLOCK_BYTES): + array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte) + + return array_padded + + +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 + + padding_bytes = len(A)%BLOCK_BYTES + + A = ArrayToBlockbytesMatrix(A) + + for i in range(0, l_a): + tweak = _tweakAssociatedData(t, i, padded=False) + enc = LilliputTBCEnc(tweak, key, A[i]) + Auth = XorState(Auth, enc) + + if padding_bytes == 0: + return Auth + + tweak = _tweakAssociatedData(t, l_a, padded=True) + ad_padded = Padding10LSB(A[l_a], padding_bytes*8) + enc = LilliputTBCEnc(tweak, key, ad_padded) + Auth = XorState(Auth, enc) + + return Auth diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index c9a731e..8cf55bb 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -2,10 +2,17 @@ OCB 3 for lilliput ae i """ -import lilliput_tbc as ltbc -from constants import BLOCK_BITS, BLOCK_BYTES, NONCE_BYTES from enum import Enum -from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes + +import lilliput_tbc as ltbc +from constants import BLOCK_BYTES, NONCE_BYTES +from helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + XorState +) KEY_BITS = 128 @@ -35,26 +42,6 @@ def InitParameters(key_bits) : ############################################################################### -def XorState(state1, state2) : - state_output = [state1[byte] ^ state2[byte] for byte in range(0, len(state1))] - return state_output - - -def Padding10LSB(array, number_bits) : - shifted = 0 - for byte in range(0, len(array)) : - shifted |= (array[byte] << (8 * byte)) - shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff - - padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1)) - - array_padded = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES) : - array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte) - - return array_padded - - def LowPart(array, number_bits) : shifted = 0 for byte in range(0, len(array)) : @@ -79,45 +66,7 @@ def LowPart(array, number_bits) : ############################################################################### -def TweakAssociatedData(i, padded) : - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - mask = 0xff - for byte in range(0, TWEAK_BYTES - 1) : - tweak[byte] = (i & mask) >> (byte * 8) - mask = mask << 8 - - mask = (0xf << (8 * (TWEAK_BYTES - 1))) - tweak[TWEAK_BYTES - 1] = (i & mask) >> ((TWEAK_BYTES - 1) * 8) - if not padded: - tweak[TWEAK_BYTES - 1] |= 0x20 - else : - tweak[TWEAK_BYTES - 1] |= 0x60 - return tweak - - -def BuildAuth(A, key) : - Auth = [0 for byte in range(0, BLOCK_BYTES)] - l_a = len(A)//BLOCK_BYTES - - padding_bytes = len(A)%BLOCK_BYTES - - A = ArrayToBlockbytesMatrix(A) - - for i in range(0, l_a) : - tweak = TweakAssociatedData(i, padded=False) - enc = ltbc.LilliputTBCEnc(tweak, key, A[i]) - Auth = XorState(Auth, enc) - - if padding_bytes == 0: - return Auth - - tweak = TweakAssociatedData(l_a, padded=True) - ad_padded = Padding10LSB(A[l_a], padding_bytes*8) - enc = ltbc.LilliputTBCEnc(tweak, key, ad_padded) - Auth = XorState(Auth, enc) - return Auth ################################################################################ @@ -214,7 +163,7 @@ def OCB3Enc(A, M, N, key) : K = list(key) - Auth = BuildAuth(A, K) + Auth = BuildAuth(TWEAK_BITS, A, K) (Final, C) = TreatMessageEnc(M, N, K) tag = XorState(Auth, Final) @@ -226,7 +175,7 @@ def OCB3Dec(A, C, N, tag, key) : K = list(key) - Auth = BuildAuth(A, K) + Auth = BuildAuth(TWEAK_BITS, A, K) (Final, M) = TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) -- cgit v1.2.3 From 417ac09668ea124245dbac0084608d9c396f5a76 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:15:08 +0100 Subject: [implem-python] Retrait de A_BITS/M_BITS (1.5/2) --- python/lilliput_ae_2.py | 83 ++++++------------------------------------------- 1 file changed, 10 insertions(+), 73 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 161598e..164c3df 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -3,7 +3,14 @@ """ import lilliput_tbc as ltbc -from helpers import ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes +from constants import BLOCK_BITS, BLOCK_BYTES +from helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + XorState +) BLOCK_BITS = 128 @@ -18,7 +25,6 @@ KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -A_BITS = BLOCK_BITS M_BITS = BLOCK_BITS @@ -38,25 +44,6 @@ def InitParameters(key_bits) : ############################################################################### -def XorState(state1, state2) : - state_output = [state1[byte] ^ state2[byte] for byte in range(0, len(state1))] - return state_output - -def Padding10LSB(array, number_bits) : - shifted = 0 - for byte in range(0, len(array)) : - shifted |= (array[byte] << (8 * byte)) - shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff - - padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1)) - - array_padded = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES) : - array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte) - - return array_padded - - def LowPart(array, number_bits) : shifted = 0 for byte in range(0, len(array)) : @@ -79,48 +66,6 @@ def LowPart(array, number_bits) : return lower_part_byte -############################################################################### - -def TweakAssociatedData(i, padded = 0) : - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - mask = 0xff - for byte in range(0, TWEAK_BYTES - 1) : - tweak[byte] = (i & mask) >> (byte * 8) - mask = mask << 8 - - mask = (0xf << (8 * (TWEAK_BYTES - 1))) - tweak[TWEAK_BYTES - 1] = (i & mask) >> ((TWEAK_BYTES - 1) * 8) - if padded == 0 : - tweak[TWEAK_BYTES - 1] |= 0x20 - else : - tweak[TWEAK_BYTES - 1] |= 0x60 - return tweak - - -def BuildAuth(A, key) : - Auth = [0 for byte in range(0, BLOCK_BYTES)] - l_a = int(A_BITS / BLOCK_BITS) - if int(A_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 - - for i in range(0, l_a) : - tweak = TweakAssociatedData(i, padded = 0) - enc = ltbc.LilliputTBCEnc(tweak, key, A[i]) - Auth = XorState(Auth, enc) - - if (A_BITS % BLOCK_BITS) == 0 : - return Auth - - tweak = TweakAssociatedData(l_a, padded = 1) - ad_padded = Padding10LSB(A[l_a], (A_BITS % BLOCK_BITS)) - enc = ltbc.LilliputTBCEnc(tweak, key, ad_padded) - Auth = XorState(Auth, enc) - - return Auth - ################################################################################ def TweakTag(j, padded = 0) : @@ -211,17 +156,13 @@ def MessageEncryption(M, N, tag, key) : def SCT2Enc(A, M, N, key) : InitParameters(len(key)*8) - global A_BITS global M_BITS - - A_BITS = len(A)*8 M_BITS = len(M)*8 - A = ArrayToBlockbytesMatrix(A) M = ArrayToBlockbytesMatrix(M) K = list(key) - Auth = BuildAuth(A, K) + Auth = BuildAuth(TWEAK_BITS, A, K) tag = MesssageAuthTag(M, N, Auth, K) C = MessageEncryption(M, N, tag, K) @@ -231,18 +172,14 @@ def SCT2Enc(A, M, N, key) : def SCT2Dec(A, C, N, tag, key) : InitParameters(len(key)*8) - global A_BITS global M_BITS - - A_BITS = len(A)*8 M_BITS = len(C)*8 - A = ArrayToBlockbytesMatrix(A) C = ArrayToBlockbytesMatrix(C) K = list(key) M = MessageEncryption(C, N, tag, K) - Auth = BuildAuth(A, K) + Auth = BuildAuth(TWEAK_BITS, A, K) tag2 = MesssageAuthTag(M, N, Auth, K) if(tag == tag2) : -- cgit v1.2.3 From a7abd1a33ca68e2e2db59332b612db69ffb31496 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:30:27 +0100 Subject: [implem-python] Gestion de l'échec de déchiffrement dans genkat_aead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ce serait mieux si l'API renvoyait une exception… Un jour. --- python/genkat_aead.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/genkat_aead.py b/python/genkat_aead.py index 6d7ca51..5bce05f 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -28,8 +28,8 @@ class DecryptionError(Exception): def __str__(self): return '({s.mode} / {s.keylen}) Expected {exp}; got {act}'.format( s=self, - exp=bstr(self.expected), - act=bstr(self.actual) + exp=bstr(self.expected) if self.expected is not None else 'NONE', + act=bstr(self.actual) if self.actual is not None else 'NONE' ) -- cgit v1.2.3 From 57ccbe8a1589a275d44c0c1de1fe7122f70b105c Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:35:02 +0100 Subject: [implem-python] Retrait de A_BITS/M_BITS (2/2) --- python/lilliput_ae_2.py | 56 +++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 35 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 164c3df..720e1aa 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -13,20 +13,16 @@ from helpers import ( ) -BLOCK_BITS = 128 KEY_BITS = 128 TWEAK_BITS = 128 TWEAKEY_BITS = KEY_BITS + TWEAK_BITS LANE_BITS = 64 LANES = int((TWEAKEY_BITS) / LANE_BITS) -BLOCK_BYTES = int(BLOCK_BITS / 8) KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) -M_BITS = BLOCK_BITS - def InitParameters(key_bits) : global KEY_BITS @@ -68,14 +64,14 @@ def LowPart(array, number_bits) : ################################################################################ -def TweakTag(j, padded = 0) : +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 == 1 : + if padded: tweak[TWEAK_BYTES - 1] |= 0x40 return tweak @@ -103,22 +99,20 @@ def AddTagJ(tag, j) : def MesssageAuthTag(M, N, Auth, key) : - l = int(M_BITS / BLOCK_BITS) - if int(M_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES tag = list(Auth) + M = ArrayToBlockbytesMatrix(M) for j in range(0, l) : - tweak = TweakTag(j, padded = 0) + tweak = TweakTag(j, False) encryption = ltbc.LilliputTBCEnc(tweak, key, M[j]) tag = XorState(tag, encryption) - if will_padd == 1 : - tweak = TweakTag(l, padded = 1) - m_padded = Padding10LSB(M[l], M_BITS % BLOCK_BITS) + if padding_bytes > 0 : + tweak = TweakTag(l, True) + m_padded = Padding10LSB(M[l], 8*padding_bytes) encryption = ltbc.LilliputTBCEnc(tweak, key, m_padded) tag = XorState(tag, encryption) @@ -130,25 +124,23 @@ def MesssageAuthTag(M, N, Auth, key) : def MessageEncryption(M, N, tag, key) : - l = int(M_BITS / BLOCK_BITS) - if int(M_BITS % BLOCK_BITS) > 0 : - will_padd = 1 - else : - will_padd = 0 + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES - C = [[0 for byte in range(0, 16)] for j in range(0, l + will_padd)] + M = ArrayToBlockbytesMatrix(M) + C = [] for j in range(0, l) : tweak = AddTagJ(tag, j) padded_nounce = list(N) + [0x00] encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nounce) - C[j] = XorState(M[j], encryption) + C.append(XorState(M[j], encryption)) - if will_padd : + if padding_bytes > 0: tweak = AddTagJ(tag, l) padded_nounce = list(N) + [0x00] encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nounce) - C[l] = XorState(M[l], encryption) + C.append(XorState(M[l], encryption)) return C @@ -156,10 +148,6 @@ def MessageEncryption(M, N, tag, key) : def SCT2Enc(A, M, N, key) : InitParameters(len(key)*8) - global M_BITS - M_BITS = len(M)*8 - - M = ArrayToBlockbytesMatrix(M) K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -172,15 +160,13 @@ def SCT2Enc(A, M, N, key) : def SCT2Dec(A, C, N, tag, key) : InitParameters(len(key)*8) - global M_BITS - M_BITS = len(C)*8 - - C = ArrayToBlockbytesMatrix(C) K = list(key) - M = MessageEncryption(C, N, tag, K) + M = BlockbytesMatrixToBytes( + MessageEncryption(C, N, tag, K) + ) Auth = BuildAuth(TWEAK_BITS, A, K) tag2 = MesssageAuthTag(M, N, Auth, K) - if(tag == tag2) : - return BlockbytesMatrixToBytes(M) + if tag == tag2: + return M -- cgit v1.2.3 From 12585a5a0f2faca9c6ab2490bb50b34450876538 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 14 Mar 2019 16:45:35 +0100 Subject: [implem-python] Retrait des constantes globales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et des fonctions d'initialisation. Et d'une fonction non-utilisée dans le mode SCT-2. --- python/lilliput_ae_1.py | 35 +------------------------------- python/lilliput_ae_2.py | 53 +------------------------------------------------ 2 files changed, 2 insertions(+), 86 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 8cf55bb..9de753c 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -15,32 +15,9 @@ from helpers import ( ) -KEY_BITS = 128 TWEAK_BITS = 192 -TWEAKEY_BITS = KEY_BITS + TWEAK_BITS -LANE_BITS = 64 -LANES = int((TWEAKEY_BITS) / LANE_BITS) +TWEAK_BYTES = TWEAK_BITS//8 -KEY_BYTES = int(KEY_BITS / 8) -TWEAK_BYTES = int(TWEAK_BITS / 8) -TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) - - -def InitParameters(key_bits) : - global KEY_BITS - global KEY_BYTES - global TWEAKEY_BITS - global TWEAKEY_BYTES - global LANES - - KEY_BITS = key_bits - TWEAKEY_BITS = KEY_BITS + TWEAK_BITS - LANES = int((TWEAKEY_BITS) / LANE_BITS) - KEY_BYTES = int(KEY_BITS / 8) - TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) - - -############################################################################### def LowPart(array, number_bits) : shifted = 0 @@ -64,11 +41,6 @@ def LowPart(array, number_bits) : return lower_part_byte -############################################################################### - - - -################################################################################ class _MessageTweak(Enum): BLOCK = 0b000 @@ -156,11 +128,8 @@ def TreatMessageDec(C, N, key) : return (Final, M) - ################################################################################ def OCB3Enc(A, M, N, key) : - InitParameters(len(key)*8) - K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -171,8 +140,6 @@ def OCB3Enc(A, M, N, key) : def OCB3Dec(A, C, N, tag, key) : - InitParameters(len(key)*8) - K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 720e1aa..cb1d1c4 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -13,56 +13,9 @@ from helpers import ( ) -KEY_BITS = 128 TWEAK_BITS = 128 -TWEAKEY_BITS = KEY_BITS + TWEAK_BITS -LANE_BITS = 64 -LANES = int((TWEAKEY_BITS) / LANE_BITS) +TWEAK_BYTES = TWEAK_BITS//8 -KEY_BYTES = int(KEY_BITS / 8) -TWEAK_BYTES = int(TWEAK_BITS / 8) -TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) - - -def InitParameters(key_bits) : - global KEY_BITS - global KEY_BYTES - global TWEAKEY_BITS - global TWEAKEY_BYTES - global LANES - - KEY_BITS = key_bits - TWEAKEY_BITS = KEY_BITS + TWEAK_BITS - LANES = int((TWEAKEY_BITS) / LANE_BITS) - KEY_BYTES = int(KEY_BITS / 8) - TWEAKEY_BYTES = int(TWEAKEY_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_padd = 0 - if (number_bits % 8) != 0 : - will_padd = 1 - - lower_part_byte = [0 for byte in range(0, int(number_bits / 8) + will_padd)] - for byte in range(0, int(number_bits / 8) + will_padd) : - lower_part_byte[byte] = lower_part & 0xff - lower_part = lower_part >> 8 - - return lower_part_byte - -################################################################################ def TweakTag(j, padded): tweak = [0 for byte in range(0, TWEAK_BYTES)] @@ -146,8 +99,6 @@ def MessageEncryption(M, N, tag, key) : ################################################################################ def SCT2Enc(A, M, N, key) : - InitParameters(len(key)*8) - K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -158,8 +109,6 @@ def SCT2Enc(A, M, N, key) : def SCT2Dec(A, C, N, tag, key) : - InitParameters(len(key)*8) - K = list(key) M = BlockbytesMatrixToBytes( -- 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') 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') 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 7178069e072dc0c922a3bf0263746f82020566ea Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 15 Mar 2019 07:58:01 +0100 Subject: [implem-python] Correction d'une typo --- python/lilliput_ae_2.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index f455f43..624fd93 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -85,14 +85,14 @@ def MessageEncryption(M, N, tag, key) : for j in range(0, l) : tweak = AddTagJ(tag, j) - padded_nounce = list(N) + [0x00] - encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nounce) + padded_nonce = list(N) + [0x00] + encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) C.append(XorState(M[j], encryption)) if padding_bytes > 0: tweak = AddTagJ(tag, l) - padded_nounce = list(N) + [0x00] - encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nounce) + padded_nonce = list(N) + [0x00] + encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) C.append(XorState(M[l], encryption)) return C -- cgit v1.2.3 From 57952a7dd9d9c586dcac84e46987d15d49674774 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 15 Mar 2019 08:11:22 +0100 Subject: [implem-python] Simplification d'une compréhension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/helpers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'python') diff --git a/python/helpers.py b/python/helpers.py index 3d741b0..45c48c9 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -26,9 +26,7 @@ def BlockbytesMatrixToBytes(matrix): def XorState(state1, state2): - return list( - s1^s2 for (s1, s2) in zip(state1, state2) - ) + return [s1^s2 for (s1, s2) in zip(state1, state2)] def Padding10LSB(array, number_bits): -- cgit v1.2.3 From aaf0d2c49f343e909dc69b487056ca31238ffabf Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 21 Mar 2019 16:04:16 +0100 Subject: [implem-python] Nettoyage PEP8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - espaces avant ':' - espaces en trop après ',' - parenthèses dans les if - levée d'exception plutôt que 'return None' implicite Simplification de genkat_aead.py grâce à l'exception levée par le module. --- python/constants.py | 66 ++++++++++++++++++++++++----------------------- python/genkat_aead.py | 26 ++----------------- python/helpers.py | 23 +++++++++++++---- python/lilliput_ae_1.py | 31 ++++++++++++---------- python/lilliput_ae_2.py | 49 +++++++++++++++++++---------------- python/lilliput_tbc.py | 54 +++++++++++++++++++------------------- python/multiplications.py | 12 ++++----- 7 files changed, 131 insertions(+), 130 deletions(-) (limited to 'python') diff --git a/python/constants.py b/python/constants.py index 764febb..c61dfe0 100644 --- a/python/constants.py +++ b/python/constants.py @@ -3,35 +3,37 @@ BLOCK_BYTES = BLOCK_BITS//8 NONCE_BYTES = 15 -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] +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/genkat_aead.py b/python/genkat_aead.py index daa48f8..8b38d9b 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -16,27 +16,8 @@ MODE_SUFFIXES = { } -def bstr(buf): - return ''.join('{:02X}'.format(b) for b in buf) - - def print_bstr(output, label, buf): - print('{l} = {b}'.format(l=label, b=bstr(buf)), file=output) - - -class DecryptionError(Exception): - def __init__(self, expected, actual, mode, keylen): - self.expected = expected - self.actual = actual - self.mode = mode - self.keylen = keylen - - def __str__(self): - return '({s.mode} / {s.keylen}) Expected {exp}; got {act}'.format( - s=self, - exp=bstr(self.expected) if self.expected is not None else 'NONE', - act=bstr(self.actual) if self.actual is not None else 'NONE' - ) + print('{l} = {b}'.format(l=label, b=buf.hex().upper()), file=output) def generate_test_vectors(mode, keylen): @@ -74,10 +55,7 @@ def generate_test_vectors(mode, keylen): print_bstr(output, 'CT', ct+tag) - msg2 = decrypt(ct, tag, ad, key, nonce, mode) - - if msg != msg2: - raise DecryptionError(msg, msg2, mode, keylen) + decrypt(ct, tag, ad, key, nonce, mode) count+=1 diff --git a/python/helpers.py b/python/helpers.py index 45c48c9..b02bea4 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -2,20 +2,20 @@ from constants import BLOCK_BITS, BLOCK_BYTES from lilliput_tbc import LilliputTBCEnc -def ArrayToBlockbytesMatrix(array) : +def ArrayToBlockbytesMatrix(array): length = len(array) pad = 0 - if(length % BLOCK_BYTES == 0) : + if length % BLOCK_BYTES == 0: number_blocks = int(length / BLOCK_BYTES) - else : + 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) : + if pad == 1: matrix.append([0] * (length % BLOCK_BYTES)) - for byte in range(0, length) : + for byte in range(0, length): matrix[int(byte / BLOCK_BYTES)][byte % BLOCK_BYTES] = array[byte] return matrix @@ -85,3 +85,16 @@ def BuildAuth(t, A, key): 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_ae_1.py b/python/lilliput_ae_1.py index 8b618d9..9aad3a6 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -11,6 +11,7 @@ from helpers import ( BlockbytesMatrixToBytes, BuildAuth, Padding10LSB, + TagValidationError, XorState ) @@ -19,23 +20,23 @@ 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)) : + for byte in range(0, len(array)): shifted |= (array[byte] << (8 * byte)) mask = 0 - for bit in range(0, number_bits) : + for bit in range(0, number_bits): mask |= (0x1 << bit) lower_part = shifted & mask will_padd = 0 - if (number_bits % 8) != 0 : + if number_bits % 8 != 0: will_padd = 1 - lower_part_byte = [0 for byte in range(0, int(number_bits / 8) + will_padd)] - for byte in range(0, int(number_bits / 8) + will_padd) : + lower_part_byte = [0 for byte in range(0, int(number_bits / 8) + will_padd)] + for byte in range(0, int(number_bits / 8) + will_padd): lower_part_byte[byte] = lower_part & 0xff lower_part = lower_part >> 8 @@ -50,13 +51,13 @@ class _MessageTweak(Enum): def TweakMessage(N, j, padding): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(NONCE_BYTES-1, -1, -1) : + 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) : + for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): tweak[byte] = (j >> (8 * byte)) & 0xff tweak[-1] |= padding.value<<4 @@ -96,7 +97,7 @@ def TreatMessageEnc(M, N, key): 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 @@ -129,7 +130,7 @@ def TreatMessageDec(C, N, key) : ################################################################################ -def encrypt(A, M, N, key) : +def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -139,7 +140,7 @@ def encrypt(A, M, N, key) : return BlockbytesMatrixToBytes(C), bytes(tag) -def decrypt(A, C, N, tag, key) : +def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) @@ -147,5 +148,7 @@ def decrypt(A, C, N, tag, key) : (Final, M) = TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) - if(tag == tag2) : - return BlockbytesMatrixToBytes(M) + if tag != tag2: + raise TagValidationError(tag, tag2) + + return BlockbytesMatrixToBytes(M) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 624fd93..3f72020 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -3,12 +3,13 @@ """ import lilliput_tbc as ltbc -from constants import BLOCK_BITS, BLOCK_BYTES +from constants import BLOCK_BYTES from helpers import ( ArrayToBlockbytesMatrix, BlockbytesMatrixToBytes, BuildAuth, Padding10LSB, + TagValidationError, XorState ) @@ -18,30 +19,31 @@ TWEAK_BYTES = TWEAK_BITS//8 def TweakTag(j, padded): - tweak = [0 for byte in range(0, TWEAK_BYTES)] + 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 + 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 + if padded: + tweak[TWEAK_BYTES - 1] |= 0x40 + + return tweak - return tweak -def TweakTagEnd(N) : - tweak = [0 for byte in range(0, TWEAK_BYTES)] +def TweakTagEnd(N): + tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(0, TWEAK_BYTES - 1) : + for byte in range(0, TWEAK_BYTES - 1): tweak[byte] = N[byte] tweak[TWEAK_BYTES - 1] = 0x10 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) : + for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) xorr = XorState(tag, array_j) @@ -51,19 +53,19 @@ def AddTagJ(tag, j) : return xorr -def MesssageAuthTag(M, N, Auth, key) : +def MesssageAuthTag(M, N, Auth, key): l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES tag = list(Auth) M = ArrayToBlockbytesMatrix(M) - for j in range(0, l) : + for j in range(0, l): tweak = TweakTag(j, False) encryption = ltbc.LilliputTBCEnc(tweak, key, M[j]) tag = XorState(tag, encryption) - if padding_bytes > 0 : + if padding_bytes > 0: tweak = TweakTag(l, True) m_padded = Padding10LSB(M[l], 8*padding_bytes) encryption = ltbc.LilliputTBCEnc(tweak, key, m_padded) @@ -76,14 +78,14 @@ def MesssageAuthTag(M, N, Auth, key) : return tag -def MessageEncryption(M, N, tag, key) : +def MessageEncryption(M, N, tag, key): l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES M = ArrayToBlockbytesMatrix(M) C = [] - for j in range(0, l) : + for j in range(0, l): tweak = AddTagJ(tag, j) padded_nonce = list(N) + [0x00] encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) @@ -97,8 +99,9 @@ def MessageEncryption(M, N, tag, key) : return C + ################################################################################ -def encrypt(A, M, N, key) : +def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) @@ -108,7 +111,7 @@ def encrypt(A, M, N, key) : return BlockbytesMatrixToBytes(C), bytes(tag) -def decrypt(A, C, N, tag, key) : +def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) @@ -118,5 +121,7 @@ def decrypt(A, C, N, tag, key) : Auth = BuildAuth(TWEAK_BITS, A, K) tag2 = MesssageAuthTag(M, N, Auth, K) - if tag == tag2: - return M + if tag != tag2: + raise TagValidationError(tag, tag2) + + return M diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py index 418d083..9dc7df2 100644 --- a/python/lilliput_tbc.py +++ b/python/lilliput_tbc.py @@ -10,7 +10,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 ############################# @@ -18,7 +18,7 @@ def BuildTweakey(tweak, key) : def _lane(TK, j): return TK[j*8:(j+1)*8] -def RoundTweakeySchedule(tweakey) : +def RoundTweakeySchedule(tweakey): p = len(tweakey)//8 multiplied_lanes = ( @@ -45,7 +45,7 @@ def TweakeyScheduleWhole(tweakey, r): TKs = [tweakey] RTKs = [SubTweakeyExtract(TKs[0], 0)] - for i in range(1, r) : + for i in range(1, r): TKs.append(RoundTweakeySchedule(TKs[i-1])) RTKs.append(SubTweakeyExtract(TKs[i], i)) @@ -54,69 +54,69 @@ def TweakeyScheduleWhole(tweakey, r): ################################################################################ -def NonLinearLayer(state, subtweakey) : +def NonLinearLayer(state, subtweakey): variables_xored = [0 for byte in range(0, 8)] - 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) : + 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) : + for byte in range(0,BLOCK_BYTES): state_output[byte] = state[byte] - for byte in range(0, 8) : + for byte in range(0, 8): state_output[15 - byte] ^= variables_sboxed[byte] 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) : + for byte in range(0, BLOCK_BYTES): state_output[byte] = state[byte] - for byte in range(1, 8) : + for byte in range(1, 8): state_output[15] ^= state[byte] - for byte in range(9, 15) : + for byte in range(9, 15): state_output[byte] ^= state[7] 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) : + for byte in range(0, BLOCK_BYTES): 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) : + for byte in range(0, BLOCK_BYTES): state_output[byte] = state[permutationInv[byte]] return state_output -def OneRoundEGFNEnc(state, subtweakey) : +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) : +def LastRoundEGFN(state, subtweakey): state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) return state_linear -def OneRoundEGFNDec(state, subtweakey) : +def OneRoundEGFNDec(state, subtweakey): state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) state_permutation = PermutationLayerDec(state_linear) @@ -136,20 +136,20 @@ def _rounds(key_bytes): ################################################################################ # Lilliput TBC -def LilliputTBCEnc(tweak, key, message) : +def LilliputTBCEnc(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) : + for byte in range(0, BLOCK_BYTES): state[byte] = message[byte] - for i in range(0, r-1) : + for i in range(0, r-1): state_output = OneRoundEGFNEnc(state, RTKs[i]) - for byte in range(0, BLOCK_BYTES) : + for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] state_output = LastRoundEGFN(state, RTKs[r-1]) @@ -157,20 +157,20 @@ def LilliputTBCEnc(tweak, key, message) : return state_output -def LilliputTBCDec(tweak, key, cipher) : +def LilliputTBCDec(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) : + for byte in range(0, BLOCK_BYTES): state[byte] = cipher[byte] - for i in range(0, r-1) : + for i in range(0, r-1): state_output = OneRoundEGFNDec(state, RTKs[r-i-1]) - for byte in range(0, BLOCK_BYTES) : + for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] state_output = LastRoundEGFN(state, RTKs[0]) diff --git a/python/multiplications.py b/python/multiplications.py index 7babd50..c5f1e44 100644 --- a/python/multiplications.py +++ b/python/multiplications.py @@ -1,6 +1,6 @@ # Multiply by matrix M -def _multiplyM(lane) : +def _multiplyM(lane): multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[6] << 2) & 0xff) @@ -9,7 +9,7 @@ def _multiplyM(lane) : return multiplied_lane -def _multiplyM2(lane) : +def _multiplyM2(lane): multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[5] << 2) & 0xff) @@ -35,7 +35,7 @@ def _multiplyM2(lane) : return multiplied_lane -def _multiplyM3(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) @@ -86,7 +86,7 @@ def _multiplyM3(lane) : return multiplied_lane -def _multiplyMR(lane) : +def _multiplyMR(lane): multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff) @@ -96,7 +96,7 @@ def _multiplyMR(lane) : return multiplied_lane -def _multiplyMR2(lane) : +def _multiplyMR2(lane): multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)] multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff) @@ -120,7 +120,7 @@ def _multiplyMR2(lane) : return multiplied_lane -def _multiplyMR3(lane) : +def _multiplyMR3(lane): multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)] multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff) -- cgit v1.2.3 From a3663b7b3bdc092fb0667ea6c16b8e9a6cf4cf73 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 21 Mar 2019 16:37:26 +0100 Subject: [implem-python] Utilisation des divisions entières // MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plutôt que int() ; moins de bruit. … Au passage, simplification (j'espère) de ArrayToBlockbytesMatrix() : - pas besoin d'initialiser la matrice à zéro ; suffit d'ajouter les octets et les blocs comme ils viennent, - AFAICT, int((length + (BLOCK_BYTES - (length % BLOCK_BYTES))) / BLOCK_BYTES) quand length % BLOCK_BYTES > 0, c'est juste une façon compliquée d'écrire int(length/BLOCK_BYTES) + 1 --- python/helpers.py | 27 +++++++++++++++------------ python/lilliput_ae_1.py | 11 ++++++----- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'python') diff --git a/python/helpers.py b/python/helpers.py index b02bea4..07affa9 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -3,20 +3,23 @@ from lilliput_tbc import LilliputTBCEnc 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 + 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 + ] - matrix = [[0] * BLOCK_BYTES for block in range(0, number_blocks - pad)] - if pad == 1: - matrix.append([0] * (length % BLOCK_BYTES)) + padding_len = len(vector)%BLOCK_BYTES - for byte in range(0, length): - matrix[int(byte / BLOCK_BYTES)][byte % BLOCK_BYTES] = array[byte] + if padding_len > 0: + padding = vector[-padding_len:] + matrix.append(padding) return matrix diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 9aad3a6..0bc4236 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -31,13 +31,14 @@ def LowPart(array, number_bits): lower_part = shifted & mask - will_padd = 0 + will_pad = 0 if number_bits % 8 != 0: - will_padd = 1 + will_pad = 1 - lower_part_byte = [0 for byte in range(0, int(number_bits / 8) + will_padd)] - for byte in range(0, int(number_bits / 8) + will_padd): - lower_part_byte[byte] = lower_part & 0xff + 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 -- cgit v1.2.3 From 7350fbb6583236b929235a8be7f17f149901f004 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Thu, 21 Mar 2019 17:16:21 +0100 Subject: [implem-python] Simplification de pad10* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dans le cadre d'une croisade contre les range(len(…)). Suppression d'un paramètre inutile dans la foulée. --- python/helpers.py | 23 ++++++----------------- python/lilliput_ae_1.py | 4 ++-- python/lilliput_ae_2.py | 10 +++++----- 3 files changed, 13 insertions(+), 24 deletions(-) (limited to 'python') diff --git a/python/helpers.py b/python/helpers.py index 07affa9..be4b406 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -32,19 +32,9 @@ def XorState(state1, state2): return [s1^s2 for (s1, s2) in zip(state1, state2)] -def Padding10LSB(array, number_bits): - shifted = 0 - for byte in range(0, len(array)): - shifted |= (array[byte] << (8 * byte)) - shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff - - padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1)) - - array_padded = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte) - - return array_padded +def Padding10LSB(X): + zeroes = [0] * (BLOCK_BYTES-len(X)-1) + return zeroes + [0b10000000] + X def _tweakAssociatedData(t, i, padded): @@ -69,8 +59,7 @@ def _tweakAssociatedData(t, i, padded): def BuildAuth(t, A, key): Auth = [0 for byte in range(0, BLOCK_BYTES)] l_a = len(A)//BLOCK_BYTES - - padding_bytes = len(A)%BLOCK_BYTES + need_padding = len(A)%BLOCK_BYTES > 0 A = ArrayToBlockbytesMatrix(A) @@ -79,11 +68,11 @@ def BuildAuth(t, A, key): enc = LilliputTBCEnc(tweak, key, A[i]) Auth = XorState(Auth, enc) - if padding_bytes == 0: + if not need_padding: return Auth tweak = _tweakAssociatedData(t, l_a, padded=True) - ad_padded = Padding10LSB(A[l_a], padding_bytes*8) + ad_padded = Padding10LSB(A[l_a]) enc = LilliputTBCEnc(tweak, key, ad_padded) Auth = XorState(Auth, enc) diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 0bc4236..5cc263b 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -85,7 +85,7 @@ def TreatMessageEnc(M, N, key): Final = ltbc.LilliputTBCEnc(tweak, key, checksum) else: - m_padded = Padding10LSB(M[l], padding_bytes*8) + m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) tweak = TweakMessage(N, l, _MessageTweak.PAD) pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) @@ -122,7 +122,7 @@ def TreatMessageDec(C, N, key): lower_part = LowPart(pad, padding_bytes*8) M.append(XorState(C[l], lower_part)) - m_padded = Padding10LSB(M[l], padding_bytes*8) + m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) Final = ltbc.LilliputTBCEnc(tweak_final, key, checksum) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 3f72020..2e7843b 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -55,7 +55,7 @@ def AddTagJ(tag, j): def MesssageAuthTag(M, N, Auth, key): l = len(M)//BLOCK_BYTES - padding_bytes = len(M)%BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 tag = list(Auth) M = ArrayToBlockbytesMatrix(M) @@ -65,9 +65,9 @@ def MesssageAuthTag(M, N, Auth, key): encryption = ltbc.LilliputTBCEnc(tweak, key, M[j]) tag = XorState(tag, encryption) - if padding_bytes > 0: + if need_padding: tweak = TweakTag(l, True) - m_padded = Padding10LSB(M[l], 8*padding_bytes) + m_padded = Padding10LSB(M[l]) encryption = ltbc.LilliputTBCEnc(tweak, key, m_padded) tag = XorState(tag, encryption) @@ -80,7 +80,7 @@ def MesssageAuthTag(M, N, Auth, key): def MessageEncryption(M, N, tag, key): l = len(M)//BLOCK_BYTES - padding_bytes = len(M)%BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 M = ArrayToBlockbytesMatrix(M) C = [] @@ -91,7 +91,7 @@ def MessageEncryption(M, N, tag, key): encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) C.append(XorState(M[j], encryption)) - if padding_bytes > 0: + if need_padding: tweak = AddTagJ(tag, l) padded_nonce = list(N) + [0x00] encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) -- cgit v1.2.3 From dd934c63386c8fa22a5b0944e0256c435d55938c Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 22 Mar 2019 10:34:02 +0100 Subject: [implem-python] Renommage du module TBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quand le tout sera packagé sous le namespace "lilliput", le préfixe alourdira plus qu'autre chose. --- python/helpers.py | 6 +- python/lilliput_ae_1.py | 18 ++--- python/lilliput_ae_2.py | 12 ++-- python/lilliput_tbc.py | 178 ------------------------------------------------ python/tbc.py | 178 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 196 deletions(-) delete mode 100644 python/lilliput_tbc.py create mode 100644 python/tbc.py (limited to 'python') diff --git a/python/helpers.py b/python/helpers.py index be4b406..321b096 100644 --- a/python/helpers.py +++ b/python/helpers.py @@ -1,5 +1,5 @@ from constants import BLOCK_BITS, BLOCK_BYTES -from lilliput_tbc import LilliputTBCEnc +import tbc def ArrayToBlockbytesMatrix(array): @@ -65,7 +65,7 @@ def BuildAuth(t, A, key): for i in range(0, l_a): tweak = _tweakAssociatedData(t, i, padded=False) - enc = LilliputTBCEnc(tweak, key, A[i]) + enc = tbc.encrypt(tweak, key, A[i]) Auth = XorState(Auth, enc) if not need_padding: @@ -73,7 +73,7 @@ def BuildAuth(t, A, key): tweak = _tweakAssociatedData(t, l_a, padded=True) ad_padded = Padding10LSB(A[l_a]) - enc = LilliputTBCEnc(tweak, key, ad_padded) + enc = tbc.encrypt(tweak, key, ad_padded) Auth = XorState(Auth, enc) return Auth diff --git a/python/lilliput_ae_1.py b/python/lilliput_ae_1.py index 5cc263b..8064871 100644 --- a/python/lilliput_ae_1.py +++ b/python/lilliput_ae_1.py @@ -4,7 +4,6 @@ from enum import Enum -import lilliput_tbc as ltbc from constants import BLOCK_BYTES, NONCE_BYTES from helpers import ( ArrayToBlockbytesMatrix, @@ -14,6 +13,7 @@ from helpers import ( TagValidationError, XorState ) +import tbc TWEAK_BITS = 192 @@ -78,22 +78,22 @@ def TreatMessageEnc(M, N, key): for j in range(0, l): checksum = XorState(checksum, M[j]) tweak = TweakMessage(N, j, _MessageTweak.BLOCK) - C.append(ltbc.LilliputTBCEnc(tweak, key, M[j])) + C.append(tbc.encrypt(tweak, key, M[j])) if padding_bytes == 0: tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) - Final = ltbc.LilliputTBCEnc(tweak, key, checksum) + Final = tbc.encrypt(tweak, key, checksum) else: m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) tweak = TweakMessage(N, l, _MessageTweak.PAD) - pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + 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 = ltbc.LilliputTBCEnc(tweak_final, key, checksum) + Final = tbc.encrypt(tweak_final, key, checksum) return (Final, C) @@ -109,23 +109,23 @@ def TreatMessageDec(C, N, key): for j in range(0, l): tweak = TweakMessage(N, j, _MessageTweak.BLOCK) - M.append(ltbc.LilliputTBCDec(tweak, key, C[j])) + 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 = ltbc.LilliputTBCEnc(tweak, key, checksum) + Final = tbc.encrypt(tweak, key, checksum) else: tweak = TweakMessage(N, l, _MessageTweak.PAD) - pad = ltbc.LilliputTBCEnc(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + 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 = ltbc.LilliputTBCEnc(tweak_final, key, checksum) + Final = tbc.encrypt(tweak_final, key, checksum) return (Final, M) diff --git a/python/lilliput_ae_2.py b/python/lilliput_ae_2.py index 2e7843b..3c0aa2a 100644 --- a/python/lilliput_ae_2.py +++ b/python/lilliput_ae_2.py @@ -2,7 +2,6 @@ SCT 2 for lilliput ae 2 """ -import lilliput_tbc as ltbc from constants import BLOCK_BYTES from helpers import ( ArrayToBlockbytesMatrix, @@ -12,6 +11,7 @@ from helpers import ( TagValidationError, XorState ) +import tbc TWEAK_BITS = 128 @@ -62,17 +62,17 @@ def MesssageAuthTag(M, N, Auth, key): for j in range(0, l): tweak = TweakTag(j, False) - encryption = ltbc.LilliputTBCEnc(tweak, key, M[j]) + encryption = tbc.encrypt(tweak, key, M[j]) tag = XorState(tag, encryption) if need_padding: tweak = TweakTag(l, True) m_padded = Padding10LSB(M[l]) - encryption = ltbc.LilliputTBCEnc(tweak, key, m_padded) + encryption = tbc.encrypt(tweak, key, m_padded) tag = XorState(tag, encryption) tweak = TweakTagEnd(N) - encryption = ltbc.LilliputTBCEnc(tweak, key, tag) + encryption = tbc.encrypt(tweak, key, tag) tag = encryption return tag @@ -88,13 +88,13 @@ def MessageEncryption(M, N, tag, key): for j in range(0, l): tweak = AddTagJ(tag, j) padded_nonce = list(N) + [0x00] - encryption = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) + 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 = ltbc.LilliputTBCEnc(tweak, key, padded_nonce) + encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(XorState(M[l], encryption)) return C diff --git a/python/lilliput_tbc.py b/python/lilliput_tbc.py deleted file mode 100644 index 9dc7df2..0000000 --- a/python/lilliput_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 LilliputTBCEnc(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 LilliputTBCDec(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/tbc.py b/python/tbc.py new file mode 100644 index 0000000..ca51649 --- /dev/null +++ b/python/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 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') 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 From ba01ba773731cb2c906beb6855dfea588dc8cf09 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 22 Mar 2019 14:48:47 +0100 Subject: [implem-python] Création de la surcouche "crypto_aead" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Il ne reste plus qu'à générer les dossiers lilliputae*/add_python et les fichiers parameters.py correspondants, et on peut ajouter le tout à l'archive à soumettre au NIST. --- python/.gitignore | 2 ++ python/compare.sh | 8 ++++---- python/crypto_aead.py | 18 ++++++++++++++++++ python/generate-vectors.sh | 27 +++++++++++++++++++++++++++ python/genkat_aead.py | 43 ++++++++++++------------------------------- python/lilliput/__init__.py | 26 ++++++++++++-------------- python/lilliput/constants.py | 1 + 7 files changed, 76 insertions(+), 49 deletions(-) create mode 100644 python/.gitignore create mode 100644 python/crypto_aead.py create mode 100755 python/generate-vectors.sh (limited to 'python') diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 0000000..d9aa5d4 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +results \ No newline at end of file diff --git a/python/compare.sh b/python/compare.sh index 7a9cdc7..41f27b6 100755 --- a/python/compare.sh +++ b/python/compare.sh @@ -5,11 +5,11 @@ set -eux -mkdir -p crypto_aead_ref +mkdir -p results/crypto_aead_ref for d in ../../SOUMISSION_NIST/REFERENCE_IMPLEMENTATION/crypto_aead/lilliputaei* do - mkdir -p crypto_aead_ref/$(basename $d) - cp $d/LWC*.txt crypto_aead_ref/$(basename $d)/ + mkdir -p results/crypto_aead_ref/$(basename $d) + cp $d/LWC*.txt results/crypto_aead_ref/$(basename $d)/ done -diff -ru crypto_aead_ref crypto_aead +diff -ru results/crypto_aead_ref results/crypto_aead diff --git a/python/crypto_aead.py b/python/crypto_aead.py new file mode 100644 index 0000000..792369c --- /dev/null +++ b/python/crypto_aead.py @@ -0,0 +1,18 @@ +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 + + +def encrypt(m, ad, npub, k): + c, tag = lilliput.encrypt(m, ad, k, npub, MODE) + return c+tag + + +def decrypt(c, ad, npub, k): + clen = len(c)-TAG_BYTES + ctext = c[:clen] + tag = c[clen:] + return lilliput.decrypt(ctext, tag, ad, k, npub, MODE) diff --git a/python/generate-vectors.sh b/python/generate-vectors.sh new file mode 100755 index 0000000..90b5840 --- /dev/null +++ b/python/generate-vectors.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -eu + +rm -rf results + +mkdir -p results/crypto_aead/lilliputae{i,ii}{128,192,256}v1 + +declare -A names=([1]=lilliputaei [2]=lilliputaeii) + +for mode in 1 2 +do + for keylen in 128 192 256 + do + echo generating for ${mode} ${keylen} + + cat < results/parameters.py +MODE = ${mode} +KEYBYTES = $((keylen/8)) +EOF + + PYTHONPATH=results ./genkat_aead.py + + dest=results/crypto_aead/${names[${mode}]}${keylen}v1 + mv LWC_AEAD_KAT_${keylen}_120.txt ${dest} + done +done diff --git a/python/genkat_aead.py b/python/genkat_aead.py index 8b38d9b..01bed6f 100755 --- a/python/genkat_aead.py +++ b/python/genkat_aead.py @@ -1,40 +1,23 @@ #!/usr/bin/env python3 -from lilliput import encrypt, decrypt, LilliputAeMode -from os import makedirs, path +import crypto_aead MAX_MESSAGE_LENGTH = 32 MAX_ADATA_LENGTH = 32 -CRYPTO_NPUBBYTES = 120//8 - - -MODE_SUFFIXES = { - LilliputAeMode.lilliput_1: 'i', - LilliputAeMode.lilliput_2: 'ii' -} - def print_bstr(output, label, buf): print('{l} = {b}'.format(l=label, b=buf.hex().upper()), file=output) -def generate_test_vectors(mode, keylen): - print('generating for', mode, keylen) - - directory = 'crypto_aead/lilliputae{mode}{keylen}v1'.format( - mode=MODE_SUFFIXES[mode], keylen=keylen - ) - - makedirs(directory, exist_ok=True) - - output_path = path.join( - directory, 'LWC_AEAD_KAT_{keylen}_120.txt'.format(keylen=keylen) +def generate_test_vectors(): + output_path = 'LWC_AEAD_KAT_{key}_{npub}.txt'.format( + key=crypto_aead.KEYBYTES*8, npub=crypto_aead.NPUBBYTES*8 ) - nonce = bytes(range(CRYPTO_NPUBBYTES)) - key = bytes(range(keylen//8)) + npub = bytes(range(crypto_aead.NPUBBYTES)) + key = bytes(range(crypto_aead.KEYBYTES)) with open(output_path, 'w') as output: @@ -47,22 +30,20 @@ def generate_test_vectors(mode, keylen): ad = bytes(range(adlen)) print_bstr(output, 'Key', key) - print_bstr(output, 'Nonce', nonce) + print_bstr(output, 'Nonce', npub) print_bstr(output, 'PT', msg) print_bstr(output, 'AD', ad) - ct, tag = encrypt(msg, ad, key, nonce, mode) + ct = crypto_aead.encrypt(msg, ad, npub, key) - print_bstr(output, 'CT', ct+tag) + print_bstr(output, 'CT', ct) - decrypt(ct, tag, ad, key, nonce, mode) + crypto_aead.decrypt(ct, ad, npub, key) - count+=1 + count += 1 print(file=output) if __name__ == '__main__': - for mode in LilliputAeMode: - for keylen in 128, 192, 256: - generate_test_vectors(mode, keylen) + generate_test_vectors() diff --git a/python/lilliput/__init__.py b/python/lilliput/__init__.py index 43179f8..5fbc0de 100644 --- a/python/lilliput/__init__.py +++ b/python/lilliput/__init__.py @@ -1,33 +1,31 @@ -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 +_AE_MODES = { + 1: lilliput_ae_1, + 2: lilliput_ae_2 +} -def _checkInputs(key, mode, nonce): +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.name not in LilliputAeMode.__members__: - raise ValueError('invalid mode: use a member of the LilliputAeMode enumeration') + if mode not in _AE_MODES: + raise ValueError('invalid mode: {} not in {}'.format(mode, tuple(_AE_MODES))) if len(nonce) != NONCE_BYTES: - raise ValueError('nonce must be {}-byte long'.format(NONCE_BYTES)) + raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BYTES, len(nonce))) def encrypt(plaintext, adata, key, nonce, mode): - _checkInputs(key, mode, nonce) - return mode.value.encrypt(adata, plaintext, nonce, key) + _check_inputs(key, mode, nonce) + return _AE_MODES[mode].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) + _check_inputs(key, mode, nonce) + return _AE_MODES[mode].decrypt(adata, ciphertext, nonce, tag, key) diff --git a/python/lilliput/constants.py b/python/lilliput/constants.py index c61dfe0..0c9b89f 100644 --- a/python/lilliput/constants.py +++ b/python/lilliput/constants.py @@ -1,6 +1,7 @@ BLOCK_BITS = 128 BLOCK_BYTES = BLOCK_BITS//8 NONCE_BYTES = 15 +TAG_BYTES = 16 Sbox = [ -- cgit v1.2.3 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) --- .gitignore | 1 + python/.gitignore | 2 - python/compare.sh | 15 --- python/crypto_aead.py | 18 --- python/generate-vectors.sh | 27 ----- python/genkat_aead.py | 49 -------- python/lilliput/__init__.py | 31 ----- python/lilliput/constants.py | 40 ------- 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 --------------------------- 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 +++++++++++++++++++++++++++ test/python.sh | 11 ++ test/python/compare.sh | 17 +++ test/python/crypto_aead.py | 18 +++ test/python/generate-vectors.sh | 31 +++++ test/python/genkat_aead.py | 49 ++++++++ 25 files changed, 936 insertions(+), 920 deletions(-) delete mode 100644 python/.gitignore delete mode 100755 python/compare.sh delete mode 100644 python/crypto_aead.py delete mode 100755 python/generate-vectors.sh delete mode 100755 python/genkat_aead.py delete mode 100644 python/lilliput/__init__.py delete mode 100644 python/lilliput/constants.py delete mode 100644 python/lilliput/helpers.py delete mode 100644 python/lilliput/lilliput_ae_1.py delete mode 100644 python/lilliput/lilliput_ae_2.py delete mode 100644 python/lilliput/multiplications.py delete mode 100644 python/lilliput/tbc.py 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 create mode 100755 test/python.sh create mode 100755 test/python/compare.sh create mode 100644 test/python/crypto_aead.py create mode 100755 test/python/generate-vectors.sh create mode 100755 test/python/genkat_aead.py (limited to 'python') diff --git a/.gitignore b/.gitignore index 7477fbe..bf4a44b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ crypto_aead results +__pycache__ *.tgz diff --git a/python/.gitignore b/python/.gitignore deleted file mode 100644 index d9aa5d4..0000000 --- a/python/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -__pycache__ -results \ No newline at end of file diff --git a/python/compare.sh b/python/compare.sh deleted file mode 100755 index 41f27b6..0000000 --- a/python/compare.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# TODO: make sure reference crypto_aead exists -# TODO: cleanup previous vectors and run genkat_aead.py - -set -eux - -mkdir -p results/crypto_aead_ref -for d in ../../SOUMISSION_NIST/REFERENCE_IMPLEMENTATION/crypto_aead/lilliputaei* -do - mkdir -p results/crypto_aead_ref/$(basename $d) - cp $d/LWC*.txt results/crypto_aead_ref/$(basename $d)/ -done - -diff -ru results/crypto_aead_ref results/crypto_aead diff --git a/python/crypto_aead.py b/python/crypto_aead.py deleted file mode 100644 index 792369c..0000000 --- a/python/crypto_aead.py +++ /dev/null @@ -1,18 +0,0 @@ -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 - - -def encrypt(m, ad, npub, k): - c, tag = lilliput.encrypt(m, ad, k, npub, MODE) - return c+tag - - -def decrypt(c, ad, npub, k): - clen = len(c)-TAG_BYTES - ctext = c[:clen] - tag = c[clen:] - return lilliput.decrypt(ctext, tag, ad, k, npub, MODE) diff --git a/python/generate-vectors.sh b/python/generate-vectors.sh deleted file mode 100755 index 90b5840..0000000 --- a/python/generate-vectors.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -eu - -rm -rf results - -mkdir -p results/crypto_aead/lilliputae{i,ii}{128,192,256}v1 - -declare -A names=([1]=lilliputaei [2]=lilliputaeii) - -for mode in 1 2 -do - for keylen in 128 192 256 - do - echo generating for ${mode} ${keylen} - - cat < results/parameters.py -MODE = ${mode} -KEYBYTES = $((keylen/8)) -EOF - - PYTHONPATH=results ./genkat_aead.py - - dest=results/crypto_aead/${names[${mode}]}${keylen}v1 - mv LWC_AEAD_KAT_${keylen}_120.txt ${dest} - done -done diff --git a/python/genkat_aead.py b/python/genkat_aead.py deleted file mode 100755 index 01bed6f..0000000 --- a/python/genkat_aead.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python3 - -import crypto_aead - - -MAX_MESSAGE_LENGTH = 32 -MAX_ADATA_LENGTH = 32 - - -def print_bstr(output, label, buf): - print('{l} = {b}'.format(l=label, b=buf.hex().upper()), file=output) - - -def generate_test_vectors(): - output_path = 'LWC_AEAD_KAT_{key}_{npub}.txt'.format( - key=crypto_aead.KEYBYTES*8, npub=crypto_aead.NPUBBYTES*8 - ) - - npub = bytes(range(crypto_aead.NPUBBYTES)) - key = bytes(range(crypto_aead.KEYBYTES)) - - with open(output_path, 'w') as output: - - count = 1 - for mlen in range(MAX_MESSAGE_LENGTH+1): - for adlen in range(MAX_ADATA_LENGTH+1): - print('Count = {c}'.format(c=count), file=output) - - msg = bytes(range(mlen)) - ad = bytes(range(adlen)) - - print_bstr(output, 'Key', key) - print_bstr(output, 'Nonce', npub) - print_bstr(output, 'PT', msg) - print_bstr(output, 'AD', ad) - - ct = crypto_aead.encrypt(msg, ad, npub, key) - - print_bstr(output, 'CT', ct) - - crypto_aead.decrypt(ct, ad, npub, key) - - count += 1 - - print(file=output) - - -if __name__ == '__main__': - generate_test_vectors() diff --git a/python/lilliput/__init__.py b/python/lilliput/__init__.py deleted file mode 100644 index 5fbc0de..0000000 --- a/python/lilliput/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -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/python/lilliput/constants.py b/python/lilliput/constants.py deleted file mode 100644 index 0c9b89f..0000000 --- a/python/lilliput/constants.py +++ /dev/null @@ -1,40 +0,0 @@ -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/python/lilliput/helpers.py b/python/lilliput/helpers.py deleted file mode 100644 index 8677f06..0000000 --- a/python/lilliput/helpers.py +++ /dev/null @@ -1,92 +0,0 @@ -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 deleted file mode 100644 index 0da2a95..0000000 --- a/python/lilliput/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 -) -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 deleted file mode 100644 index 61aa86e..0000000 --- a/python/lilliput/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 -) -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 deleted file mode 100644 index c5f1e44..0000000 --- a/python/lilliput/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/lilliput/tbc.py b/python/lilliput/tbc.py deleted file mode 100644 index 5291994..0000000 --- a/python/lilliput/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 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 diff --git a/test/python.sh b/test/python.sh new file mode 100755 index 0000000..ea23caf --- /dev/null +++ b/test/python.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -eu + +TEST_DIR=$(dirname $0) +ROOT_DIR=${TEST_DIR}/.. + +make -C ${ROOT_DIR} nist + +./python/generate-vectors.sh +./python/compare.sh diff --git a/test/python/compare.sh b/test/python/compare.sh new file mode 100755 index 0000000..414eb1e --- /dev/null +++ b/test/python/compare.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +PYTHON_DIR=$(dirname $0) +ROOT_DIR=${PYTHON_DIR}/../../ +RESULTS_DIR=${ROOT_DIR}/results +CRYPTO_AEAD=${ROOT_DIR}/crypto_aead + +set -eu + +mkdir -p ${RESULTS_DIR}/crypto_aead_ref +for d in ${CRYPTO_AEAD}/lilliputaei* +do + mkdir -p ${RESULTS_DIR}/crypto_aead_ref/$(basename $d) + cp $d/LWC*.txt ${RESULTS_DIR}/crypto_aead_ref/$(basename $d)/ +done + +diff -ru ${RESULTS_DIR}/crypto_aead_ref ${RESULTS_DIR}/crypto_aead_py diff --git a/test/python/crypto_aead.py b/test/python/crypto_aead.py new file mode 100644 index 0000000..792369c --- /dev/null +++ b/test/python/crypto_aead.py @@ -0,0 +1,18 @@ +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 + + +def encrypt(m, ad, npub, k): + c, tag = lilliput.encrypt(m, ad, k, npub, MODE) + return c+tag + + +def decrypt(c, ad, npub, k): + clen = len(c)-TAG_BYTES + ctext = c[:clen] + tag = c[clen:] + return lilliput.decrypt(ctext, tag, ad, k, npub, MODE) diff --git a/test/python/generate-vectors.sh b/test/python/generate-vectors.sh new file mode 100755 index 0000000..e328c67 --- /dev/null +++ b/test/python/generate-vectors.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -eu + +PYTHON_DIR=$(dirname $0) +ROOT_DIR=${PYTHON_DIR}/../../ +SRC_DIR=${ROOT_DIR}/src/add_python +RESULTS_DIR=${ROOT_DIR}/results +CRYPTO_AEAD=${RESULTS_DIR}/crypto_aead_py + +mkdir -p ${CRYPTO_AEAD}/lilliputae{i,ii}{128,192,256}v1 + +declare -A names=([1]=lilliputaei [2]=lilliputaeii) + +for mode in 1 2 +do + for keylen in 128 192 256 + do + echo generating for ${mode} ${keylen} + + cat < ${RESULTS_DIR}/parameters.py +MODE = ${mode} +KEYBYTES = $((keylen/8)) +EOF + + PYTHONPATH=${RESULTS_DIR}:${SRC_DIR} ${PYTHON_DIR}/genkat_aead.py + + dest=${CRYPTO_AEAD}/${names[${mode}]}${keylen}v1 + mv LWC_AEAD_KAT_${keylen}_120.txt ${dest} + done +done diff --git a/test/python/genkat_aead.py b/test/python/genkat_aead.py new file mode 100755 index 0000000..01bed6f --- /dev/null +++ b/test/python/genkat_aead.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import crypto_aead + + +MAX_MESSAGE_LENGTH = 32 +MAX_ADATA_LENGTH = 32 + + +def print_bstr(output, label, buf): + print('{l} = {b}'.format(l=label, b=buf.hex().upper()), file=output) + + +def generate_test_vectors(): + output_path = 'LWC_AEAD_KAT_{key}_{npub}.txt'.format( + key=crypto_aead.KEYBYTES*8, npub=crypto_aead.NPUBBYTES*8 + ) + + npub = bytes(range(crypto_aead.NPUBBYTES)) + key = bytes(range(crypto_aead.KEYBYTES)) + + with open(output_path, 'w') as output: + + count = 1 + for mlen in range(MAX_MESSAGE_LENGTH+1): + for adlen in range(MAX_ADATA_LENGTH+1): + print('Count = {c}'.format(c=count), file=output) + + msg = bytes(range(mlen)) + ad = bytes(range(adlen)) + + print_bstr(output, 'Key', key) + print_bstr(output, 'Nonce', npub) + print_bstr(output, 'PT', msg) + print_bstr(output, 'AD', ad) + + ct = crypto_aead.encrypt(msg, ad, npub, key) + + print_bstr(output, 'CT', ct) + + crypto_aead.decrypt(ct, ad, npub, key) + + count += 1 + + print(file=output) + + +if __name__ == '__main__': + generate_test_vectors() -- cgit v1.2.3