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