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