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