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