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