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