summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Le Gouguec <kevin.legouguec@gmail.com>2019-03-23 23:54:35 +0100
committerKévin Le Gouguec <kevin.legouguec@gmail.com>2019-03-23 23:54:35 +0100
commitb46dd7acc86295d3072945f4a8098649d87504a2 (patch)
treeecb3b37c2c7c554bb8799deec92456ebc9598add
parent01957e0fa098071e10b074dfe477fcc7d687bb99 (diff)
downloadlilliput-ae-implem-b46dd7acc86295d3072945f4a8098649d87504a2.tar.xz
[implem-python] Documentation de Lilliput-Ⅰ et Lilliput-TBC
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…
-rw-r--r--src/add_python/lilliput/lilliput_ae_1.py52
-rw-r--r--src/add_python/lilliput/tbc.py105
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