1 from __future__ import unicode_literals
2
3 from math import ceil
4
5 from .compat import compat_b64decode
6 from .utils import bytes_to_intlist, intlist_to_bytes
7
8 BLOCK_SIZE_BYTES = 16
9
10
11 def pkcs7_padding(data):
12 """
13 PKCS#7 padding
14
15 @param {int[]} data cleartext
16 @returns {int[]} padding data
17 """
18
19 remaining_length = BLOCK_SIZE_BYTES - len(data) % BLOCK_SIZE_BYTES
20 return data + [remaining_length] * remaining_length
21
22
23 def aes_ctr_decrypt(data, key, counter):
24 """
25 Decrypt with aes in counter mode
26
27 @param {int[]} data cipher
28 @param {int[]} key 16/24/32-Byte cipher key
29 @param {instance} counter Instance whose next_value function (@returns {int[]} 16-Byte block)
30 returns the next counter block
31 @returns {int[]} decrypted data
32 """
33 expanded_key = key_expansion(key)
34 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
35
36 decrypted_data = []
37 for i in range(block_count):
38 counter_block = counter.next_value()
39 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
40 block += [0] * (BLOCK_SIZE_BYTES - len(block))
41
42 cipher_counter_block = aes_encrypt(counter_block, expanded_key)
43 decrypted_data += xor(block, cipher_counter_block)
44 decrypted_data = decrypted_data[:len(data)]
45
46 return decrypted_data
47
48
49 def aes_cbc_decrypt(data, key, iv):
50 """
51 Decrypt with aes in CBC mode
52
53 @param {int[]} data cipher
54 @param {int[]} key 16/24/32-Byte cipher key
55 @param {int[]} iv 16-Byte IV
56 @returns {int[]} decrypted data
57 """
58 expanded_key = key_expansion(key)
59 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
60
61 decrypted_data = []
62 previous_cipher_block = iv
63 for i in range(block_count):
64 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
65 block += [0] * (BLOCK_SIZE_BYTES - len(block))
66
67 decrypted_block = aes_decrypt(block, expanded_key)
68 decrypted_data += xor(decrypted_block, previous_cipher_block)
69 previous_cipher_block = block
70 decrypted_data = decrypted_data[:len(data)]
71
72 return decrypted_data
73
74
75 def aes_cbc_encrypt(data, key, iv):
76 """
77 Encrypt with aes in CBC mode. Using PKCS#7 padding
78
79 @param {int[]} data cleartext
80 @param {int[]} key 16/24/32-Byte cipher key
81 @param {int[]} iv 16-Byte IV
82 @returns {int[]} encrypted data
83 """
84 expanded_key = key_expansion(key)
85 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
86
87 encrypted_data = []
88 previous_cipher_block = iv
89 for i in range(block_count):
90 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
91 block = pkcs7_padding(block)
92 mixed_block = xor(block, previous_cipher_block)
93
94 encrypted_block = aes_encrypt(mixed_block, expanded_key)
95 encrypted_data += encrypted_block
96
97 previous_cipher_block = encrypted_block
98
99 return encrypted_data
100
101
102 def aes_ecb_encrypt(data, key):
103 """
104 Encrypt with aes in ECB mode. Using PKCS#7 padding
105
106 @param {int[]} data cleartext
107 @param {int[]} key 16/24/32-Byte cipher key
108 @returns {int[]} encrypted data
109 """
110 expanded_key = key_expansion(key)
111 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
112
113 encrypted_data = []
114 for i in range(block_count):
115 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
116 block = pkcs7_padding(block)
117
118 encrypted_block = aes_encrypt(block, expanded_key)
119 encrypted_data += encrypted_block
120
121 return encrypted_data
122
123
124 def key_expansion(data):
125 """
126 Generate key schedule
127
128 @param {int[]} data 16/24/32-Byte cipher key
129 @returns {int[]} 176/208/240-Byte expanded key
130 """
131 data = data[:] # copy
132 rcon_iteration = 1
133 key_size_bytes = len(data)
134 expanded_key_size_bytes = (key_size_bytes // 4 + 7) * BLOCK_SIZE_BYTES
135
136 while len(data) < expanded_key_size_bytes:
137 temp = data[-4:]
138 temp = key_schedule_core(temp, rcon_iteration)
139 rcon_iteration += 1
140 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
141
142 for _ in range(3):
143 temp = data[-4:]
144 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
145
146 if key_size_bytes == 32:
147 temp = data[-4:]
148 temp = sub_bytes(temp)
149 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
150
151 for _ in range(3 if key_size_bytes == 32 else 2 if key_size_bytes == 24 else 0):
152 temp = data[-4:]
153 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
154 data = data[:expanded_key_size_bytes]
155
156 return data
157
158
159 def aes_encrypt(data, expanded_key):
160 """
161 Encrypt one block with aes
162
163 @param {int[]} data 16-Byte state
164 @param {int[]} expanded_key 176/208/240-Byte expanded key
165 @returns {int[]} 16-Byte cipher
166 """
167 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
168
169 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
170 for i in range(1, rounds + 1):
171 data = sub_bytes(data)
172 data = shift_rows(data)
173 if i != rounds:
174 data = mix_columns(data)
175 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
176
177 return data
178
179
180 def aes_decrypt(data, expanded_key):
181 """
182 Decrypt one block with aes
183
184 @param {int[]} data 16-Byte cipher
185 @param {int[]} expanded_key 176/208/240-Byte expanded key
186 @returns {int[]} 16-Byte state
187 """
188 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
189
190 for i in range(rounds, 0, -1):
191 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
192 if i != rounds:
193 data = mix_columns_inv(data)
194 data = shift_rows_inv(data)
195 data = sub_bytes_inv(data)
196 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
197
198 return data
199
200
201 def aes_decrypt_text(data, password, key_size_bytes):
202 """
203 Decrypt text
204 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
205 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
206 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
207 - Mode of operation is 'counter'
208
209 @param {str} data Base64 encoded string
210 @param {str,unicode} password Password (will be encoded with utf-8)
211 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
212 @returns {str} Decrypted data
213 """
214 NONCE_LENGTH_BYTES = 8
215
216 data = bytes_to_intlist(compat_b64decode(data))
217 password = bytes_to_intlist(password.encode('utf-8'))
218
219 key = password[:key_size_bytes] + [0] * (key_size_bytes - len(password))
220 key = aes_encrypt(key[:BLOCK_SIZE_BYTES], key_expansion(key)) * (key_size_bytes // BLOCK_SIZE_BYTES)
221
222 nonce = data[:NONCE_LENGTH_BYTES]
223 cipher = data[NONCE_LENGTH_BYTES:]
224
225 class Counter(object):
226 __value = nonce + [0] * (BLOCK_SIZE_BYTES - NONCE_LENGTH_BYTES)
227
228 def next_value(self):
229 temp = self.__value
230 self.__value = inc(self.__value)
231 return temp
232
233 decrypted_data = aes_ctr_decrypt(cipher, key, Counter())
234 plaintext = intlist_to_bytes(decrypted_data)
235
236 return plaintext
237
238
239 RCON = (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
240 SBOX = (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
241 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
242 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
243 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
244 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
245 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
246 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
247 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
248 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
249 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
250 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
251 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
252 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
253 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
254 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
255 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
256 SBOX_INV = (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
257 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
258 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
259 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
260 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
261 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
262 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
263 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
264 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
265 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
266 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
267 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
268 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
269 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
270 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
271 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
272 MIX_COLUMN_MATRIX = ((0x2, 0x3, 0x1, 0x1),
273 (0x1, 0x2, 0x3, 0x1),
274 (0x1, 0x1, 0x2, 0x3),
275 (0x3, 0x1, 0x1, 0x2))
276 MIX_COLUMN_MATRIX_INV = ((0xE, 0xB, 0xD, 0x9),
277 (0x9, 0xE, 0xB, 0xD),
278 (0xD, 0x9, 0xE, 0xB),
279 (0xB, 0xD, 0x9, 0xE))
280 RIJNDAEL_EXP_TABLE = (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
281 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
282 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
283 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
284 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
285 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
286 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
287 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
288 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
289 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
290 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
291 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
292 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
293 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
294 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
295 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
296 RIJNDAEL_LOG_TABLE = (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
297 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
298 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
299 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
300 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
301 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
302 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
303 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
304 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
305 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
306 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
307 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
308 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
309 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
310 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
311 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
312
313
314 def sub_bytes(data):
315 return [SBOX[x] for x in data]
316
317
318 def sub_bytes_inv(data):
319 return [SBOX_INV[x] for x in data]
320
321
322 def rotate(data):
323 return data[1:] + [data[0]]
324
325
326 def key_schedule_core(data, rcon_iteration):
327 data = rotate(data)
328 data = sub_bytes(data)
329 data[0] = data[0] ^ RCON[rcon_iteration]
330
331 return data
332
333
334 def xor(data1, data2):
335 return [x ^ y for x, y in zip(data1, data2)]
336
337
338 def rijndael_mul(a, b):
339 if (a == 0 or b == 0):
340 return 0
341 return RIJNDAEL_EXP_TABLE[(RIJNDAEL_LOG_TABLE[a] + RIJNDAEL_LOG_TABLE[b]) % 0xFF]
342
343
344 def mix_column(data, matrix):
345 data_mixed = []
346 for row in range(4):
347 mixed = 0
348 for column in range(4):
349 # xor is (+) and (-)
350 mixed ^= rijndael_mul(data[column], matrix[row][column])
351 data_mixed.append(mixed)
352 return data_mixed
353
354
355 def mix_columns(data, matrix=MIX_COLUMN_MATRIX):
356 data_mixed = []
357 for i in range(4):
358 column = data[i * 4: (i + 1) * 4]
359 data_mixed += mix_column(column, matrix)
360 return data_mixed
361
362
363 def mix_columns_inv(data):
364 return mix_columns(data, MIX_COLUMN_MATRIX_INV)
365
366
367 def shift_rows(data):
368 data_shifted = []
369 for column in range(4):
370 for row in range(4):
371 data_shifted.append(data[((column + row) & 0b11) * 4 + row])
372 return data_shifted
373
374
375 def shift_rows_inv(data):
376 data_shifted = []
377 for column in range(4):
378 for row in range(4):
379 data_shifted.append(data[((column - row) & 0b11) * 4 + row])
380 return data_shifted
381
382
383 def inc(data):
384 data = data[:] # copy
385 for i in range(len(data) - 1, -1, -1):
386 if data[i] == 255:
387 data[i] = 0
388 else:
389 data[i] = data[i] + 1
390 break
391 return data
392
393
394 __all__ = ['aes_encrypt', 'key_expansion', 'aes_ctr_decrypt', 'aes_cbc_decrypt', 'aes_decrypt_text']
|