summaryrefslogtreecommitdiff
path: root/src/add_python/lilliput/lilliput_ae_2.py
blob: 61aa86e16c707456f399567f313db0b0e5ae47c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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