]> jfr.im git - yt-dlp.git/blob - yt_dlp/aes.py
[ie/youtube] Remove `android` from default clients (#9553)
[yt-dlp.git] / yt_dlp / aes.py
1 import base64
2 from math import ceil
3
4 from .compat import compat_ord
5 from .dependencies import Cryptodome
6 from .utils import bytes_to_intlist, intlist_to_bytes
7
8 if Cryptodome.AES:
9 def aes_cbc_decrypt_bytes(data, key, iv):
10 """ Decrypt bytes with AES-CBC using pycryptodome """
11 return Cryptodome.AES.new(key, Cryptodome.AES.MODE_CBC, iv).decrypt(data)
12
13 def aes_gcm_decrypt_and_verify_bytes(data, key, tag, nonce):
14 """ Decrypt bytes with AES-GCM using pycryptodome """
15 return Cryptodome.AES.new(key, Cryptodome.AES.MODE_GCM, nonce).decrypt_and_verify(data, tag)
16
17 else:
18 def aes_cbc_decrypt_bytes(data, key, iv):
19 """ Decrypt bytes with AES-CBC using native implementation since pycryptodome is unavailable """
20 return intlist_to_bytes(aes_cbc_decrypt(*map(bytes_to_intlist, (data, key, iv))))
21
22 def aes_gcm_decrypt_and_verify_bytes(data, key, tag, nonce):
23 """ Decrypt bytes with AES-GCM using native implementation since pycryptodome is unavailable """
24 return intlist_to_bytes(aes_gcm_decrypt_and_verify(*map(bytes_to_intlist, (data, key, tag, nonce))))
25
26
27 def aes_cbc_encrypt_bytes(data, key, iv, **kwargs):
28 return intlist_to_bytes(aes_cbc_encrypt(*map(bytes_to_intlist, (data, key, iv)), **kwargs))
29
30
31 BLOCK_SIZE_BYTES = 16
32
33
34 def unpad_pkcs7(data):
35 return data[:-compat_ord(data[-1])]
36
37
38 def pkcs7_padding(data):
39 """
40 PKCS#7 padding
41
42 @param {int[]} data cleartext
43 @returns {int[]} padding data
44 """
45
46 remaining_length = BLOCK_SIZE_BYTES - len(data) % BLOCK_SIZE_BYTES
47 return data + [remaining_length] * remaining_length
48
49
50 def pad_block(block, padding_mode):
51 """
52 Pad a block with the given padding mode
53 @param {int[]} block block to pad
54 @param padding_mode padding mode
55 """
56 padding_size = BLOCK_SIZE_BYTES - len(block)
57
58 PADDING_BYTE = {
59 'pkcs7': padding_size,
60 'iso7816': 0x0,
61 'whitespace': 0x20,
62 'zero': 0x0,
63 }
64
65 if padding_size < 0:
66 raise ValueError('Block size exceeded')
67 elif padding_mode not in PADDING_BYTE:
68 raise NotImplementedError(f'Padding mode {padding_mode} is not implemented')
69
70 if padding_mode == 'iso7816' and padding_size:
71 block = block + [0x80] # NB: += mutates list
72 padding_size -= 1
73
74 return block + [PADDING_BYTE[padding_mode]] * padding_size
75
76
77 def aes_ecb_encrypt(data, key, iv=None):
78 """
79 Encrypt with aes in ECB mode. Using PKCS#7 padding
80
81 @param {int[]} data cleartext
82 @param {int[]} key 16/24/32-Byte cipher key
83 @param {int[]} iv Unused for this mode
84 @returns {int[]} encrypted data
85 """
86 expanded_key = key_expansion(key)
87 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
88
89 encrypted_data = []
90 for i in range(block_count):
91 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
92 encrypted_data += aes_encrypt(pkcs7_padding(block), expanded_key)
93
94 return encrypted_data
95
96
97 def aes_ecb_decrypt(data, key, iv=None):
98 """
99 Decrypt with aes in ECB mode
100
101 @param {int[]} data cleartext
102 @param {int[]} key 16/24/32-Byte cipher key
103 @param {int[]} iv Unused for this mode
104 @returns {int[]} decrypted data
105 """
106 expanded_key = key_expansion(key)
107 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
108
109 encrypted_data = []
110 for i in range(block_count):
111 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
112 encrypted_data += aes_decrypt(block, expanded_key)
113 encrypted_data = encrypted_data[:len(data)]
114
115 return encrypted_data
116
117
118 def aes_ctr_decrypt(data, key, iv):
119 """
120 Decrypt with aes in counter mode
121
122 @param {int[]} data cipher
123 @param {int[]} key 16/24/32-Byte cipher key
124 @param {int[]} iv 16-Byte initialization vector
125 @returns {int[]} decrypted data
126 """
127 return aes_ctr_encrypt(data, key, iv)
128
129
130 def aes_ctr_encrypt(data, key, iv):
131 """
132 Encrypt with aes in counter mode
133
134 @param {int[]} data cleartext
135 @param {int[]} key 16/24/32-Byte cipher key
136 @param {int[]} iv 16-Byte initialization vector
137 @returns {int[]} encrypted data
138 """
139 expanded_key = key_expansion(key)
140 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
141 counter = iter_vector(iv)
142
143 encrypted_data = []
144 for i in range(block_count):
145 counter_block = next(counter)
146 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
147 block += [0] * (BLOCK_SIZE_BYTES - len(block))
148
149 cipher_counter_block = aes_encrypt(counter_block, expanded_key)
150 encrypted_data += xor(block, cipher_counter_block)
151 encrypted_data = encrypted_data[:len(data)]
152
153 return encrypted_data
154
155
156 def aes_cbc_decrypt(data, key, iv):
157 """
158 Decrypt with aes in CBC mode
159
160 @param {int[]} data cipher
161 @param {int[]} key 16/24/32-Byte cipher key
162 @param {int[]} iv 16-Byte IV
163 @returns {int[]} decrypted data
164 """
165 expanded_key = key_expansion(key)
166 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
167
168 decrypted_data = []
169 previous_cipher_block = iv
170 for i in range(block_count):
171 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
172 block += [0] * (BLOCK_SIZE_BYTES - len(block))
173
174 decrypted_block = aes_decrypt(block, expanded_key)
175 decrypted_data += xor(decrypted_block, previous_cipher_block)
176 previous_cipher_block = block
177 decrypted_data = decrypted_data[:len(data)]
178
179 return decrypted_data
180
181
182 def aes_cbc_encrypt(data, key, iv, *, padding_mode='pkcs7'):
183 """
184 Encrypt with aes in CBC mode
185
186 @param {int[]} data cleartext
187 @param {int[]} key 16/24/32-Byte cipher key
188 @param {int[]} iv 16-Byte IV
189 @param padding_mode Padding mode to use
190 @returns {int[]} encrypted data
191 """
192 expanded_key = key_expansion(key)
193 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
194
195 encrypted_data = []
196 previous_cipher_block = iv
197 for i in range(block_count):
198 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
199 block = pad_block(block, padding_mode)
200
201 mixed_block = xor(block, previous_cipher_block)
202
203 encrypted_block = aes_encrypt(mixed_block, expanded_key)
204 encrypted_data += encrypted_block
205
206 previous_cipher_block = encrypted_block
207
208 return encrypted_data
209
210
211 def aes_gcm_decrypt_and_verify(data, key, tag, nonce):
212 """
213 Decrypt with aes in GBM mode and checks authenticity using tag
214
215 @param {int[]} data cipher
216 @param {int[]} key 16-Byte cipher key
217 @param {int[]} tag authentication tag
218 @param {int[]} nonce IV (recommended 12-Byte)
219 @returns {int[]} decrypted data
220 """
221
222 # XXX: check aes, gcm param
223
224 hash_subkey = aes_encrypt([0] * BLOCK_SIZE_BYTES, key_expansion(key))
225
226 if len(nonce) == 12:
227 j0 = nonce + [0, 0, 0, 1]
228 else:
229 fill = (BLOCK_SIZE_BYTES - (len(nonce) % BLOCK_SIZE_BYTES)) % BLOCK_SIZE_BYTES + 8
230 ghash_in = nonce + [0] * fill + bytes_to_intlist((8 * len(nonce)).to_bytes(8, 'big'))
231 j0 = ghash(hash_subkey, ghash_in)
232
233 # TODO: add nonce support to aes_ctr_decrypt
234
235 # nonce_ctr = j0[:12]
236 iv_ctr = inc(j0)
237
238 decrypted_data = aes_ctr_decrypt(data, key, iv_ctr + [0] * (BLOCK_SIZE_BYTES - len(iv_ctr)))
239 pad_len = len(data) // 16 * 16
240 s_tag = ghash(
241 hash_subkey,
242 data
243 + [0] * (BLOCK_SIZE_BYTES - len(data) + pad_len) # pad
244 + bytes_to_intlist((0 * 8).to_bytes(8, 'big') # length of associated data
245 + ((len(data) * 8).to_bytes(8, 'big'))) # length of data
246 )
247
248 if tag != aes_ctr_encrypt(s_tag, key, j0):
249 raise ValueError("Mismatching authentication tag")
250
251 return decrypted_data
252
253
254 def aes_encrypt(data, expanded_key):
255 """
256 Encrypt one block with aes
257
258 @param {int[]} data 16-Byte state
259 @param {int[]} expanded_key 176/208/240-Byte expanded key
260 @returns {int[]} 16-Byte cipher
261 """
262 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
263
264 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
265 for i in range(1, rounds + 1):
266 data = sub_bytes(data)
267 data = shift_rows(data)
268 if i != rounds:
269 data = list(iter_mix_columns(data, MIX_COLUMN_MATRIX))
270 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
271
272 return data
273
274
275 def aes_decrypt(data, expanded_key):
276 """
277 Decrypt one block with aes
278
279 @param {int[]} data 16-Byte cipher
280 @param {int[]} expanded_key 176/208/240-Byte expanded key
281 @returns {int[]} 16-Byte state
282 """
283 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
284
285 for i in range(rounds, 0, -1):
286 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
287 if i != rounds:
288 data = list(iter_mix_columns(data, MIX_COLUMN_MATRIX_INV))
289 data = shift_rows_inv(data)
290 data = sub_bytes_inv(data)
291 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
292
293 return data
294
295
296 def aes_decrypt_text(data, password, key_size_bytes):
297 """
298 Decrypt text
299 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
300 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
301 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
302 - Mode of operation is 'counter'
303
304 @param {str} data Base64 encoded string
305 @param {str,unicode} password Password (will be encoded with utf-8)
306 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
307 @returns {str} Decrypted data
308 """
309 NONCE_LENGTH_BYTES = 8
310
311 data = bytes_to_intlist(base64.b64decode(data))
312 password = bytes_to_intlist(password.encode())
313
314 key = password[:key_size_bytes] + [0] * (key_size_bytes - len(password))
315 key = aes_encrypt(key[:BLOCK_SIZE_BYTES], key_expansion(key)) * (key_size_bytes // BLOCK_SIZE_BYTES)
316
317 nonce = data[:NONCE_LENGTH_BYTES]
318 cipher = data[NONCE_LENGTH_BYTES:]
319
320 decrypted_data = aes_ctr_decrypt(cipher, key, nonce + [0] * (BLOCK_SIZE_BYTES - NONCE_LENGTH_BYTES))
321 plaintext = intlist_to_bytes(decrypted_data)
322
323 return plaintext
324
325
326 RCON = (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
327 SBOX = (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
328 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
329 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
330 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
331 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
332 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
333 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
334 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
335 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
336 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
337 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
338 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
339 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
340 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
341 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
342 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
343 SBOX_INV = (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
344 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
345 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
346 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
347 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
348 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
349 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
350 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
351 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
352 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
353 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
354 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
355 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
356 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
357 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
358 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
359 MIX_COLUMN_MATRIX = ((0x2, 0x3, 0x1, 0x1),
360 (0x1, 0x2, 0x3, 0x1),
361 (0x1, 0x1, 0x2, 0x3),
362 (0x3, 0x1, 0x1, 0x2))
363 MIX_COLUMN_MATRIX_INV = ((0xE, 0xB, 0xD, 0x9),
364 (0x9, 0xE, 0xB, 0xD),
365 (0xD, 0x9, 0xE, 0xB),
366 (0xB, 0xD, 0x9, 0xE))
367 RIJNDAEL_EXP_TABLE = (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
368 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
369 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
370 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
371 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
372 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
373 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
374 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
375 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
376 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
377 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
378 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
379 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
380 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
381 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
382 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
383 RIJNDAEL_LOG_TABLE = (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
384 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
385 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
386 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
387 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
388 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
389 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
390 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
391 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
392 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
393 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
394 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
395 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
396 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
397 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
398 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
399
400
401 def key_expansion(data):
402 """
403 Generate key schedule
404
405 @param {int[]} data 16/24/32-Byte cipher key
406 @returns {int[]} 176/208/240-Byte expanded key
407 """
408 data = data[:] # copy
409 rcon_iteration = 1
410 key_size_bytes = len(data)
411 expanded_key_size_bytes = (key_size_bytes // 4 + 7) * BLOCK_SIZE_BYTES
412
413 while len(data) < expanded_key_size_bytes:
414 temp = data[-4:]
415 temp = key_schedule_core(temp, rcon_iteration)
416 rcon_iteration += 1
417 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
418
419 for _ in range(3):
420 temp = data[-4:]
421 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
422
423 if key_size_bytes == 32:
424 temp = data[-4:]
425 temp = sub_bytes(temp)
426 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
427
428 for _ in range(3 if key_size_bytes == 32 else 2 if key_size_bytes == 24 else 0):
429 temp = data[-4:]
430 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
431 data = data[:expanded_key_size_bytes]
432
433 return data
434
435
436 def iter_vector(iv):
437 while True:
438 yield iv
439 iv = inc(iv)
440
441
442 def sub_bytes(data):
443 return [SBOX[x] for x in data]
444
445
446 def sub_bytes_inv(data):
447 return [SBOX_INV[x] for x in data]
448
449
450 def rotate(data):
451 return data[1:] + [data[0]]
452
453
454 def key_schedule_core(data, rcon_iteration):
455 data = rotate(data)
456 data = sub_bytes(data)
457 data[0] = data[0] ^ RCON[rcon_iteration]
458
459 return data
460
461
462 def xor(data1, data2):
463 return [x ^ y for x, y in zip(data1, data2)]
464
465
466 def iter_mix_columns(data, matrix):
467 for i in (0, 4, 8, 12):
468 for row in matrix:
469 mixed = 0
470 for j in range(4):
471 # xor is (+) and (-)
472 mixed ^= (0 if data[i:i + 4][j] == 0 or row[j] == 0 else
473 RIJNDAEL_EXP_TABLE[(RIJNDAEL_LOG_TABLE[data[i + j]] + RIJNDAEL_LOG_TABLE[row[j]]) % 0xFF])
474 yield mixed
475
476
477 def shift_rows(data):
478 return [data[((column + row) & 0b11) * 4 + row] for column in range(4) for row in range(4)]
479
480
481 def shift_rows_inv(data):
482 return [data[((column - row) & 0b11) * 4 + row] for column in range(4) for row in range(4)]
483
484
485 def shift_block(data):
486 data_shifted = []
487
488 bit = 0
489 for n in data:
490 if bit:
491 n |= 0x100
492 bit = n & 1
493 n >>= 1
494 data_shifted.append(n)
495
496 return data_shifted
497
498
499 def inc(data):
500 data = data[:] # copy
501 for i in range(len(data) - 1, -1, -1):
502 if data[i] == 255:
503 data[i] = 0
504 else:
505 data[i] = data[i] + 1
506 break
507 return data
508
509
510 def block_product(block_x, block_y):
511 # NIST SP 800-38D, Algorithm 1
512
513 if len(block_x) != BLOCK_SIZE_BYTES or len(block_y) != BLOCK_SIZE_BYTES:
514 raise ValueError("Length of blocks need to be %d bytes" % BLOCK_SIZE_BYTES)
515
516 block_r = [0xE1] + [0] * (BLOCK_SIZE_BYTES - 1)
517 block_v = block_y[:]
518 block_z = [0] * BLOCK_SIZE_BYTES
519
520 for i in block_x:
521 for bit in range(7, -1, -1):
522 if i & (1 << bit):
523 block_z = xor(block_z, block_v)
524
525 do_xor = block_v[-1] & 1
526 block_v = shift_block(block_v)
527 if do_xor:
528 block_v = xor(block_v, block_r)
529
530 return block_z
531
532
533 def ghash(subkey, data):
534 # NIST SP 800-38D, Algorithm 2
535
536 if len(data) % BLOCK_SIZE_BYTES:
537 raise ValueError("Length of data should be %d bytes" % BLOCK_SIZE_BYTES)
538
539 last_y = [0] * BLOCK_SIZE_BYTES
540 for i in range(0, len(data), BLOCK_SIZE_BYTES):
541 block = data[i: i + BLOCK_SIZE_BYTES]
542 last_y = block_product(xor(last_y, block), subkey)
543
544 return last_y
545
546
547 __all__ = [
548 'aes_cbc_decrypt',
549 'aes_cbc_decrypt_bytes',
550 'aes_ctr_decrypt',
551 'aes_decrypt_text',
552 'aes_decrypt',
553 'aes_ecb_decrypt',
554 'aes_gcm_decrypt_and_verify',
555 'aes_gcm_decrypt_and_verify_bytes',
556
557 'aes_cbc_encrypt',
558 'aes_cbc_encrypt_bytes',
559 'aes_ctr_encrypt',
560 'aes_ecb_encrypt',
561 'aes_encrypt',
562
563 'key_expansion',
564 'pad_block',
565 'pkcs7_padding',
566 'unpad_pkcs7',
567 ]