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