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