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