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