Repository navigation
Expand file tree
/
Copy pathtea.py
More file actions
119 lines (95 loc) · 3.45 KB
/
Copy pathtea.py
File metadata and controls
119 lines (95 loc) · 3.45 KB
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
from __future__ import annotations
from abc import abstractmethod
from typing import Iterable, Sequence
from refinery.lib.chunks import pack, unpack
from refinery.lib.crypto import (
BlockCipher,
BlockCipherFactory,
BufferType,
CipherInterface,
CipherMode,
)
from refinery.lib.types import Param
from refinery.units.crypto.cipher import Arg, StandardBlockCipherUnit
class TEABase(BlockCipher):
block_size = 8
key_size = {16}
derived_key: list[int]
big_endian: bool
def __init__(
self,
key: BufferType, mode: CipherMode | None,
big_endian: bool = False
):
self.big_endian = big_endian
super().__init__(key, mode)
@property
def key(self):
return self.derived_key
@key.setter
def key(self, key):
self.derived_key = unpack(key, 4, self.big_endian)
@abstractmethod
def tea_encrypt(self, key: Sequence[int], block: Iterable[int]):
pass
def block_encrypt(self, data):
be = self.big_endian
blocks = list(unpack(data, 4, be))
blocks = self.tea_encrypt(self.derived_key, blocks)
return pack(blocks, 4, be)
@abstractmethod
def tea_decrypt(self, key: Sequence[int], block: Iterable[int]):
pass
def block_decrypt(self, data):
be = self.big_endian
blocks = list(unpack(data, 4, be))
blocks = self.tea_decrypt(self.derived_key, blocks)
return pack(blocks, 4, be)
class TEAWithRounds(TEABase):
rounds: int
def __init__(self, key, mode, rounds: int = 32, big_endian: bool = False):
super().__init__(key, mode, big_endian)
self.rounds = rounds
class TEA(TEAWithRounds):
"""
TEA encryption and decryption.
"""
def tea_encrypt(self, key: Sequence[int], block: Sequence[int]):
k0, k1, k2, k3 = key
v0, v1 = block
carry = 0
delta = 0x9E3779B9
for _ in range(self.rounds):
carry = (carry + delta) & 0xFFFFFFFF
v0 = v0 + (((v1 << 4) + k0) ^ (v1 + carry) ^ (v1 >> 5) + k1) & 0xFFFFFFFF
v1 = v1 + (((v0 << 4) + k2) ^ (v0 + carry) ^ (v0 >> 5) + k3) & 0xFFFFFFFF
return (v0, v1)
def tea_decrypt(self, key: Sequence[int], block: Sequence[int]):
rounds = self.rounds
k0, k1, k2, k3 = key
v0, v1 = block
delta = 0x9E3779B9
carry = (delta * rounds) & 0xFFFFFFFF
for _ in range(rounds):
v1 = v1 - (((v0 << 4) + k2) ^ (v0 + carry) ^ (v0 >> 5) + k3) & 0xFFFFFFFF
v0 = v0 - (((v1 << 4) + k0) ^ (v1 + carry) ^ (v1 >> 5) + k1) & 0xFFFFFFFF
carry = (carry - delta) & 0xFFFFFFFF
return (v0, v1)
class TEAUnit(StandardBlockCipherUnit):
def __init__(
self, key, iv=b'', padding=None, mode=None, raw=False,
swap: Param[bool, Arg.Switch('-s', help='Decode blocks as big endian rather than little endian.')] = False,
rounds: Param[int, Arg.Number('-k', help='Specify the number of rounds, {default} by default.')] = 32,
**more
):
super().__init__(key, iv=iv, padding=padding, mode=mode, raw=raw, swap=swap, rounds=rounds, **more)
@property
def block_size(self):
return 8
def _new_cipher(self, **optionals) -> CipherInterface:
return super()._new_cipher(
big_endian=self.args.swap, rounds=self.args.rounds, **optionals)
class tea(TEAUnit, cipher=BlockCipherFactory(TEA)):
"""
TEA encryption and decryption.
"""