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(-) 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 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 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 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 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 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 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 From 80c311262daf19f796a190cc99e850d199315c0a Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Fri, 22 Mar 2019 16:53:43 +0100 Subject: [WIP][implem-python] Intégration à la soumission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nist/make-package.sh | 2 ++ nist/package-python.sh | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100755 nist/package-python.sh diff --git a/nist/make-package.sh b/nist/make-package.sh index 234532a..c3bbd32 100755 --- a/nist/make-package.sh +++ b/nist/make-package.sh @@ -116,3 +116,5 @@ done cp -r ${TMP_DIR}/crypto_aead . cleanup + +${NIST_DIR}/package-python.sh diff --git a/nist/package-python.sh b/nist/package-python.sh new file mode 100755 index 0000000..4813dc7 --- /dev/null +++ b/nist/package-python.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -eu + +NIST_DIR=$(dirname $0) +ROOT=${NIST_DIR}/.. +ADD_PYTHON=${ROOT}/src/add_python +CRYPTO_AEAD=${ROOT}/crypto_aead + + +add-variant () +{ + local mode=$1 + local keylen=$2 + + local -A names=([1]=lilliputaei [2]=lilliputaeii) + + variant_dir=${CRYPTO_AEAD}/${names[${mode}]}${keylen}v1 + + cp -r ${ADD_PYTHON} ${variant_dir} + + cat < ${variant_dir}/add_python/parameters.py +MODE = ${mode} +KEYBYTES = $((keylen/8)) +EOF +} + + +for mode in 1 2 +do + for keylen in 128 192 256 + do + add-variant ${mode} ${keylen} + done +done -- cgit v1.2.3 From c0d7ffb343d38a301773ea49975de6c54c91e264 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 19:31:06 +0100 Subject: [implem-python] Intégration à la soumission (suite et fin) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En plus du paquet Python "lilliput", chaque dossier embarque - un script "genkat_aead.py" qui génère les vecteurs de test via l'API du module "crypto_aead", - un module "crypto_aead" servant de point d'entrée générique, - un module "parameters", qui permet à crypto_aead d'instancier Lilliput-AE avec le bon mode et la bonne taille de clé. Livraison dans ./crypto_aead sans se soucier de l'arborescence du dépôt, par homogénéité avec make-package.sh. Quelques ajustement dans genkat_aead.py pour que le lien avec genkat_aead.c soit plus évident. --- nist/package-python.sh | 7 +++++-- test/python/genkat_aead.py | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/nist/package-python.sh b/nist/package-python.sh index 4813dc7..88c4ef1 100755 --- a/nist/package-python.sh +++ b/nist/package-python.sh @@ -5,7 +5,7 @@ set -eu NIST_DIR=$(dirname $0) ROOT=${NIST_DIR}/.. ADD_PYTHON=${ROOT}/src/add_python -CRYPTO_AEAD=${ROOT}/crypto_aead +PYTHON_RESOURCES=${ROOT}/test/python/ add-variant () @@ -15,7 +15,7 @@ add-variant () local -A names=([1]=lilliputaei [2]=lilliputaeii) - variant_dir=${CRYPTO_AEAD}/${names[${mode}]}${keylen}v1 + variant_dir=crypto_aead/${names[${mode}]}${keylen}v1 cp -r ${ADD_PYTHON} ${variant_dir} @@ -23,6 +23,9 @@ add-variant () MODE = ${mode} KEYBYTES = $((keylen/8)) EOF + + cp ${PYTHON_RESOURCES}/{crypto_aead.py,genkat_aead.py} \ + ${variant_dir}/add_python } diff --git a/test/python/genkat_aead.py b/test/python/genkat_aead.py index 01bed6f..5e953c4 100755 --- a/test/python/genkat_aead.py +++ b/test/python/genkat_aead.py @@ -3,8 +3,13 @@ import crypto_aead +class DecryptionError(Exception): + def __init__(self): + super().__init__('crypto_aead_decrypt did not recover the plaintext') + + MAX_MESSAGE_LENGTH = 32 -MAX_ADATA_LENGTH = 32 +MAX_ASSOCIATED_DATA_LENGTH = 32 def print_bstr(output, label, buf): @@ -12,23 +17,25 @@ def print_bstr(output, label, buf): def generate_test_vectors(): - output_path = 'LWC_AEAD_KAT_{key}_{npub}.txt'.format( + count = 1 + filename = '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: + with open(filename, '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) + for adlen in range(MAX_ASSOCIATED_DATA_LENGTH+1): msg = bytes(range(mlen)) ad = bytes(range(adlen)) + print('Count = {c}'.format(c=count), file=output) + count += 1 + print_bstr(output, 'Key', key) print_bstr(output, 'Nonce', npub) print_bstr(output, 'PT', msg) @@ -38,9 +45,10 @@ def generate_test_vectors(): print_bstr(output, 'CT', ct) - crypto_aead.decrypt(ct, ad, npub, key) + msg2 = crypto_aead.decrypt(ct, ad, npub, key) - count += 1 + if msg != msg2: + raise DecryptionError() print(file=output) -- cgit v1.2.3 From d1bc581b1923537e7410254d91890565f08d50ca Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 20:04:22 +0100 Subject: [implem-python] Documentation du paquet "lilliput" --- src/add_python/lilliput/__init__.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index 5fbc0de..b1bad58 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -1,3 +1,29 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-AE tweakable block cipher. + +This module provides the high-level functions for authenticated encryption and +decryption. Both functions take and return bytestring values. + +The "mode" argument can be either of the following integers: + +- 1, for the ΘCB3 nonce-respecting mode, +- 2, for the SCT-2 nonce-misuse-resistant mode. +""" + + from . import lilliput_ae_1 from . import lilliput_ae_2 from .constants import NONCE_BYTES -- cgit v1.2.3 From ec43894288a070a04e5ba837602c5eec38f332f2 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 23:30:57 +0100 Subject: [implem-python] Accélération du test d'implémentation Python MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Idéalement, il faudrait rajouter les bonnes dépendances dans le Makefile… --- test/python.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/python.sh b/test/python.sh index ea23caf..720daaa 100755 --- a/test/python.sh +++ b/test/python.sh @@ -2,10 +2,5 @@ set -eu -TEST_DIR=$(dirname $0) -ROOT_DIR=${TEST_DIR}/.. - -make -C ${ROOT_DIR} nist - ./python/generate-vectors.sh ./python/compare.sh -- cgit v1.2.3 From 01957e0fa098071e10b074dfe477fcc7d687bb99 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 23:32:04 +0100 Subject: [implem-python] Documentation du mode authentifié Lilliput-Ⅱ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout d'un souligné devant les fonctions privées ; de cette façon, >>> from lilliput import lilliput_ae_1 >>> help(lilliput_ae_1) … ne montre que les fonctions "publiques", i.e. celles que l'utilisateur est censé appeler. --- src/add_python/lilliput/lilliput_ae_2.py | 48 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/add_python/lilliput/lilliput_ae_2.py b/src/add_python/lilliput/lilliput_ae_2.py index 61aa86e..fb6feff 100644 --- a/src/add_python/lilliput/lilliput_ae_2.py +++ b/src/add_python/lilliput/lilliput_ae_2.py @@ -1,5 +1,21 @@ -""" - SCT 2 for lilliput ae 2 +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-II Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. """ from .constants import BLOCK_BYTES @@ -18,7 +34,7 @@ TWEAK_BITS = 128 TWEAK_BYTES = TWEAK_BITS//8 -def TweakTag(j, padded): +def _TweakTag(j, padded): tweak = [0 for byte in range(0, TWEAK_BYTES)] tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) @@ -31,7 +47,7 @@ def TweakTag(j, padded): return tweak -def TweakTagEnd(N): +def _TweakTagEnd(N): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES - 1): @@ -41,7 +57,7 @@ def TweakTagEnd(N): return tweak -def AddTagJ(tag, j): +def _AddTagJ(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) @@ -53,7 +69,7 @@ def AddTagJ(tag, j): return xorr -def MesssageAuthTag(M, N, Auth, key): +def _MesssageAuthTag(M, N, Auth, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 @@ -61,24 +77,24 @@ def MesssageAuthTag(M, N, Auth, key): M = ArrayToBlockbytesMatrix(M) for j in range(0, l): - tweak = TweakTag(j, False) + tweak = _TweakTag(j, False) encryption = tbc.encrypt(tweak, key, M[j]) tag = XorState(tag, encryption) if need_padding: - tweak = TweakTag(l, True) + tweak = _TweakTag(l, True) m_padded = Padding10LSB(M[l]) encryption = tbc.encrypt(tweak, key, m_padded) tag = XorState(tag, encryption) - tweak = TweakTagEnd(N) + tweak = _TweakTagEnd(N) encryption = tbc.encrypt(tweak, key, tag) tag = encryption return tag -def MessageEncryption(M, N, tag, key): +def _MessageEncryption(M, N, tag, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 @@ -86,13 +102,13 @@ def MessageEncryption(M, N, tag, key): C = [] for j in range(0, l): - tweak = AddTagJ(tag, j) + tweak = _AddTagJ(tag, j) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(XorState(M[j], encryption)) if need_padding: - tweak = AddTagJ(tag, l) + tweak = _AddTagJ(tag, l) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(XorState(M[l], encryption)) @@ -105,8 +121,8 @@ def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) - tag = MesssageAuthTag(M, N, Auth, K) - C = MessageEncryption(M, N, tag, K) + tag = _MesssageAuthTag(M, N, Auth, K) + C = _MessageEncryption(M, N, tag, K) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -116,10 +132,10 @@ def decrypt(A, C, N, tag, key): tag = list(tag) M = BlockbytesMatrixToBytes( - MessageEncryption(C, N, tag, K) + _MessageEncryption(C, N, tag, K) ) Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = MesssageAuthTag(M, N, Auth, K) + tag2 = _MesssageAuthTag(M, N, Auth, K) if tag != tag2: raise TagValidationError(tag, tag2) -- cgit v1.2.3 From b46dd7acc86295d3072945f4a8098649d87504a2 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sat, 23 Mar 2019 23:54:35 +0100 Subject: [implem-python] Documentation de Lilliput-Ⅰ et Lilliput-TBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Idem, renommage des fonctions privées avec un souligné pour que l'API soit plus simple à comprendre. ⚠ Pas testé, ça prend littéralement 20 minutes à l'implémentation Python de générer les vecteurs de test, et c'est l'heure du dodo… --- src/add_python/lilliput/lilliput_ae_1.py | 52 +++++++++------ src/add_python/lilliput/tbc.py | 105 ++++++++++++++++++------------- 2 files changed, 95 insertions(+), 62 deletions(-) diff --git a/src/add_python/lilliput/lilliput_ae_1.py b/src/add_python/lilliput/lilliput_ae_1.py index 0da2a95..1429002 100644 --- a/src/add_python/lilliput/lilliput_ae_1.py +++ b/src/add_python/lilliput/lilliput_ae_1.py @@ -1,5 +1,21 @@ -""" - OCB 3 for lilliput ae i +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-I Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. """ from enum import Enum @@ -20,7 +36,7 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def LowPart(array, number_bits): +def _LowPart(array, number_bits): shifted = 0 for byte in range(0, len(array)): shifted |= (array[byte] << (8 * byte)) @@ -51,7 +67,7 @@ class _MessageTweak(Enum): FINAL = 0b0101 -def TweakMessage(N, j, padding): +def _TweakMessage(N, j, padding): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(NONCE_BYTES-1, -1, -1): tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 @@ -66,7 +82,7 @@ def TweakMessage(N, j, padding): return tweak -def TreatMessageEnc(M, N, key): +def _TreatMessageEnc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(M)//BLOCK_BYTES @@ -77,28 +93,28 @@ def TreatMessageEnc(M, N, key): for j in range(0, l): checksum = XorState(checksum, M[j]) - tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) C.append(tbc.encrypt(tweak, key, M[j])) if padding_bytes == 0: - tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) - tweak = TweakMessage(N, l, _MessageTweak.PAD) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, padding_bytes*8) + lower_part = _LowPart(pad, padding_bytes*8) C.append(XorState(M[l], lower_part)) - tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, C) -def TreatMessageDec(C, N, key): +def _TreatMessageDec(C, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(C)//BLOCK_BYTES @@ -108,23 +124,23 @@ def TreatMessageDec(C, N, key): M = [] for j in range(0, l): - tweak = TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) M.append(tbc.decrypt(tweak, key, C[j])) checksum = XorState(checksum, M[j]) if padding_bytes == 0: - tweak = TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - tweak = TweakMessage(N, l, _MessageTweak.PAD) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = LowPart(pad, padding_bytes*8) + lower_part = _LowPart(pad, padding_bytes*8) M.append(XorState(C[l], lower_part)) m_padded = Padding10LSB(M[l]) checksum = XorState(checksum, m_padded) - tweak_final = TweakMessage(N, l+1, _MessageTweak.FINAL) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, M) @@ -135,7 +151,7 @@ def encrypt(A, M, N, key): K = list(key) Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = TreatMessageEnc(M, N, K) + (Final, C) = _TreatMessageEnc(M, N, K) tag = XorState(Auth, Final) return BlockbytesMatrixToBytes(C), bytes(tag) @@ -146,7 +162,7 @@ def decrypt(A, C, N, tag, key): tag = list(tag) Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = TreatMessageDec(C, N, K) + (Final, M) = _TreatMessageDec(C, N, K) tag2 = XorState(Auth, Final) if tag != tag2: diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py index 5291994..50f9e2f 100644 --- a/src/add_python/lilliput/tbc.py +++ b/src/add_python/lilliput/tbc.py @@ -1,34 +1,51 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-TBC tweakable block cipher. + +This module provides functions to encrypt and decrypt blocks of 128 bits. """ - Lilliput TBC -""" + from .constants import BLOCK_BYTES, Sbox from .multiplications import ALPHAS -permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] -permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] +_permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] +_permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] ################################################################################ -def BuildTweakey(tweak, key): +def _BuildTweakey(tweak, key): return tweak+key ############################# -def _lane(TK, j): +def _Lane(TK, j): return TK[j*8:(j+1)*8] -def RoundTweakeySchedule(tweakey): + +def _RoundTweakeySchedule(tweakey): p = len(tweakey)//8 multiplied_lanes = ( - ALPHAS[j](_lane(tweakey, j)) for j in range(p) + ALPHAS[j](_Lane(tweakey, j)) for j in range(p) ) return [byte for lane in multiplied_lanes for byte in lane] -def SubTweakeyExtract(tweakey, Ci): +def _SubTweakeyExtract(tweakey, Ci): RTKi = [0]*8 for j, byte in enumerate(tweakey): @@ -39,22 +56,22 @@ def SubTweakeyExtract(tweakey, Ci): return RTKi -def TweakeyScheduleWhole(tweakey, r): - # store main tweakey in TKs[0] - # and corresponding round tweakey in RTKs[0] +def _TweakeyScheduleWhole(tweakey, r): + # Store the initial tweakey in TKs[0], and the corresponding round tweakey + # in RTKs[0]. TKs = [tweakey] - RTKs = [SubTweakeyExtract(TKs[0], 0)] + RTKs = [_SubTweakeyExtract(TKs[0], 0)] for i in range(1, r): - TKs.append(RoundTweakeySchedule(TKs[i-1])) - RTKs.append(SubTweakeyExtract(TKs[i], i)) + TKs.append(_RoundTweakeySchedule(TKs[i-1])) + RTKs.append(_SubTweakeyExtract(TKs[i], i)) return RTKs ################################################################################ -def NonLinearLayer(state, subtweakey): +def _NonLinearLayer(state, subtweakey): variables_xored = [0 for byte in range(0, 8)] for byte in range(0,8): @@ -73,7 +90,7 @@ def NonLinearLayer(state, subtweakey): return state_output -def LinearLayer(state): +def _LinearLayer(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state_output[byte] = state[byte] @@ -87,44 +104,44 @@ def LinearLayer(state): return state_output -def PermutationLayerEnc(state): +def _PermutationLayerEnc(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[permutation[byte]] + state_output[byte] = state[_permutation[byte]] return state_output -def PermutationLayerDec(state): +def _PermutationLayerDec(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[permutationInv[byte]] + state_output[byte] = state[_permutationInv[byte]] return state_output -def OneRoundEGFNEnc(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) - state_permutation = PermutationLayerEnc(state_linear) +def _OneRoundEGFNEnc(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) + state_permutation = _PermutationLayerEnc(state_linear) return state_permutation -def LastRoundEGFN(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) +def _LastRoundEGFN(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) return state_linear -def OneRoundEGFNDec(state, subtweakey): - state_non_linear = NonLinearLayer(state, subtweakey) - state_linear = LinearLayer(state_non_linear) - state_permutation = PermutationLayerDec(state_linear) +def _OneRoundEGFNDec(state, subtweakey): + state_non_linear = _NonLinearLayer(state, subtweakey) + state_linear = _LinearLayer(state_non_linear) + state_permutation = _PermutationLayerDec(state_linear) return state_permutation -def _rounds(key_bytes): +def _Rounds(key_bytes): rounds = { 128: 32, 192: 36, @@ -134,45 +151,45 @@ def _rounds(key_bytes): ################################################################################ -# Lilliput TBC + def encrypt(tweak, key, message): - r = _rounds(len(key)) + r = _Rounds(len(key)) - tweakey = BuildTweakey(tweak, key) - RTKs = TweakeyScheduleWhole(tweakey, r) + tweakey = _BuildTweakey(tweak, key) + RTKs = _TweakeyScheduleWhole(tweakey, r) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state[byte] = message[byte] for i in range(0, r-1): - state_output = OneRoundEGFNEnc(state, RTKs[i]) + state_output = _OneRoundEGFNEnc(state, RTKs[i]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = LastRoundEGFN(state, RTKs[r-1]) + state_output = _LastRoundEGFN(state, RTKs[r-1]) return state_output def decrypt(tweak, key, cipher): - r = _rounds(len(key)) + r = _Rounds(len(key)) - tweakey = BuildTweakey(tweak, key) - RTKs = TweakeyScheduleWhole(tweakey, r) + tweakey = _BuildTweakey(tweak, key) + RTKs = _TweakeyScheduleWhole(tweakey, r) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state[byte] = cipher[byte] for i in range(0, r-1): - state_output = OneRoundEGFNDec(state, RTKs[r-i-1]) + state_output = _OneRoundEGFNDec(state, RTKs[r-i-1]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = LastRoundEGFN(state, RTKs[0]) + state_output = _LastRoundEGFN(state, RTKs[0]) return state_output -- cgit v1.2.3 From 099eac536457b12fa1919abffdb06a147d2cafde Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 00:02:27 +0100 Subject: [implem-python] Renommage des modules des modes authentifiés MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On bénéficie déjà de l'espace de nommage "lilliput". --- src/add_python/lilliput/__init__.py | 8 +- src/add_python/lilliput/ae_mode_1.py | 171 +++++++++++++++++++++++++++++++ src/add_python/lilliput/ae_mode_2.py | 143 ++++++++++++++++++++++++++ src/add_python/lilliput/lilliput_ae_1.py | 171 ------------------------------- src/add_python/lilliput/lilliput_ae_2.py | 143 -------------------------- 5 files changed, 318 insertions(+), 318 deletions(-) create mode 100644 src/add_python/lilliput/ae_mode_1.py create mode 100644 src/add_python/lilliput/ae_mode_2.py delete mode 100644 src/add_python/lilliput/lilliput_ae_1.py delete mode 100644 src/add_python/lilliput/lilliput_ae_2.py diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index b1bad58..dc193c6 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -24,14 +24,14 @@ The "mode" argument can be either of the following integers: """ -from . import lilliput_ae_1 -from . import lilliput_ae_2 +from . import ae_mode_1 +from . import ae_mode_2 from .constants import NONCE_BYTES _AE_MODES = { - 1: lilliput_ae_1, - 2: lilliput_ae_2 + 1: ae_mode_1, + 2: ae_mode_2 } diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py new file mode 100644 index 0000000..1429002 --- /dev/null +++ b/src/add_python/lilliput/ae_mode_1.py @@ -0,0 +1,171 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-I Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. +""" + +from enum import Enum + +from .constants import BLOCK_BYTES, NONCE_BYTES +from .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 192 +TWEAK_BYTES = TWEAK_BITS//8 + + +def _LowPart(array, number_bits): + shifted = 0 + for byte in range(0, len(array)): + shifted |= (array[byte] << (8 * byte)) + + mask = 0 + for bit in range(0, number_bits): + mask |= (0x1 << bit) + + lower_part = shifted & mask + + will_pad = 0 + if number_bits % 8 != 0: + will_pad = 1 + + lower_part_byte = [] + nb_bytes = number_bits//8 + will_pad + for byte in range(nb_bytes): + lower_part_byte.append(lower_part & 0xff) + lower_part = lower_part >> 8 + + return lower_part_byte + + +class _MessageTweak(Enum): + BLOCK = 0b000 + NO_PADDING = 0b0001 + PAD = 0b0100 + FINAL = 0b0101 + + +def _TweakMessage(N, j, padding): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(NONCE_BYTES-1, -1, -1): + tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 + tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 + + tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) + for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + tweak[-1] |= padding.value<<4 + + return tweak + + +def _TreatMessageEnc(M, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(M)//BLOCK_BYTES + padding_bytes = len(M)%BLOCK_BYTES + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + checksum = XorState(checksum, M[j]) + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + C.append(tbc.encrypt(tweak, key, M[j])) + + if padding_bytes == 0: + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak = _TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + + lower_part = _LowPart(pad, padding_bytes*8) + C.append(XorState(M[l], lower_part)) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, C) + + +def _TreatMessageDec(C, N, key): + checksum = [0 for byte in range(0, BLOCK_BYTES)] + + l = len(C)//BLOCK_BYTES + padding_bytes = len(C)%BLOCK_BYTES + + C = ArrayToBlockbytesMatrix(C) + M = [] + + for j in range(0, l): + tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + M.append(tbc.decrypt(tweak, key, C[j])) + checksum = XorState(checksum, M[j]) + + if padding_bytes == 0: + tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + Final = tbc.encrypt(tweak, key, checksum) + + else: + tweak = _TweakMessage(N, l, _MessageTweak.PAD) + pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + lower_part = _LowPart(pad, padding_bytes*8) + M.append(XorState(C[l], lower_part)) + + m_padded = Padding10LSB(M[l]) + checksum = XorState(checksum, m_padded) + tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + Final = tbc.encrypt(tweak_final, key, checksum) + + return (Final, M) + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, C) = _TreatMessageEnc(M, N, K) + tag = XorState(Auth, Final) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + Auth = BuildAuth(TWEAK_BITS, A, K) + (Final, M) = _TreatMessageDec(C, N, K) + tag2 = XorState(Auth, Final) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return BlockbytesMatrixToBytes(M) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py new file mode 100644 index 0000000..fb6feff --- /dev/null +++ b/src/add_python/lilliput/ae_mode_2.py @@ -0,0 +1,143 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Lilliput-II Authenticated Encryption mode. + +This module provides the functions for authenticated encryption and decryption +using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. +""" + +from .constants import BLOCK_BYTES +from .helpers import ( + ArrayToBlockbytesMatrix, + BlockbytesMatrixToBytes, + BuildAuth, + Padding10LSB, + TagValidationError, + XorState +) +from . import tbc + + +TWEAK_BITS = 128 +TWEAK_BYTES = TWEAK_BITS//8 + + +def _TweakTag(j, padded): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) + for byte in range(TWEAK_BYTES - 2, -1, -1): + tweak[byte] = (j >> (8 * byte)) & 0xff + + if padded: + tweak[TWEAK_BYTES - 1] |= 0x40 + + return tweak + + +def _TweakTagEnd(N): + tweak = [0 for byte in range(0, TWEAK_BYTES)] + + for byte in range(0, TWEAK_BYTES - 1): + tweak[byte] = N[byte] + tweak[TWEAK_BYTES - 1] = 0x10 + + return tweak + + +def _AddTagJ(tag, j): + array_j = [0 for byte in range(0, TWEAK_BYTES)] + for byte in range(0, TWEAK_BYTES): + array_j[byte] = (j >> (byte * 8)) + + xorr = XorState(tag, array_j) + + xorr[TWEAK_BYTES - 1] |= 0x80 + + return xorr + + +def _MesssageAuthTag(M, N, Auth, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + tag = list(Auth) + M = ArrayToBlockbytesMatrix(M) + + for j in range(0, l): + tweak = _TweakTag(j, False) + encryption = tbc.encrypt(tweak, key, M[j]) + tag = XorState(tag, encryption) + + if need_padding: + tweak = _TweakTag(l, True) + m_padded = Padding10LSB(M[l]) + encryption = tbc.encrypt(tweak, key, m_padded) + tag = XorState(tag, encryption) + + tweak = _TweakTagEnd(N) + encryption = tbc.encrypt(tweak, key, tag) + tag = encryption + + return tag + + +def _MessageEncryption(M, N, tag, key): + l = len(M)//BLOCK_BYTES + need_padding = len(M)%BLOCK_BYTES > 0 + + M = ArrayToBlockbytesMatrix(M) + C = [] + + for j in range(0, l): + tweak = _AddTagJ(tag, j) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[j], encryption)) + + if need_padding: + tweak = _AddTagJ(tag, l) + padded_nonce = list(N) + [0x00] + encryption = tbc.encrypt(tweak, key, padded_nonce) + C.append(XorState(M[l], encryption)) + + return C + + +################################################################################ +def encrypt(A, M, N, key): + K = list(key) + + Auth = BuildAuth(TWEAK_BITS, A, K) + tag = _MesssageAuthTag(M, N, Auth, K) + C = _MessageEncryption(M, N, tag, K) + + return BlockbytesMatrixToBytes(C), bytes(tag) + + +def decrypt(A, C, N, tag, key): + K = list(key) + tag = list(tag) + + M = BlockbytesMatrixToBytes( + _MessageEncryption(C, N, tag, K) + ) + Auth = BuildAuth(TWEAK_BITS, A, K) + tag2 = _MesssageAuthTag(M, N, Auth, K) + + if tag != tag2: + raise TagValidationError(tag, tag2) + + return M diff --git a/src/add_python/lilliput/lilliput_ae_1.py b/src/add_python/lilliput/lilliput_ae_1.py deleted file mode 100644 index 1429002..0000000 --- a/src/add_python/lilliput/lilliput_ae_1.py +++ /dev/null @@ -1,171 +0,0 @@ -# Implementation of the Lilliput-AE tweakable block cipher. -# -# Authors, hereby denoted as "the implementer": -# Kévin Le Gouguec, -# Léo Reynaud -# 2019. -# -# For more information, feedback or questions, refer to our website: -# https://paclido.fr/lilliput-ae -# -# To the extent possible under law, the implementer has waived all copyright -# and related or neighboring rights to the source code in this file. -# http://creativecommons.org/publicdomain/zero/1.0/ - -"""Lilliput-I Authenticated Encryption mode. - -This module provides the functions for authenticated encryption and decryption -using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. -""" - -from enum import Enum - -from .constants import BLOCK_BYTES, NONCE_BYTES -from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, - TagValidationError, - XorState -) -from . import tbc - - -TWEAK_BITS = 192 -TWEAK_BYTES = TWEAK_BITS//8 - - -def _LowPart(array, number_bits): - shifted = 0 - for byte in range(0, len(array)): - shifted |= (array[byte] << (8 * byte)) - - mask = 0 - for bit in range(0, number_bits): - mask |= (0x1 << bit) - - lower_part = shifted & mask - - will_pad = 0 - if number_bits % 8 != 0: - will_pad = 1 - - lower_part_byte = [] - nb_bytes = number_bits//8 + will_pad - for byte in range(nb_bytes): - lower_part_byte.append(lower_part & 0xff) - lower_part = lower_part >> 8 - - return lower_part_byte - - -class _MessageTweak(Enum): - BLOCK = 0b000 - NO_PADDING = 0b0001 - PAD = 0b0100 - FINAL = 0b0101 - - -def _TweakMessage(N, j, padding): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(NONCE_BYTES-1, -1, -1): - tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 - tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 - - tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) - for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff - - tweak[-1] |= padding.value<<4 - - return tweak - - -def _TreatMessageEnc(M, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] - - l = len(M)//BLOCK_BYTES - padding_bytes = len(M)%BLOCK_BYTES - - M = ArrayToBlockbytesMatrix(M) - C = [] - - for j in range(0, l): - checksum = XorState(checksum, M[j]) - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) - C.append(tbc.encrypt(tweak, key, M[j])) - - if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) - Final = tbc.encrypt(tweak, key, checksum) - - else: - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak = _TweakMessage(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - - lower_part = _LowPart(pad, padding_bytes*8) - C.append(XorState(M[l], lower_part)) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) - Final = tbc.encrypt(tweak_final, key, checksum) - - return (Final, C) - - -def _TreatMessageDec(C, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] - - l = len(C)//BLOCK_BYTES - padding_bytes = len(C)%BLOCK_BYTES - - C = ArrayToBlockbytesMatrix(C) - M = [] - - for j in range(0, l): - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) - M.append(tbc.decrypt(tweak, key, C[j])) - checksum = XorState(checksum, M[j]) - - if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) - Final = tbc.encrypt(tweak, key, checksum) - - else: - tweak = _TweakMessage(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _LowPart(pad, padding_bytes*8) - M.append(XorState(C[l], lower_part)) - - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) - Final = tbc.encrypt(tweak_final, key, checksum) - - return (Final, M) - - -################################################################################ -def encrypt(A, M, N, key): - K = list(key) - - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = _TreatMessageEnc(M, N, K) - tag = XorState(Auth, Final) - - return BlockbytesMatrixToBytes(C), bytes(tag) - - -def decrypt(A, C, N, tag, key): - K = list(key) - tag = list(tag) - - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = _TreatMessageDec(C, N, K) - tag2 = XorState(Auth, Final) - - if tag != tag2: - raise TagValidationError(tag, tag2) - - return BlockbytesMatrixToBytes(M) diff --git a/src/add_python/lilliput/lilliput_ae_2.py b/src/add_python/lilliput/lilliput_ae_2.py deleted file mode 100644 index fb6feff..0000000 --- a/src/add_python/lilliput/lilliput_ae_2.py +++ /dev/null @@ -1,143 +0,0 @@ -# Implementation of the Lilliput-AE tweakable block cipher. -# -# Authors, hereby denoted as "the implementer": -# Kévin Le Gouguec, -# Léo Reynaud -# 2019. -# -# For more information, feedback or questions, refer to our website: -# https://paclido.fr/lilliput-ae -# -# To the extent possible under law, the implementer has waived all copyright -# and related or neighboring rights to the source code in this file. -# http://creativecommons.org/publicdomain/zero/1.0/ - -"""Lilliput-II Authenticated Encryption mode. - -This module provides the functions for authenticated encryption and decryption -using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. -""" - -from .constants import BLOCK_BYTES -from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, - TagValidationError, - XorState -) -from . import tbc - - -TWEAK_BITS = 128 -TWEAK_BYTES = TWEAK_BITS//8 - - -def _TweakTag(j, padded): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) - for byte in range(TWEAK_BYTES - 2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff - - if padded: - tweak[TWEAK_BYTES - 1] |= 0x40 - - return tweak - - -def _TweakTagEnd(N): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - for byte in range(0, TWEAK_BYTES - 1): - tweak[byte] = N[byte] - tweak[TWEAK_BYTES - 1] = 0x10 - - return tweak - - -def _AddTagJ(tag, j): - array_j = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(0, TWEAK_BYTES): - array_j[byte] = (j >> (byte * 8)) - - xorr = XorState(tag, array_j) - - xorr[TWEAK_BYTES - 1] |= 0x80 - - return xorr - - -def _MesssageAuthTag(M, N, Auth, key): - l = len(M)//BLOCK_BYTES - need_padding = len(M)%BLOCK_BYTES > 0 - - tag = list(Auth) - M = ArrayToBlockbytesMatrix(M) - - for j in range(0, l): - tweak = _TweakTag(j, False) - encryption = tbc.encrypt(tweak, key, M[j]) - tag = XorState(tag, encryption) - - if need_padding: - tweak = _TweakTag(l, True) - m_padded = Padding10LSB(M[l]) - encryption = tbc.encrypt(tweak, key, m_padded) - tag = XorState(tag, encryption) - - tweak = _TweakTagEnd(N) - encryption = tbc.encrypt(tweak, key, tag) - tag = encryption - - return tag - - -def _MessageEncryption(M, N, tag, key): - l = len(M)//BLOCK_BYTES - need_padding = len(M)%BLOCK_BYTES > 0 - - M = ArrayToBlockbytesMatrix(M) - C = [] - - for j in range(0, l): - tweak = _AddTagJ(tag, j) - padded_nonce = list(N) + [0x00] - encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[j], encryption)) - - if need_padding: - tweak = _AddTagJ(tag, l) - padded_nonce = list(N) + [0x00] - encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[l], encryption)) - - return C - - -################################################################################ -def encrypt(A, M, N, key): - K = list(key) - - Auth = BuildAuth(TWEAK_BITS, A, K) - tag = _MesssageAuthTag(M, N, Auth, K) - C = _MessageEncryption(M, N, tag, K) - - return BlockbytesMatrixToBytes(C), bytes(tag) - - -def decrypt(A, C, N, tag, key): - K = list(key) - tag = list(tag) - - M = BlockbytesMatrixToBytes( - _MessageEncryption(C, N, tag, K) - ) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = _MesssageAuthTag(M, N, Auth, K) - - if tag != tag2: - raise TagValidationError(tag, tag2) - - return M -- cgit v1.2.3 From cac916e13cc39b95a95b90352fe0f7a6fa6734f7 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 13:26:08 +0100 Subject: [implem-python] Correction de la documentation de Lilliput-Ⅰ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 1429002..c2fdd9e 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -15,7 +15,7 @@ """Lilliput-I Authenticated Encryption mode. This module provides the functions for authenticated encryption and decryption -using Lilliput-AE's nonce-misuse-resistant mode based on ΘCB3. +using Lilliput-AE's nonce-respecting mode based on ΘCB3. """ from enum import Enum -- cgit v1.2.3 From fad848887249da22a83e4f35dab3d80f8c590d4d Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 14:15:56 +0100 Subject: [implem-python] Ajustement du script de test Python MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit De sorte à ce qu'on puisse le lancer depuis n'importe quel dossier. --- test/python.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/python.sh b/test/python.sh index 720daaa..df4ce01 100755 --- a/test/python.sh +++ b/test/python.sh @@ -2,5 +2,7 @@ set -eu -./python/generate-vectors.sh -./python/compare.sh +TEST_DIR=$(dirname $0) + +${TEST_DIR}/python/generate-vectors.sh +${TEST_DIR}/python/compare.sh -- cgit v1.2.3 From 1b6e1eb38927633292e934ac314b10e7acc28e3d Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 14:17:25 +0100 Subject: [implem-python] Conformité PEP8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surtout la capitalisation des noms de fonction. Retrait des lignes de '#' ; si il y a des séparations à faire, autant ajouter des modules. Correction de _MessageTweak.BLOCK en passant. --- src/add_python/lilliput/ae_mode_1.py | 77 +++++++++++++------------ src/add_python/lilliput/ae_mode_2.py | 62 ++++++++++---------- src/add_python/lilliput/constants.py | 2 +- src/add_python/lilliput/helpers.py | 24 ++++---- src/add_python/lilliput/multiplications.py | 28 ++++----- src/add_python/lilliput/tbc.py | 91 ++++++++++++++---------------- 6 files changed, 140 insertions(+), 144 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index c2fdd9e..cc550e8 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -22,12 +22,12 @@ from enum import Enum from .constants import BLOCK_BYTES, NONCE_BYTES from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, + bytes_to_block_matrix, + block_matrix_to_bytes, + build_auth, + pad10, TagValidationError, - XorState + xor_state ) from . import tbc @@ -36,7 +36,7 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def _LowPart(array, number_bits): +def _low_part(array, number_bits): shifted = 0 for byte in range(0, len(array)): shifted |= (array[byte] << (8 * byte)) @@ -61,13 +61,13 @@ def _LowPart(array, number_bits): class _MessageTweak(Enum): - BLOCK = 0b000 + BLOCK = 0b0000 NO_PADDING = 0b0001 PAD = 0b0100 FINAL = 0b0101 -def _TweakMessage(N, j, padding): +def _tweak_message(N, j, padding): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(NONCE_BYTES-1, -1, -1): tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 @@ -82,90 +82,89 @@ def _TweakMessage(N, j, padding): return tweak -def _TreatMessageEnc(M, N, key): +def _treat_message_enc(M, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) C = [] for j in range(0, l): - checksum = XorState(checksum, M[j]) - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + checksum = xor_state(checksum, M[j]) + tweak = _tweak_message(N, j, _MessageTweak.BLOCK) C.append(tbc.encrypt(tweak, key, M[j])) if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak = _TweakMessage(N, l, _MessageTweak.PAD) + m_padded = pad10(M[l]) + checksum = xor_state(checksum, m_padded) + tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _LowPart(pad, padding_bytes*8) - C.append(XorState(M[l], lower_part)) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + lower_part = _low_part(pad, padding_bytes*8) + C.append(xor_state(M[l], lower_part)) + tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, C) -def _TreatMessageDec(C, N, key): +def _treat_message_dec(C, N, key): checksum = [0 for byte in range(0, BLOCK_BYTES)] l = len(C)//BLOCK_BYTES padding_bytes = len(C)%BLOCK_BYTES - C = ArrayToBlockbytesMatrix(C) + C = bytes_to_block_matrix(C) M = [] for j in range(0, l): - tweak = _TweakMessage(N, j, _MessageTweak.BLOCK) + tweak = _tweak_message(N, j, _MessageTweak.BLOCK) M.append(tbc.decrypt(tweak, key, C[j])) - checksum = XorState(checksum, M[j]) + checksum = xor_state(checksum, M[j]) if padding_bytes == 0: - tweak = _TweakMessage(N, l, _MessageTweak.NO_PADDING) + tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING) Final = tbc.encrypt(tweak, key, checksum) else: - tweak = _TweakMessage(N, l, _MessageTweak.PAD) + tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _LowPart(pad, padding_bytes*8) - M.append(XorState(C[l], lower_part)) + lower_part = _low_part(pad, padding_bytes*8) + M.append(xor_state(C[l], lower_part)) - m_padded = Padding10LSB(M[l]) - checksum = XorState(checksum, m_padded) - tweak_final = _TweakMessage(N, l+1, _MessageTweak.FINAL) + m_padded = pad10(M[l]) + checksum = xor_state(checksum, m_padded) + tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) return (Final, M) -################################################################################ def encrypt(A, M, N, key): K = list(key) - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, C) = _TreatMessageEnc(M, N, K) - tag = XorState(Auth, Final) + Auth = build_auth(TWEAK_BITS, A, K) + (Final, C) = _treat_message_enc(M, N, K) + tag = xor_state(Auth, Final) - return BlockbytesMatrixToBytes(C), bytes(tag) + return block_matrix_to_bytes(C), bytes(tag) def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) - Auth = BuildAuth(TWEAK_BITS, A, K) - (Final, M) = _TreatMessageDec(C, N, K) - tag2 = XorState(Auth, Final) + Auth = build_auth(TWEAK_BITS, A, K) + (Final, M) = _treat_message_dec(C, N, K) + tag2 = xor_state(Auth, Final) if tag != tag2: raise TagValidationError(tag, tag2) - return BlockbytesMatrixToBytes(M) + return block_matrix_to_bytes(M) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index fb6feff..4d5e499 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -20,12 +20,12 @@ using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. from .constants import BLOCK_BYTES from .helpers import ( - ArrayToBlockbytesMatrix, - BlockbytesMatrixToBytes, - BuildAuth, - Padding10LSB, + bytes_to_block_matrix, + block_matrix_to_bytes, + build_auth, + pad10, TagValidationError, - XorState + xor_state ) from . import tbc @@ -34,7 +34,7 @@ TWEAK_BITS = 128 TWEAK_BYTES = TWEAK_BITS//8 -def _TweakTag(j, padded): +def _tweak_tag(j, padded): tweak = [0 for byte in range(0, TWEAK_BYTES)] tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) @@ -47,7 +47,7 @@ def _TweakTag(j, padded): return tweak -def _TweakTagEnd(N): +def _tweak_tag_end(N): tweak = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES - 1): @@ -57,61 +57,61 @@ def _TweakTagEnd(N): return tweak -def _AddTagJ(tag, j): +def _add_tag_j(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) - xorr = XorState(tag, array_j) + xorr = xor_state(tag, array_j) xorr[TWEAK_BYTES - 1] |= 0x80 return xorr -def _MesssageAuthTag(M, N, Auth, key): +def _message_auth_tag(M, N, Auth, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 tag = list(Auth) - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) for j in range(0, l): - tweak = _TweakTag(j, False) + tweak = _tweak_tag(j, False) encryption = tbc.encrypt(tweak, key, M[j]) - tag = XorState(tag, encryption) + tag = xor_state(tag, encryption) if need_padding: - tweak = _TweakTag(l, True) - m_padded = Padding10LSB(M[l]) + tweak = _tweak_tag(l, True) + m_padded = pad10(M[l]) encryption = tbc.encrypt(tweak, key, m_padded) - tag = XorState(tag, encryption) + tag = xor_state(tag, encryption) - tweak = _TweakTagEnd(N) + tweak = _tweak_tag_end(N) encryption = tbc.encrypt(tweak, key, tag) tag = encryption return tag -def _MessageEncryption(M, N, tag, key): +def _message_encryption(M, N, tag, key): l = len(M)//BLOCK_BYTES need_padding = len(M)%BLOCK_BYTES > 0 - M = ArrayToBlockbytesMatrix(M) + M = bytes_to_block_matrix(M) C = [] for j in range(0, l): - tweak = _AddTagJ(tag, j) + tweak = _add_tag_j(tag, j) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[j], encryption)) + C.append(xor_state(M[j], encryption)) if need_padding: - tweak = _AddTagJ(tag, l) + tweak = _add_tag_j(tag, l) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(XorState(M[l], encryption)) + C.append(xor_state(M[l], encryption)) return C @@ -120,22 +120,22 @@ def _MessageEncryption(M, N, tag, key): def encrypt(A, M, N, key): K = list(key) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag = _MesssageAuthTag(M, N, Auth, K) - C = _MessageEncryption(M, N, tag, K) + Auth = build_auth(TWEAK_BITS, A, K) + tag = _message_auth_tag(M, N, Auth, K) + C = _message_encryption(M, N, tag, K) - return BlockbytesMatrixToBytes(C), bytes(tag) + return block_matrix_to_bytes(C), bytes(tag) def decrypt(A, C, N, tag, key): K = list(key) tag = list(tag) - M = BlockbytesMatrixToBytes( - _MessageEncryption(C, N, tag, K) + M = block_matrix_to_bytes( + _message_encryption(C, N, tag, K) ) - Auth = BuildAuth(TWEAK_BITS, A, K) - tag2 = _MesssageAuthTag(M, N, Auth, K) + Auth = build_auth(TWEAK_BITS, A, K) + tag2 = _message_auth_tag(M, N, Auth, K) if tag != tag2: raise TagValidationError(tag, tag2) diff --git a/src/add_python/lilliput/constants.py b/src/add_python/lilliput/constants.py index 0c9b89f..5e07e96 100644 --- a/src/add_python/lilliput/constants.py +++ b/src/add_python/lilliput/constants.py @@ -4,7 +4,7 @@ NONCE_BYTES = 15 TAG_BYTES = 16 -Sbox = [ +SBOX = [ 0x20, 0x00, 0xb2, 0x85, 0x3b, 0x35, 0xa6, 0xa4, 0x30, 0xe4, 0x6a, 0x2c, 0xff, 0x59, 0xe2, 0x0e, 0xf8, 0x1e, 0x7a, 0x80, 0x15, 0xbd, 0x3e, 0xb1, diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py index 8677f06..65989d0 100644 --- a/src/add_python/lilliput/helpers.py +++ b/src/add_python/lilliput/helpers.py @@ -2,7 +2,7 @@ from .constants import BLOCK_BITS, BLOCK_BYTES from . import tbc -def ArrayToBlockbytesMatrix(array): +def bytes_to_block_matrix(array): vector = list(array) blocks_nb = len(vector)//BLOCK_BYTES @@ -24,20 +24,20 @@ def ArrayToBlockbytesMatrix(array): return matrix -def BlockbytesMatrixToBytes(matrix): +def block_matrix_to_bytes(matrix): return bytes(byte for block in matrix for byte in block) -def XorState(state1, state2): +def xor_state(state1, state2): return [s1^s2 for (s1, s2) in zip(state1, state2)] -def Padding10LSB(X): +def pad10(X): zeroes = [0] * (BLOCK_BYTES-len(X)-1) return zeroes + [0b10000000] + X -def _tweakAssociatedData(t, i, padded): +def _tweak_associated_data(t, i, padded): t_bytes = t//8 tweak = [0]*(t_bytes) @@ -56,25 +56,25 @@ def _tweakAssociatedData(t, i, padded): return tweak -def BuildAuth(t, A, key): +def build_auth(t, A, key): Auth = [0 for byte in range(0, BLOCK_BYTES)] l_a = len(A)//BLOCK_BYTES need_padding = len(A)%BLOCK_BYTES > 0 - A = ArrayToBlockbytesMatrix(A) + A = bytes_to_block_matrix(A) for i in range(0, l_a): - tweak = _tweakAssociatedData(t, i, padded=False) + tweak = _tweak_associated_data(t, i, padded=False) enc = tbc.encrypt(tweak, key, A[i]) - Auth = XorState(Auth, enc) + Auth = xor_state(Auth, enc) if not need_padding: return Auth - tweak = _tweakAssociatedData(t, l_a, padded=True) - ad_padded = Padding10LSB(A[l_a]) + tweak = _tweak_associated_data(t, l_a, padded=True) + ad_padded = pad10(A[l_a]) enc = tbc.encrypt(tweak, key, ad_padded) - Auth = XorState(Auth, enc) + Auth = xor_state(Auth, enc) return Auth diff --git a/src/add_python/lilliput/multiplications.py b/src/add_python/lilliput/multiplications.py index c5f1e44..dfdc3cb 100644 --- a/src/add_python/lilliput/multiplications.py +++ b/src/add_python/lilliput/multiplications.py @@ -1,6 +1,6 @@ -# Multiply by matrix M -def _multiplyM(lane): + +def _multiply_M(lane): multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[6] << 2) & 0xff) @@ -9,7 +9,8 @@ def _multiplyM(lane): return multiplied_lane -def _multiplyM2(lane): + +def _multiply_M2(lane): multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[5] << 2) & 0xff) @@ -35,7 +36,7 @@ def _multiplyM2(lane): return multiplied_lane -def _multiplyM3(lane): +def _multiply_M3(lane): multiplied_lane = [lane[(byte-3) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] << 2) & 0xff) ^ ((lane[5] << 5) & 0xff) @@ -86,7 +87,7 @@ def _multiplyM3(lane): return multiplied_lane -def _multiplyMR(lane): +def _multiply_MR(lane): multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)] multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff) @@ -96,7 +97,7 @@ def _multiplyMR(lane): return multiplied_lane -def _multiplyMR2(lane): +def _multiply_MR2(lane): multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)] multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff) @@ -120,7 +121,8 @@ def _multiplyMR2(lane): return multiplied_lane -def _multiplyMR3(lane): + +def _multiply_MR3(lane): multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)] multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff) @@ -177,10 +179,10 @@ def _multiplyMR3(lane): ALPHAS = ( list, # Identity. - _multiplyM, - _multiplyM2, - _multiplyM3, - _multiplyMR, - _multiplyMR2, - _multiplyMR3 + _multiply_M, + _multiply_M2, + _multiply_M3, + _multiply_MR, + _multiply_MR2, + _multiply_MR3 ) diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py index 50f9e2f..c607e45 100644 --- a/src/add_python/lilliput/tbc.py +++ b/src/add_python/lilliput/tbc.py @@ -17,35 +17,33 @@ This module provides functions to encrypt and decrypt blocks of 128 bits. """ -from .constants import BLOCK_BYTES, Sbox +from .constants import BLOCK_BYTES, SBOX from .multiplications import ALPHAS -_permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] -_permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] +_PERMUTATION = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] +_PERMUTATION_INV = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] -################################################################################ -def _BuildTweakey(tweak, key): +def _build_tweakey(tweak, key): return tweak+key -############################# -def _Lane(TK, j): +def _lane(TK, j): return TK[j*8:(j+1)*8] -def _RoundTweakeySchedule(tweakey): +def _round_tweakey_schedule(tweakey): p = len(tweakey)//8 multiplied_lanes = ( - ALPHAS[j](_Lane(tweakey, j)) for j in range(p) + ALPHAS[j](_lane(tweakey, j)) for j in range(p) ) return [byte for lane in multiplied_lanes for byte in lane] -def _SubTweakeyExtract(tweakey, Ci): +def _subtweakey_extract(tweakey, Ci): RTKi = [0]*8 for j, byte in enumerate(tweakey): @@ -56,22 +54,20 @@ def _SubTweakeyExtract(tweakey, Ci): return RTKi -def _TweakeyScheduleWhole(tweakey, r): +def _tweakey_schedule_whole(tweakey, r): # Store the initial tweakey in TKs[0], and the corresponding round tweakey # in RTKs[0]. TKs = [tweakey] - RTKs = [_SubTweakeyExtract(TKs[0], 0)] + RTKs = [_subtweakey_extract(TKs[0], 0)] for i in range(1, r): - TKs.append(_RoundTweakeySchedule(TKs[i-1])) - RTKs.append(_SubTweakeyExtract(TKs[i], i)) + TKs.append(_round_tweakey_schedule(TKs[i-1])) + RTKs.append(_subtweakey_extract(TKs[i], i)) return RTKs -################################################################################ - -def _NonLinearLayer(state, subtweakey): +def _non_linear_layer(state, subtweakey): variables_xored = [0 for byte in range(0, 8)] for byte in range(0,8): @@ -79,7 +75,7 @@ def _NonLinearLayer(state, subtweakey): variables_sboxed = [0 for byte in range(0, 8)] for byte in range(0, 8): - variables_sboxed[byte] = Sbox[variables_xored[byte]] + variables_sboxed[byte] = SBOX[variables_xored[byte]] state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0,BLOCK_BYTES): @@ -90,7 +86,7 @@ def _NonLinearLayer(state, subtweakey): return state_output -def _LinearLayer(state): +def _linear_layer(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state_output[byte] = state[byte] @@ -104,44 +100,46 @@ def _LinearLayer(state): return state_output -def _PermutationLayerEnc(state): +def _permutation_layer_enc(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[_permutation[byte]] + state_output[byte] = state[_PERMUTATION[byte]] return state_output -def _PermutationLayerDec(state): + +def _permutation_layer_dec(state): state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[_permutationInv[byte]] + state_output[byte] = state[_PERMUTATION_INV[byte]] return state_output -def _OneRoundEGFNEnc(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) - state_permutation = _PermutationLayerEnc(state_linear) +def _one_round_egfn_enc(state, subtweakey): + state_non_linear = _non_linear_layer(state, subtweakey) + state_linear = _linear_layer(state_non_linear) + state_permutation = _permutation_layer_enc(state_linear) return state_permutation -def _LastRoundEGFN(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) + +def _last_round_egfn(state, subtweakey): + state_non_linear = _non_linear_layer(state, subtweakey) + state_linear = _linear_layer(state_non_linear) return state_linear -def _OneRoundEGFNDec(state, subtweakey): - state_non_linear = _NonLinearLayer(state, subtweakey) - state_linear = _LinearLayer(state_non_linear) - state_permutation = _PermutationLayerDec(state_linear) +def _one_round_egfn_dec(state, subtweakey): + state_non_linear = _non_linear_layer(state, subtweakey) + state_linear = _linear_layer(state_non_linear) + state_permutation = _permutation_layer_dec(state_linear) return state_permutation -def _Rounds(key_bytes): +def _rounds(key_bytes): rounds = { 128: 32, 192: 36, @@ -150,46 +148,43 @@ def _Rounds(key_bytes): return rounds[key_bytes*8] -################################################################################ - - def encrypt(tweak, key, message): - r = _Rounds(len(key)) + r = _rounds(len(key)) - tweakey = _BuildTweakey(tweak, key) - RTKs = _TweakeyScheduleWhole(tweakey, r) + tweakey = _build_tweakey(tweak, key) + RTKs = _tweakey_schedule_whole(tweakey, r) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state[byte] = message[byte] for i in range(0, r-1): - state_output = _OneRoundEGFNEnc(state, RTKs[i]) + state_output = _one_round_egfn_enc(state, RTKs[i]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = _LastRoundEGFN(state, RTKs[r-1]) + state_output = _last_round_egfn(state, RTKs[r-1]) return state_output def decrypt(tweak, key, cipher): - r = _Rounds(len(key)) + r = _rounds(len(key)) - tweakey = _BuildTweakey(tweak, key) - RTKs = _TweakeyScheduleWhole(tweakey, r) + tweakey = _build_tweakey(tweak, key) + RTKs = _tweakey_schedule_whole(tweakey, r) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES): state[byte] = cipher[byte] for i in range(0, r-1): - state_output = _OneRoundEGFNDec(state, RTKs[r-i-1]) + state_output = _one_round_egfn_dec(state, RTKs[r-i-1]) for byte in range(0, BLOCK_BYTES): state[byte] = state_output[byte] - state_output = _LastRoundEGFN(state, RTKs[0]) + state_output = _last_round_egfn(state, RTKs[0]) return state_output -- cgit v1.2.3 From 33c615feaaf148c099ee4299ad2c8a6f7e1778cf Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 15:19:15 +0100 Subject: [implem-python] Réécriture de certains range() dans tbc.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IME, itérer sur un range() est rarement la façon la plus expressive de faire les choses ; les alternatives imposent une structure qui rendent l'intention plus claire. E.g. quand on voit une compréhension, on comprend que l'auteur cherche à filtrer et/ou transformer ce sur quoi il itère. Réutilisation de xor_state(), renommé xor() puisqu'il sert dans plusieurs situations. Séparation de ce xor() et des fonctions communes aux modes authentifiés pour éviter un import circulaire. --- src/add_python/lilliput/ae_common.py | 89 ++++++++++++++++++++++++++++++++ src/add_python/lilliput/ae_mode_1.py | 20 ++++---- src/add_python/lilliput/ae_mode_2.py | 14 +++--- src/add_python/lilliput/helpers.py | 94 +--------------------------------- src/add_python/lilliput/tbc.py | 98 ++++++++++++------------------------ 5 files changed, 140 insertions(+), 175 deletions(-) create mode 100644 src/add_python/lilliput/ae_common.py diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py new file mode 100644 index 0000000..f212353 --- /dev/null +++ b/src/add_python/lilliput/ae_common.py @@ -0,0 +1,89 @@ +from .constants import BLOCK_BITS, BLOCK_BYTES +from .helpers import xor +from . import tbc + + +def bytes_to_block_matrix(array): + vector = list(array) + + blocks_nb = len(vector)//BLOCK_BYTES + + block_starts = ( + i*BLOCK_BYTES for i in range(blocks_nb) + ) + + matrix = [ + vector[start:start+BLOCK_BYTES] for start in block_starts + ] + + padding_len = len(vector)%BLOCK_BYTES + + if padding_len > 0: + padding = vector[-padding_len:] + matrix.append(padding) + + return matrix + + +def block_matrix_to_bytes(matrix): + return bytes(byte for block in matrix for byte in block) + + +def pad10(X): + zeroes = [0] * (BLOCK_BYTES-len(X)-1) + return zeroes + [0b10000000] + X + + +def _tweak_associated_data(t, i, padded): + t_bytes = t//8 + tweak = [0]*(t_bytes) + + mask = 0xff + for byte in range(t_bytes-1): + tweak[byte] = (i & mask) >> (byte * 8) + mask = mask << 8 + + mask = (0xf << (8 * t_bytes-1)) + tweak[-1] = (i & mask) >> ((t_bytes-1)*8) + if not padded: + tweak[-1] |= 0x20 + else: + tweak[-1] |= 0x60 + + return tweak + + +def build_auth(t, A, key): + Auth = [0 for byte in range(0, BLOCK_BYTES)] + l_a = len(A)//BLOCK_BYTES + need_padding = len(A)%BLOCK_BYTES > 0 + + A = bytes_to_block_matrix(A) + + for i in range(0, l_a): + tweak = _tweak_associated_data(t, i, padded=False) + enc = tbc.encrypt(tweak, key, A[i]) + Auth = xor(Auth, enc) + + if not need_padding: + return Auth + + tweak = _tweak_associated_data(t, l_a, padded=True) + ad_padded = pad10(A[l_a]) + enc = tbc.encrypt(tweak, key, ad_padded) + Auth = xor(Auth, enc) + + return Auth + + +class TagValidationError(Exception): + def __init__(self, announced, computed): + msg = '\n'.join(( + 'Invalid tag:', + announced.hex().upper()+' (announced)', + computed.hex().upper()+' (computed)' + )) + + super().__init__(msg) + self._announced = announced + self._computed = computed diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index cc550e8..efa0b6f 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -21,13 +21,13 @@ using Lilliput-AE's nonce-respecting mode based on ΘCB3. from enum import Enum from .constants import BLOCK_BYTES, NONCE_BYTES -from .helpers import ( +from .ae_common import ( bytes_to_block_matrix, block_matrix_to_bytes, build_auth, pad10, TagValidationError, - xor_state + xor ) from . import tbc @@ -92,7 +92,7 @@ def _treat_message_enc(M, N, key): C = [] for j in range(0, l): - checksum = xor_state(checksum, M[j]) + checksum = xor(checksum, M[j]) tweak = _tweak_message(N, j, _MessageTweak.BLOCK) C.append(tbc.encrypt(tweak, key, M[j])) @@ -102,12 +102,12 @@ def _treat_message_enc(M, N, key): else: m_padded = pad10(M[l]) - checksum = xor_state(checksum, m_padded) + checksum = xor(checksum, m_padded) tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) lower_part = _low_part(pad, padding_bytes*8) - C.append(xor_state(M[l], lower_part)) + C.append(xor(M[l], lower_part)) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -126,7 +126,7 @@ def _treat_message_dec(C, N, key): for j in range(0, l): tweak = _tweak_message(N, j, _MessageTweak.BLOCK) M.append(tbc.decrypt(tweak, key, C[j])) - checksum = xor_state(checksum, M[j]) + checksum = xor(checksum, M[j]) if padding_bytes == 0: tweak = _tweak_message(N, l, _MessageTweak.NO_PADDING) @@ -136,10 +136,10 @@ def _treat_message_dec(C, N, key): tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) lower_part = _low_part(pad, padding_bytes*8) - M.append(xor_state(C[l], lower_part)) + M.append(xor(C[l], lower_part)) m_padded = pad10(M[l]) - checksum = xor_state(checksum, m_padded) + checksum = xor(checksum, m_padded) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -151,7 +151,7 @@ def encrypt(A, M, N, key): Auth = build_auth(TWEAK_BITS, A, K) (Final, C) = _treat_message_enc(M, N, K) - tag = xor_state(Auth, Final) + tag = xor(Auth, Final) return block_matrix_to_bytes(C), bytes(tag) @@ -162,7 +162,7 @@ def decrypt(A, C, N, tag, key): Auth = build_auth(TWEAK_BITS, A, K) (Final, M) = _treat_message_dec(C, N, K) - tag2 = xor_state(Auth, Final) + tag2 = xor(Auth, Final) if tag != tag2: raise TagValidationError(tag, tag2) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 4d5e499..91c53f3 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -19,13 +19,13 @@ using Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. """ from .constants import BLOCK_BYTES -from .helpers import ( +from .ae_common import ( bytes_to_block_matrix, block_matrix_to_bytes, build_auth, pad10, TagValidationError, - xor_state + xor ) from . import tbc @@ -62,7 +62,7 @@ def _add_tag_j(tag, j): for byte in range(0, TWEAK_BYTES): array_j[byte] = (j >> (byte * 8)) - xorr = xor_state(tag, array_j) + xorr = xor(tag, array_j) xorr[TWEAK_BYTES - 1] |= 0x80 @@ -79,13 +79,13 @@ def _message_auth_tag(M, N, Auth, key): for j in range(0, l): tweak = _tweak_tag(j, False) encryption = tbc.encrypt(tweak, key, M[j]) - tag = xor_state(tag, encryption) + tag = xor(tag, encryption) if need_padding: tweak = _tweak_tag(l, True) m_padded = pad10(M[l]) encryption = tbc.encrypt(tweak, key, m_padded) - tag = xor_state(tag, encryption) + tag = xor(tag, encryption) tweak = _tweak_tag_end(N) encryption = tbc.encrypt(tweak, key, tag) @@ -105,13 +105,13 @@ def _message_encryption(M, N, tag, key): tweak = _add_tag_j(tag, j) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(xor_state(M[j], encryption)) + C.append(xor(M[j], encryption)) if need_padding: tweak = _add_tag_j(tag, l) padded_nonce = list(N) + [0x00] encryption = tbc.encrypt(tweak, key, padded_nonce) - C.append(xor_state(M[l], encryption)) + C.append(xor(M[l], encryption)) return C diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py index 65989d0..048aac7 100644 --- a/src/add_python/lilliput/helpers.py +++ b/src/add_python/lilliput/helpers.py @@ -1,92 +1,2 @@ -from .constants import BLOCK_BITS, BLOCK_BYTES -from . import tbc - - -def bytes_to_block_matrix(array): - vector = list(array) - - blocks_nb = len(vector)//BLOCK_BYTES - - block_starts = ( - i*BLOCK_BYTES for i in range(blocks_nb) - ) - - matrix = [ - vector[start:start+BLOCK_BYTES] for start in block_starts - ] - - padding_len = len(vector)%BLOCK_BYTES - - if padding_len > 0: - padding = vector[-padding_len:] - matrix.append(padding) - - return matrix - - -def block_matrix_to_bytes(matrix): - return bytes(byte for block in matrix for byte in block) - - -def xor_state(state1, state2): - return [s1^s2 for (s1, s2) in zip(state1, state2)] - - -def pad10(X): - zeroes = [0] * (BLOCK_BYTES-len(X)-1) - return zeroes + [0b10000000] + X - - -def _tweak_associated_data(t, i, padded): - t_bytes = t//8 - tweak = [0]*(t_bytes) - - mask = 0xff - for byte in range(t_bytes-1): - tweak[byte] = (i & mask) >> (byte * 8) - mask = mask << 8 - - mask = (0xf << (8 * t_bytes-1)) - tweak[-1] = (i & mask) >> ((t_bytes-1)*8) - if not padded: - tweak[-1] |= 0x20 - else: - tweak[-1] |= 0x60 - - return tweak - - -def build_auth(t, A, key): - Auth = [0 for byte in range(0, BLOCK_BYTES)] - l_a = len(A)//BLOCK_BYTES - need_padding = len(A)%BLOCK_BYTES > 0 - - A = bytes_to_block_matrix(A) - - for i in range(0, l_a): - tweak = _tweak_associated_data(t, i, padded=False) - enc = tbc.encrypt(tweak, key, A[i]) - Auth = xor_state(Auth, enc) - - if not need_padding: - return Auth - - tweak = _tweak_associated_data(t, l_a, padded=True) - ad_padded = pad10(A[l_a]) - enc = tbc.encrypt(tweak, key, ad_padded) - Auth = xor_state(Auth, enc) - - return Auth - - -class TagValidationError(Exception): - def __init__(self, announced, computed): - msg = '\n'.join(( - 'Invalid tag:', - announced.hex().upper()+' (announced)', - computed.hex().upper()+' (computed)' - )) - - super().__init__(msg) - self._announced = announced - self._computed = computed +def xor(array1, array2): + return [a1^a2 for (a1, a2) in zip(array1, array2)] diff --git a/src/add_python/lilliput/tbc.py b/src/add_python/lilliput/tbc.py index c607e45..0772853 100644 --- a/src/add_python/lilliput/tbc.py +++ b/src/add_python/lilliput/tbc.py @@ -18,6 +18,7 @@ This module provides functions to encrypt and decrypt blocks of 128 bits. """ from .constants import BLOCK_BYTES, SBOX +from .helpers import xor from .multiplications import ALPHAS @@ -25,6 +26,13 @@ _PERMUTATION = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] _PERMUTATION_INV = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] +_ROUNDS = { + 128: 32, + 192: 36, + 256: 42 +} + + def _build_tweakey(tweak, key): return tweak+key @@ -55,8 +63,6 @@ def _subtweakey_extract(tweakey, Ci): def _tweakey_schedule_whole(tweakey, r): - # Store the initial tweakey in TKs[0], and the corresponding round tweakey - # in RTKs[0]. TKs = [tweakey] RTKs = [_subtweakey_extract(TKs[0], 0)] @@ -68,28 +74,21 @@ def _tweakey_schedule_whole(tweakey, r): def _non_linear_layer(state, subtweakey): + variables_xored = xor(state, subtweakey) - variables_xored = [0 for byte in range(0, 8)] - for byte in range(0,8): - variables_xored[byte] = state[byte] ^ subtweakey[byte] - - variables_sboxed = [0 for byte in range(0, 8)] - for byte in range(0, 8): - variables_sboxed[byte] = SBOX[variables_xored[byte]] + variables_sboxed = [ + SBOX[variables_xored[i]] for i in range(8) + ] - state_output = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0,BLOCK_BYTES): - state_output[byte] = state[byte] - for byte in range(0, 8): - state_output[15 - byte] ^= variables_sboxed[byte] + state_output = state + for i in range(8): + state_output[15-i] ^= variables_sboxed[i] return state_output def _linear_layer(state): - state_output = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[byte] + state_output = state for byte in range(1, 8): state_output[15] ^= state[byte] @@ -100,26 +99,16 @@ def _linear_layer(state): return state_output -def _permutation_layer_enc(state): - state_output = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[_PERMUTATION[byte]] - - return state_output - - -def _permutation_layer_dec(state): - state_output = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - state_output[byte] = state[_PERMUTATION_INV[byte]] - - return state_output +def _permutation_layer(state, p): + return [ + state[p[i]] for i in range(BLOCK_BYTES) + ] def _one_round_egfn_enc(state, subtweakey): state_non_linear = _non_linear_layer(state, subtweakey) state_linear = _linear_layer(state_non_linear) - state_permutation = _permutation_layer_enc(state_linear) + state_permutation = _permutation_layer(state_linear, _PERMUTATION) return state_permutation @@ -134,57 +123,34 @@ def _last_round_egfn(state, subtweakey): def _one_round_egfn_dec(state, subtweakey): state_non_linear = _non_linear_layer(state, subtweakey) state_linear = _linear_layer(state_non_linear) - state_permutation = _permutation_layer_dec(state_linear) + state_permutation = _permutation_layer(state_linear, _PERMUTATION_INV) return state_permutation -def _rounds(key_bytes): - rounds = { - 128: 32, - 192: 36, - 256: 42 - } - return rounds[key_bytes*8] - - def encrypt(tweak, key, message): - r = _rounds(len(key)) + r = _ROUNDS[8*len(key)] tweakey = _build_tweakey(tweak, key) RTKs = _tweakey_schedule_whole(tweakey, r) - state = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - state[byte] = message[byte] - - for i in range(0, r-1): - state_output = _one_round_egfn_enc(state, RTKs[i]) - - for byte in range(0, BLOCK_BYTES): - state[byte] = state_output[byte] + state = message - state_output = _last_round_egfn(state, RTKs[r-1]) + for i in range(r-1): + state = _one_round_egfn_enc(state, RTKs[i]) - return state_output + return _last_round_egfn(state, RTKs[r-1]) def decrypt(tweak, key, cipher): - r = _rounds(len(key)) + r = _ROUNDS[8*len(key)] tweakey = _build_tweakey(tweak, key) RTKs = _tweakey_schedule_whole(tweakey, r) - state = [0 for byte in range(0, BLOCK_BYTES)] - for byte in range(0, BLOCK_BYTES): - state[byte] = cipher[byte] - - for i in range(0, r-1): - state_output = _one_round_egfn_dec(state, RTKs[r-i-1]) + state = cipher - for byte in range(0, BLOCK_BYTES): - state[byte] = state_output[byte] + for i in range(r-1): + state = _one_round_egfn_dec(state, RTKs[r-i-1]) - state_output = _last_round_egfn(state, RTKs[0]) - - return state_output + return _last_round_egfn(state, RTKs[0]) -- cgit v1.2.3 From 482091fe1812cf68789a65d7a8b8df9d1be551d2 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 16:38:18 +0100 Subject: [implem-python] Réécriture de certains range() dans ae_common.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et réutilisation de fonctions Python natives. --- src/add_python/lilliput/ae_common.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index f212353..033b5b0 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -35,32 +35,26 @@ def pad10(X): def _tweak_associated_data(t, i, padded): - t_bytes = t//8 - tweak = [0]*(t_bytes) + tweak = list(i.to_bytes(t//8, 'little')) - mask = 0xff - for byte in range(t_bytes-1): - tweak[byte] = (i & mask) >> (byte * 8) - mask = mask << 8 + prefix = 0b0110 if padded else 0b0010 - mask = (0xf << (8 * t_bytes-1)) - tweak[-1] = (i & mask) >> ((t_bytes-1)*8) - if not padded: - tweak[-1] |= 0x20 - else: - tweak[-1] |= 0x60 + # Clear upper 4 bits and set them to prefix. + tweak[-1] &= 0b00001111 + tweak[-1] = prefix << 4 return tweak def build_auth(t, A, key): - Auth = [0 for byte in range(0, BLOCK_BYTES)] + Auth = [0]*BLOCK_BYTES + l_a = len(A)//BLOCK_BYTES need_padding = len(A)%BLOCK_BYTES > 0 A = bytes_to_block_matrix(A) - for i in range(0, l_a): + for i in range(l_a): tweak = _tweak_associated_data(t, i, padded=False) enc = tbc.encrypt(tweak, key, A[i]) Auth = xor(Auth, enc) -- cgit v1.2.3 From 97db0c6e5dc3576cdcca339acf3bb33b698dccd0 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 16:48:46 +0100 Subject: [implem-python] Génération des vecteurs dans une fonction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pour que ce soit plus simple de remplacer la boucle par generate 2 128 generate 1 256 … ce qui prend 6 minutes au lieu de 20 sur ma machine \o/ --- test/python/generate-vectors.sh | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/test/python/generate-vectors.sh b/test/python/generate-vectors.sh index e328c67..d37f15f 100755 --- a/test/python/generate-vectors.sh +++ b/test/python/generate-vectors.sh @@ -10,22 +10,32 @@ 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) +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 +generate () +{ + local mode=$1 + local keylen=$2 + + 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 + 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} + dest=${CRYPTO_AEAD}/${NAMES[${mode}]}${keylen}v1 + mv LWC_AEAD_KAT_${keylen}_120.txt ${dest} +} + + +for mode in 1 2 +do + for keylen in 128 192 256 + do + generate ${mode} ${keylen} done done -- cgit v1.2.3 From 62cff183e2e9e67549db0461589a05138ce2ed00 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2019 17:33:38 +0100 Subject: [implem-python] Remplacement de _low_part par du "tranchage" natif --- src/add_python/lilliput/ae_mode_1.py | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index efa0b6f..a5ba7c8 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -36,30 +36,6 @@ TWEAK_BITS = 192 TWEAK_BYTES = TWEAK_BITS//8 -def _low_part(array, number_bits): - shifted = 0 - for byte in range(0, len(array)): - shifted |= (array[byte] << (8 * byte)) - - mask = 0 - for bit in range(0, number_bits): - mask |= (0x1 << bit) - - lower_part = shifted & mask - - will_pad = 0 - if number_bits % 8 != 0: - will_pad = 1 - - lower_part_byte = [] - nb_bytes = number_bits//8 + will_pad - for byte in range(nb_bytes): - lower_part_byte.append(lower_part & 0xff) - lower_part = lower_part >> 8 - - return lower_part_byte - - class _MessageTweak(Enum): BLOCK = 0b0000 NO_PADDING = 0b0001 @@ -106,7 +82,7 @@ def _treat_message_enc(M, N, key): tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _low_part(pad, padding_bytes*8) + lower_part = pad[:padding_bytes] C.append(xor(M[l], lower_part)) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -135,7 +111,7 @@ def _treat_message_dec(C, N, key): else: tweak = _tweak_message(N, l, _MessageTweak.PAD) pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = _low_part(pad, padding_bytes*8) + lower_part = pad[:padding_bytes] M.append(xor(C[l], lower_part)) m_padded = pad10(M[l]) -- cgit v1.2.3 From 07af965f2687105324e0142270a9e194a5ae6af5 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 08:38:01 +0100 Subject: [implem-python] Ajout des entêtes manquants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_common.py | 17 +++++++++++++++ src/add_python/lilliput/helpers.py | 17 +++++++++++++++ src/add_python/lilliput/multiplications.py | 19 +++++++++++++++++ test/python/crypto_aead.py | 33 +++++++++++++++++++++++------- test/python/genkat_aead.py | 17 ++++++++++++++- 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index 033b5b0..83db056 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -1,3 +1,20 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Helper functions used in both Lilliput-I and Lilliput-II.""" + + from .constants import BLOCK_BITS, BLOCK_BYTES from .helpers import xor from . import tbc diff --git a/src/add_python/lilliput/helpers.py b/src/add_python/lilliput/helpers.py index 048aac7..41f75a6 100644 --- a/src/add_python/lilliput/helpers.py +++ b/src/add_python/lilliput/helpers.py @@ -1,2 +1,19 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Helper functions used in Lilliput-AE.""" + + def xor(array1, array2): return [a1^a2 for (a1, a2) in zip(array1, array2)] diff --git a/src/add_python/lilliput/multiplications.py b/src/add_python/lilliput/multiplications.py index dfdc3cb..2dea948 100644 --- a/src/add_python/lilliput/multiplications.py +++ b/src/add_python/lilliput/multiplications.py @@ -1,3 +1,22 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# Léo Reynaud +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Multiplications for Lilliput-TBC's tweakey schedule. + +This module provides a list of functions implementing lane multiplications, +from ALPHAS[0] = α₀ = I to ALPHAS[6] = α₆ = M_R³. +""" def _multiply_M(lane): diff --git a/test/python/crypto_aead.py b/test/python/crypto_aead.py index 792369c..6a9b328 100644 --- a/test/python/crypto_aead.py +++ b/test/python/crypto_aead.py @@ -1,9 +1,29 @@ +# Implementation of the Lilliput-AE tweakable block cipher. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Python port of the crypto_aead API for Lilliput-AE.""" + import lilliput -from lilliput.constants import NONCE_BYTES as NPUBBYTES, TAG_BYTES -# Import KEYBYTES to expose it to genkat_aead. -# Import MODE to provide it to lilliput. -from parameters import KEYBYTES, MODE +from lilliput.constants import ( + NONCE_BYTES as NPUBBYTES, # Expose to genkat_aead. + TAG_BYTES +) + +from parameters import ( + KEYBYTES, # Expose to genkat_aead. + MODE +) def encrypt(m, ad, npub, k): @@ -12,7 +32,6 @@ def encrypt(m, ad, npub, k): def decrypt(c, ad, npub, k): - clen = len(c)-TAG_BYTES - ctext = c[:clen] - tag = c[clen:] + ctext = c[:-TAG_BYTES] + tag = c[-TAG_BYTES:] return lilliput.decrypt(ctext, tag, ad, k, npub, MODE) diff --git a/test/python/genkat_aead.py b/test/python/genkat_aead.py index 5e953c4..db3a89c 100755 --- a/test/python/genkat_aead.py +++ b/test/python/genkat_aead.py @@ -1,11 +1,26 @@ #!/usr/bin/env python3 +# Python port of genkat_aead.c. +# +# Authors, hereby denoted as "the implementer": +# Kévin Le Gouguec, +# 2019. +# +# For more information, feedback or questions, refer to our website: +# https://paclido.fr/lilliput-ae +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +"""Python port of the genkat_aead.c program.""" + import crypto_aead class DecryptionError(Exception): def __init__(self): - super().__init__('crypto_aead_decrypt did not recover the plaintext') + super().__init__('crypto_aead.decrypt did not recover the plaintext') MAX_MESSAGE_LENGTH = 32 -- cgit v1.2.3 From 0d0ecee46d6e5d47ff390cbaa254bf0d560d504f Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:10:33 +0100 Subject: [implem-python] Ajustements de forme --- src/add_python/lilliput/ae_common.py | 6 +++++- src/add_python/lilliput/ae_mode_1.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py index 83db056..b94be1b 100644 --- a/src/add_python/lilliput/ae_common.py +++ b/src/add_python/lilliput/ae_common.py @@ -51,8 +51,12 @@ def pad10(X): return zeroes + [0b10000000] + X +def integer_to_byte_array(i, n): + return list(i.to_bytes(n, 'little')) + + def _tweak_associated_data(t, i, padded): - tweak = list(i.to_bytes(t//8, 'little')) + tweak = integer_to_byte_array(i, t//8) prefix = 0b0110 if padded else 0b0010 diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index a5ba7c8..b07adf6 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -87,7 +87,7 @@ def _treat_message_enc(M, N, key): tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) - return (Final, C) + return Final, C def _treat_message_dec(C, N, key): @@ -119,7 +119,7 @@ def _treat_message_dec(C, N, key): tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) - return (Final, M) + return Final, M def encrypt(A, M, N, key): -- cgit v1.2.3 From 2cdc379dc0d4a260c5ca20619c892bdfbb6c0248 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:30:23 +0100 Subject: [implem-python] Remplacement de _tweak_tag_end par une concaténation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_2.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 91c53f3..bf09731 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -47,16 +47,6 @@ def _tweak_tag(j, padded): return tweak -def _tweak_tag_end(N): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - - for byte in range(0, TWEAK_BYTES - 1): - tweak[byte] = N[byte] - tweak[TWEAK_BYTES - 1] = 0x10 - - return tweak - - def _add_tag_j(tag, j): array_j = [0 for byte in range(0, TWEAK_BYTES)] for byte in range(0, TWEAK_BYTES): @@ -87,7 +77,7 @@ def _message_auth_tag(M, N, Auth, key): encryption = tbc.encrypt(tweak, key, m_padded) tag = xor(tag, encryption) - tweak = _tweak_tag_end(N) + tweak = N + [0b00010000] encryption = tbc.encrypt(tweak, key, tag) tag = encryption @@ -103,13 +93,13 @@ def _message_encryption(M, N, tag, key): for j in range(0, l): tweak = _add_tag_j(tag, j) - padded_nonce = list(N) + [0x00] + padded_nonce = N + [0b00000000] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(xor(M[j], encryption)) if need_padding: tweak = _add_tag_j(tag, l) - padded_nonce = list(N) + [0x00] + padded_nonce = N + [0b00000000] encryption = tbc.encrypt(tweak, key, padded_nonce) C.append(xor(M[l], encryption)) @@ -119,6 +109,7 @@ def _message_encryption(M, N, tag, key): ################################################################################ def encrypt(A, M, N, key): K = list(key) + N = list(N) Auth = build_auth(TWEAK_BITS, A, K) tag = _message_auth_tag(M, N, Auth, K) @@ -129,6 +120,7 @@ def encrypt(A, M, N, key): def decrypt(A, C, N, tag, key): K = list(key) + N = list(N) tag = list(tag) M = block_matrix_to_bytes( -- cgit v1.2.3 From e96df775be1ab1553588bb0b81d02b9f6a3d19af Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:35:19 +0100 Subject: [implem-python] Simplification de _add_tag_j --- src/add_python/lilliput/ae_mode_2.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index bf09731..1878060 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -22,6 +22,7 @@ from .constants import BLOCK_BYTES from .ae_common import ( bytes_to_block_matrix, block_matrix_to_bytes, + integer_to_byte_array, build_auth, pad10, TagValidationError, @@ -48,15 +49,11 @@ def _tweak_tag(j, padded): def _add_tag_j(tag, j): - array_j = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(0, TWEAK_BYTES): - array_j[byte] = (j >> (byte * 8)) + array_j = integer_to_byte_array(j, TWEAK_BYTES) + tweak = xor(tag, array_j) + tweak[-1] |= 0b10000000 - xorr = xor(tag, array_j) - - xorr[TWEAK_BYTES - 1] |= 0x80 - - return xorr + return tweak def _message_auth_tag(M, N, Auth, key): -- cgit v1.2.3 From b6186739572125788c9ae0c528458eaaa7361ce9 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:42:23 +0100 Subject: [implem-python] Simplification de _tweak_tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Très similaire à ae_common._tweak_associated_data. --- src/add_python/lilliput/ae_mode_2.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 1878060..a486bc9 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -36,14 +36,13 @@ TWEAK_BYTES = TWEAK_BITS//8 def _tweak_tag(j, padded): - tweak = [0 for byte in range(0, TWEAK_BYTES)] + tweak = integer_to_byte_array(j, TWEAK_BYTES) - tweak[TWEAK_BYTES - 1] |= ((j >> 120) & 0xf) - for byte in range(TWEAK_BYTES - 2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff + prefix = 0b0100 if padded else 0b0000 - if padded: - tweak[TWEAK_BYTES - 1] |= 0x40 + # Clear upper 4 bits and set them to prefix. + tweak[-1] &= 0b00001111 + tweak[-1] = prefix << 4 return tweak -- cgit v1.2.3 From d6164fddbb09f0dc5248b341e97610957f80f8f8 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 09:45:24 +0100 Subject: [implem-python] Suppression de variables intermédiaires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le code résultant ressemble plus à ce qui est décrit dans les algorithmes 3 et 4. --- src/add_python/lilliput/ae_mode_2.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index a486bc9..2349757 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -69,8 +69,7 @@ def _message_auth_tag(M, N, Auth, key): if need_padding: tweak = _tweak_tag(l, True) - m_padded = pad10(M[l]) - encryption = tbc.encrypt(tweak, key, m_padded) + encryption = tbc.encrypt(tweak, key, pad10(M[l])) tag = xor(tag, encryption) tweak = N + [0b00010000] @@ -89,14 +88,12 @@ def _message_encryption(M, N, tag, key): for j in range(0, l): tweak = _add_tag_j(tag, j) - padded_nonce = N + [0b00000000] - encryption = tbc.encrypt(tweak, key, padded_nonce) + encryption = tbc.encrypt(tweak, key, N+[0b00000000]) C.append(xor(M[j], encryption)) if need_padding: tweak = _add_tag_j(tag, l) - padded_nonce = N + [0b00000000] - encryption = tbc.encrypt(tweak, key, padded_nonce) + encryption = tbc.encrypt(tweak, key, N+[0b00000000]) C.append(xor(M[l], encryption)) return C -- cgit v1.2.3 From e9682e5ff9946a018e00f513f58b7c7651708a63 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:35:27 +0100 Subject: [implem-python] Construction de _tweak_message par concaténation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et petits nettoyages par-ci par-là. --- src/add_python/lilliput/__init__.py | 6 +++--- src/add_python/lilliput/ae_mode_1.py | 41 +++++++++++++++++++++++++----------- src/add_python/lilliput/constants.py | 2 +- test/python/crypto_aead.py | 5 ++++- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/add_python/lilliput/__init__.py b/src/add_python/lilliput/__init__.py index dc193c6..870e485 100644 --- a/src/add_python/lilliput/__init__.py +++ b/src/add_python/lilliput/__init__.py @@ -26,7 +26,7 @@ The "mode" argument can be either of the following integers: from . import ae_mode_1 from . import ae_mode_2 -from .constants import NONCE_BYTES +from .constants import NONCE_BITS _AE_MODES = { @@ -43,8 +43,8 @@ def _check_inputs(key, mode, nonce): if mode not in _AE_MODES: raise ValueError('invalid mode: {} not in {}'.format(mode, tuple(_AE_MODES))) - if len(nonce) != NONCE_BYTES: - raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BYTES, len(nonce))) + if len(nonce)*8 != NONCE_BITS: + raise ValueError('invalid nonce size: expecting {}, have {}'.format(NONCE_BITS, len(nonce)*8)) def encrypt(plaintext, adata, key, nonce, mode): diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index b07adf6..1a3c39e 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -20,11 +20,12 @@ using Lilliput-AE's nonce-respecting mode based on ΘCB3. from enum import Enum -from .constants import BLOCK_BYTES, NONCE_BYTES +from .constants import BLOCK_BYTES, NONCE_BITS from .ae_common import ( bytes_to_block_matrix, block_matrix_to_bytes, build_auth, + integer_to_byte_array, pad10, TagValidationError, xor @@ -43,19 +44,33 @@ class _MessageTweak(Enum): FINAL = 0b0101 +def _upper_nibble(i): + return i >> 4 + + +def _lower_nibble(i): + return i & 0b00001111 + + +def _byte_from_nibbles(lower, upper): + return upper<<4 | lower + + def _tweak_message(N, j, padding): - tweak = [0 for byte in range(0, TWEAK_BYTES)] - for byte in range(NONCE_BYTES-1, -1, -1): - tweak[byte + (TWEAK_BYTES-NONCE_BYTES)] |= (N[byte] & 0xf0) >> 4 - tweak[byte + (TWEAK_BYTES-NONCE_BYTES-1)] |= (N[byte] & 0x0f) << 4 + j = integer_to_byte_array(j, (TWEAK_BITS-NONCE_BITS-4)//8+1) + + middle_byte = _byte_from_nibbles( + _lower_nibble(j[-1]), _lower_nibble(N[0]) + ) - tweak[TWEAK_BYTES-NONCE_BYTES-1] |= ((j >> 64) & 0xf) - for byte in range(TWEAK_BYTES-NONCE_BYTES-2, -1, -1): - tweak[byte] = (j >> (8 * byte)) & 0xff + shifted_N = [ + _byte_from_nibbles(_upper_nibble(N[i-1]), _lower_nibble(N[i])) + for i in range(1, NONCE_BITS//8) + ] - tweak[-1] |= padding.value<<4 + last_byte = _byte_from_nibbles(_upper_nibble(N[-1]), padding.value) - return tweak + return j[:-1] + [middle_byte] + shifted_N + [last_byte] def _treat_message_enc(M, N, key): @@ -124,9 +139,10 @@ def _treat_message_dec(C, N, key): def encrypt(A, M, N, key): K = list(key) + N = list(N) Auth = build_auth(TWEAK_BITS, A, K) - (Final, C) = _treat_message_enc(M, N, K) + Final, C = _treat_message_enc(M, N, K) tag = xor(Auth, Final) return block_matrix_to_bytes(C), bytes(tag) @@ -134,10 +150,11 @@ def encrypt(A, M, N, key): def decrypt(A, C, N, tag, key): K = list(key) + N = list(N) tag = list(tag) Auth = build_auth(TWEAK_BITS, A, K) - (Final, M) = _treat_message_dec(C, N, K) + Final, M = _treat_message_dec(C, N, K) tag2 = xor(Auth, Final) if tag != tag2: diff --git a/src/add_python/lilliput/constants.py b/src/add_python/lilliput/constants.py index 5e07e96..e69ca46 100644 --- a/src/add_python/lilliput/constants.py +++ b/src/add_python/lilliput/constants.py @@ -1,6 +1,6 @@ BLOCK_BITS = 128 BLOCK_BYTES = BLOCK_BITS//8 -NONCE_BYTES = 15 +NONCE_BITS = 120 TAG_BYTES = 16 diff --git a/test/python/crypto_aead.py b/test/python/crypto_aead.py index 6a9b328..d2f1896 100644 --- a/test/python/crypto_aead.py +++ b/test/python/crypto_aead.py @@ -16,7 +16,7 @@ import lilliput from lilliput.constants import ( - NONCE_BYTES as NPUBBYTES, # Expose to genkat_aead. + NONCE_BITS, TAG_BYTES ) @@ -26,6 +26,9 @@ from parameters import ( ) +NPUBBYTES = NONCE_BITS//8 + + def encrypt(m, ad, npub, k): c, tag = lilliput.encrypt(m, ad, k, npub, MODE) return c+tag -- cgit v1.2.3 From f468f2ca79e480fc058d37c338eb756ef88779f6 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:36:21 +0100 Subject: [implem-python] Suppression d'une ligne de '#' --- src/add_python/lilliput/ae_mode_2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/add_python/lilliput/ae_mode_2.py b/src/add_python/lilliput/ae_mode_2.py index 2349757..79d1bcd 100644 --- a/src/add_python/lilliput/ae_mode_2.py +++ b/src/add_python/lilliput/ae_mode_2.py @@ -99,7 +99,6 @@ def _message_encryption(M, N, tag, key): return C -################################################################################ def encrypt(A, M, N, key): K = list(key) N = list(N) -- cgit v1.2.3 From 5949f01e728c11990280f6b1d1a35c2153db4578 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:41:02 +0100 Subject: [implem-python] Retrait de range()s et variables intermédiaires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/add_python/lilliput/ae_mode_1.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 1a3c39e..23f4c7b 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -74,7 +74,7 @@ def _tweak_message(N, j, padding): def _treat_message_enc(M, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] + checksum = [0]*BLOCK_BYTES l = len(M)//BLOCK_BYTES padding_bytes = len(M)%BLOCK_BYTES @@ -95,10 +95,9 @@ def _treat_message_enc(M, N, key): m_padded = pad10(M[l]) checksum = xor(checksum, m_padded) tweak = _tweak_message(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) + pad = tbc.encrypt(tweak, key, [0]*BLOCK_BYTES) - lower_part = pad[:padding_bytes] - C.append(xor(M[l], lower_part)) + C.append(xor(M[l], pad[:padding_bytes])) tweak_final = _tweak_message(N, l+1, _MessageTweak.FINAL) Final = tbc.encrypt(tweak_final, key, checksum) @@ -106,7 +105,7 @@ def _treat_message_enc(M, N, key): def _treat_message_dec(C, N, key): - checksum = [0 for byte in range(0, BLOCK_BYTES)] + checksum = [0]*BLOCK_BYTES l = len(C)//BLOCK_BYTES padding_bytes = len(C)%BLOCK_BYTES @@ -125,9 +124,8 @@ def _treat_message_dec(C, N, key): else: tweak = _tweak_message(N, l, _MessageTweak.PAD) - pad = tbc.encrypt(tweak, key, [0 for byte in range(0, BLOCK_BYTES)]) - lower_part = pad[:padding_bytes] - M.append(xor(C[l], lower_part)) + pad = tbc.encrypt(tweak, key, [0]*BLOCK_BYTES) + M.append(xor(C[l], pad[:padding_bytes])) m_padded = pad10(M[l]) checksum = xor(checksum, m_padded) -- cgit v1.2.3 From fc64da017336c553a345fdb690a2e496a4aefff3 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Mon, 25 Mar 2019 10:59:24 +0100 Subject: [implem-python] Ajustements dans _tweak_message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hopefully, le résultat est plus clair en construisant le tweak par concaténations progressives. --- src/add_python/lilliput/ae_mode_1.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/add_python/lilliput/ae_mode_1.py b/src/add_python/lilliput/ae_mode_1.py index 23f4c7b..4a40b78 100644 --- a/src/add_python/lilliput/ae_mode_1.py +++ b/src/add_python/lilliput/ae_mode_1.py @@ -56,21 +56,25 @@ def _byte_from_nibbles(lower, upper): return upper<<4 | lower -def _tweak_message(N, j, padding): - j = integer_to_byte_array(j, (TWEAK_BITS-NONCE_BITS-4)//8+1) - - middle_byte = _byte_from_nibbles( - _lower_nibble(j[-1]), _lower_nibble(N[0]) - ) - - shifted_N = [ +def _tweak_message(N, j, prefix): + # j is encoded on 68 bits; get 72 and clear the upper 4. + j_len = (TWEAK_BITS-NONCE_BITS-4)//8 + 1 + tweak = integer_to_byte_array(j, j_len) + tweak[-1] &= 0b00001111 + + # Add nonce. + tweak[-1] |= _lower_nibble(N[0]) << 4 + tweak.extend( _byte_from_nibbles(_upper_nibble(N[i-1]), _lower_nibble(N[i])) for i in range(1, NONCE_BITS//8) - ] + ) - last_byte = _byte_from_nibbles(_upper_nibble(N[-1]), padding.value) + # Add last nibble from nonce and prefix. + tweak.append( + _byte_from_nibbles(_upper_nibble(N[-1]), prefix.value) + ) - return j[:-1] + [middle_byte] + shifted_N + [last_byte] + return tweak def _treat_message_enc(M, N, key): -- cgit v1.2.3