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