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