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