-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaes_cbc.py
134 lines (95 loc) · 3.3 KB
/
aes_cbc.py
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
128
129
130
131
132
133
134
if __name__ == "__main__":
from aes import aes
else:
from utils.aes import aes
class cbc:
BLOCK_SIZE = 16 # bytes
IV = bytes(16) # 16-byte Initialization Vector
key = b""
AES = """the aes object to be initialized later"""
def __init__(self, key):
self.key = key
self.AES = aes(self.key)
def pad(self, text):
"""pads the `text` so that its size equals self.BLOCK_SIZE
Args:
text (bytes): the text to pad
Returns:
bytes: the padded text
"""
length = len(text)
padLength = length - (length % self.BLOCK_SIZE)
padValue = hex(padLength).lstrip('0x')
if len(padValue) == 1:
padValue = '0' + padValue
padding = padValue * padLength
text += padding
return text
def xor(self, block1, block2):
"""performs XOR operation on two bytes of equal length
Args:
block1 (bytes): first block of bytes
block2 (bytes): second block of bytes
Returns:
bytes: the result of `block1` XOR `block2`
"""
hexBlock1 = block1.hex()
hexBlock2 = block2.hex()
deciBlock1 = int(hexBlock1, base=16)
deciBlock2 = int(hexBlock2, base=16)
result = deciBlock1 ^ deciBlock2
result = hex(result).lstrip('0x')
resultLength = len(result)
requiredLength = 2 * self.BLOCK_SIZE
if not resultLength == requiredLength:
padLength = requiredLength - resultLength
result = '0' * padLength + result
resultBlock = bytes.fromhex(result)
return resultBlock
def encrypt(self, plaintext):
"""perform encryption on `plaintext` using AES-128 in CBC mode
Args:
plaintext (bytes): the plaintext to encrypt
Returns:
bytes: the encrypted ciphertext
"""
text = plaintext
length = len(text)
if length % self.BLOCK_SIZE != 0:
text = self.pad(text)
addend = self.IV
ciphertext = b""
for i in range(0, length, self.BLOCK_SIZE):
block = text[i:i+self.BLOCK_SIZE]
xord = self.xor(block, addend)
encrypted = self.AES.encrypt(xord)
addend = encrypted
ciphertext += encrypted
return ciphertext
def decrypt(self, ciphertext):
"""decrypts the given `ciphertext`
Args:
ciphertext (bytes): the ciphertext to decrypt
Returns:
bytes: the plaintext after decryption
"""
text = ciphertext
length = len(text)
addend = self.IV
plaintext = b""
for i in range(0, length, self.BLOCK_SIZE):
block = ciphertext[i:i+self.BLOCK_SIZE]
decrypted = self.AES.decrypt(block)
xord = self.xor(addend, decrypted)
plaintext += xord
addend = block
return plaintext
if __name__ == "__main__":
key = b'Thats my Kung Fu'
plaintext = b'Two One Nine TwoNine Two Two One'
cipher = cbc(key)
ciphertext = cipher.encrypt(plaintext)
print(f"Ciphertext: {ciphertext}")
print('='*40)
recovered = cipher.decrypt(ciphertext)
print(f"Recovered: {recovered}")