]>
jfr.im git - yt-dlp.git/blob - yt_dlp/aes.py
4 from .compat
import compat_ord
5 from .dependencies
import Cryptodome_AES
6 from .utils
import bytes_to_intlist
, intlist_to_bytes
9 def aes_cbc_decrypt_bytes(data
, key
, iv
):
10 """ Decrypt bytes with AES-CBC using pycryptodome """
11 return Cryptodome_AES
.new(key
, Cryptodome_AES
.MODE_CBC
, iv
).decrypt(data
)
13 def aes_gcm_decrypt_and_verify_bytes(data
, key
, tag
, nonce
):
14 """ Decrypt bytes with AES-GCM using pycryptodome """
15 return Cryptodome_AES
.new(key
, Cryptodome_AES
.MODE_GCM
, nonce
).decrypt_and_verify(data
, tag
)
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
))))
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
))))
27 def aes_cbc_encrypt_bytes(data
, key
, iv
, **kwargs
):
28 return intlist_to_bytes(aes_cbc_encrypt(*map(bytes_to_intlist
, (data
, key
, iv
)), **kwargs
))
31 def unpad_pkcs7(data
):
32 return data
[:-compat_ord(data
[-1])]
38 def pad_block(block
, padding_mode
):
40 Pad a block with the given padding mode
41 @param {int[]} block block to pad
42 @param padding_mode padding mode
44 padding_size
= BLOCK_SIZE_BYTES
- len(block
)
47 'pkcs7': padding_size
,
54 raise ValueError('Block size exceeded')
55 elif padding_mode
not in PADDING_BYTE
:
56 raise NotImplementedError(f
'Padding mode {padding_mode} is not implemented')
58 if padding_mode
== 'iso7816' and padding_size
:
59 block
= block
+ [0x80] # NB: += mutates list
62 return block
+ [PADDING_BYTE
[padding_mode
]] * padding_size
65 def aes_ecb_encrypt(data
, key
, iv
=None):
67 Encrypt with aes in ECB mode
69 @param {int[]} data cleartext
70 @param {int[]} key 16/24/32-Byte cipher key
71 @param {int[]} iv Unused for this mode
72 @returns {int[]} encrypted data
74 expanded_key
= key_expansion(key
)
75 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
78 for i
in range(block_count
):
79 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
80 encrypted_data
+= aes_encrypt(block
, expanded_key
)
81 encrypted_data
= encrypted_data
[:len(data
)]
86 def aes_ecb_decrypt(data
, key
, iv
=None):
88 Decrypt with aes in ECB mode
90 @param {int[]} data cleartext
91 @param {int[]} key 16/24/32-Byte cipher key
92 @param {int[]} iv Unused for this mode
93 @returns {int[]} decrypted data
95 expanded_key
= key_expansion(key
)
96 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
99 for i
in range(block_count
):
100 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
101 encrypted_data
+= aes_decrypt(block
, expanded_key
)
102 encrypted_data
= encrypted_data
[:len(data
)]
104 return encrypted_data
107 def aes_ctr_decrypt(data
, key
, iv
):
109 Decrypt with aes in counter mode
111 @param {int[]} data cipher
112 @param {int[]} key 16/24/32-Byte cipher key
113 @param {int[]} iv 16-Byte initialization vector
114 @returns {int[]} decrypted data
116 return aes_ctr_encrypt(data
, key
, iv
)
119 def aes_ctr_encrypt(data
, key
, iv
):
121 Encrypt with aes in counter mode
123 @param {int[]} data cleartext
124 @param {int[]} key 16/24/32-Byte cipher key
125 @param {int[]} iv 16-Byte initialization vector
126 @returns {int[]} encrypted data
128 expanded_key
= key_expansion(key
)
129 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
130 counter
= iter_vector(iv
)
133 for i
in range(block_count
):
134 counter_block
= next(counter
)
135 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
136 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
138 cipher_counter_block
= aes_encrypt(counter_block
, expanded_key
)
139 encrypted_data
+= xor(block
, cipher_counter_block
)
140 encrypted_data
= encrypted_data
[:len(data
)]
142 return encrypted_data
145 def aes_cbc_decrypt(data
, key
, iv
):
147 Decrypt with aes in CBC mode
149 @param {int[]} data cipher
150 @param {int[]} key 16/24/32-Byte cipher key
151 @param {int[]} iv 16-Byte IV
152 @returns {int[]} decrypted data
154 expanded_key
= key_expansion(key
)
155 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
158 previous_cipher_block
= iv
159 for i
in range(block_count
):
160 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
161 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
163 decrypted_block
= aes_decrypt(block
, expanded_key
)
164 decrypted_data
+= xor(decrypted_block
, previous_cipher_block
)
165 previous_cipher_block
= block
166 decrypted_data
= decrypted_data
[:len(data
)]
168 return decrypted_data
171 def aes_cbc_encrypt(data
, key
, iv
, *, padding_mode
='pkcs7'):
173 Encrypt with aes in CBC mode
175 @param {int[]} data cleartext
176 @param {int[]} key 16/24/32-Byte cipher key
177 @param {int[]} iv 16-Byte IV
178 @param padding_mode Padding mode to use
179 @returns {int[]} encrypted data
181 expanded_key
= key_expansion(key
)
182 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
185 previous_cipher_block
= iv
186 for i
in range(block_count
):
187 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
188 block
= pad_block(block
, padding_mode
)
190 mixed_block
= xor(block
, previous_cipher_block
)
192 encrypted_block
= aes_encrypt(mixed_block
, expanded_key
)
193 encrypted_data
+= encrypted_block
195 previous_cipher_block
= encrypted_block
197 return encrypted_data
200 def aes_gcm_decrypt_and_verify(data
, key
, tag
, nonce
):
202 Decrypt with aes in GBM mode and checks authenticity using tag
204 @param {int[]} data cipher
205 @param {int[]} key 16-Byte cipher key
206 @param {int[]} tag authentication tag
207 @param {int[]} nonce IV (recommended 12-Byte)
208 @returns {int[]} decrypted data
211 # XXX: check aes, gcm param
213 hash_subkey
= aes_encrypt([0] * BLOCK_SIZE_BYTES
, key_expansion(key
))
216 j0
= nonce
+ [0, 0, 0, 1]
218 fill
= (BLOCK_SIZE_BYTES
- (len(nonce
) % BLOCK_SIZE_BYTES
)) % BLOCK_SIZE_BYTES
+ 8
219 ghash_in
= nonce
+ [0] * fill
+ bytes_to_intlist((8 * len(nonce
)).to_bytes(8, 'big'))
220 j0
= ghash(hash_subkey
, ghash_in
)
222 # TODO: add nonce support to aes_ctr_decrypt
224 # nonce_ctr = j0[:12]
227 decrypted_data
= aes_ctr_decrypt(data
, key
, iv_ctr
+ [0] * (BLOCK_SIZE_BYTES
- len(iv_ctr
)))
228 pad_len
= len(data
) // 16 * 16
232 + [0] * (BLOCK_SIZE_BYTES
- len(data
) + pad_len
) # pad
233 + bytes_to_intlist((0 * 8).to_bytes(8, 'big') # length of associated data
234 + ((len(data
) * 8).to_bytes(8, 'big'))) # length of data
237 if tag
!= aes_ctr_encrypt(s_tag
, key
, j0
):
238 raise ValueError("Mismatching authentication tag")
240 return decrypted_data
243 def aes_encrypt(data
, expanded_key
):
245 Encrypt one block with aes
247 @param {int[]} data 16-Byte state
248 @param {int[]} expanded_key 176/208/240-Byte expanded key
249 @returns {int[]} 16-Byte cipher
251 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
253 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
254 for i
in range(1, rounds
+ 1):
255 data
= sub_bytes(data
)
256 data
= shift_rows(data
)
258 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX
))
259 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
264 def aes_decrypt(data
, expanded_key
):
266 Decrypt one block with aes
268 @param {int[]} data 16-Byte cipher
269 @param {int[]} expanded_key 176/208/240-Byte expanded key
270 @returns {int[]} 16-Byte state
272 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
274 for i
in range(rounds
, 0, -1):
275 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
277 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX_INV
))
278 data
= shift_rows_inv(data
)
279 data
= sub_bytes_inv(data
)
280 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
285 def aes_decrypt_text(data
, password
, key_size_bytes
):
288 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
289 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
290 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
291 - Mode of operation is 'counter'
293 @param {str} data Base64 encoded string
294 @param {str,unicode} password Password (will be encoded with utf-8)
295 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
296 @returns {str} Decrypted data
298 NONCE_LENGTH_BYTES
= 8
300 data
= bytes_to_intlist(base64
.b64decode(data
))
301 password
= bytes_to_intlist(password
.encode())
303 key
= password
[:key_size_bytes
] + [0] * (key_size_bytes
- len(password
))
304 key
= aes_encrypt(key
[:BLOCK_SIZE_BYTES
], key_expansion(key
)) * (key_size_bytes
// BLOCK_SIZE_BYTES
)
306 nonce
= data
[:NONCE_LENGTH_BYTES
]
307 cipher
= data
[NONCE_LENGTH_BYTES
:]
309 decrypted_data
= aes_ctr_decrypt(cipher
, key
, nonce
+ [0] * (BLOCK_SIZE_BYTES
- NONCE_LENGTH_BYTES
))
310 plaintext
= intlist_to_bytes(decrypted_data
)
315 RCON
= (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
316 SBOX
= (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
317 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
318 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
319 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
320 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
321 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
322 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
323 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
324 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
325 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
326 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
327 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
328 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
329 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
330 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
331 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
332 SBOX_INV
= (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
333 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
334 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
335 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
336 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
337 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
338 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
339 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
340 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
341 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
342 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
343 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
344 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
345 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
346 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
347 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
348 MIX_COLUMN_MATRIX
= ((0x2, 0x3, 0x1, 0x1),
349 (0x1, 0x2, 0x3, 0x1),
350 (0x1, 0x1, 0x2, 0x3),
351 (0x3, 0x1, 0x1, 0x2))
352 MIX_COLUMN_MATRIX_INV
= ((0xE, 0xB, 0xD, 0x9),
353 (0x9, 0xE, 0xB, 0xD),
354 (0xD, 0x9, 0xE, 0xB),
355 (0xB, 0xD, 0x9, 0xE))
356 RIJNDAEL_EXP_TABLE
= (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
357 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
358 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
359 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
360 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
361 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
362 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
363 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
364 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
365 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
366 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
367 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
368 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
369 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
370 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
371 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
372 RIJNDAEL_LOG_TABLE
= (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
373 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
374 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
375 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
376 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
377 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
378 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
379 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
380 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
381 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
382 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
383 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
384 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
385 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
386 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
387 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
390 def key_expansion(data
):
392 Generate key schedule
394 @param {int[]} data 16/24/32-Byte cipher key
395 @returns {int[]} 176/208/240-Byte expanded key
397 data
= data
[:] # copy
399 key_size_bytes
= len(data
)
400 expanded_key_size_bytes
= (key_size_bytes
// 4 + 7) * BLOCK_SIZE_BYTES
402 while len(data
) < expanded_key_size_bytes
:
404 temp
= key_schedule_core(temp
, rcon_iteration
)
406 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
410 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
412 if key_size_bytes
== 32:
414 temp
= sub_bytes(temp
)
415 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
417 for _
in range(3 if key_size_bytes
== 32 else 2 if key_size_bytes
== 24 else 0):
419 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
420 data
= data
[:expanded_key_size_bytes
]
432 return [SBOX
[x
] for x
in data
]
435 def sub_bytes_inv(data
):
436 return [SBOX_INV
[x
] for x
in data
]
440 return data
[1:] + [data
[0]]
443 def key_schedule_core(data
, rcon_iteration
):
445 data
= sub_bytes(data
)
446 data
[0] = data
[0] ^ RCON
[rcon_iteration
]
451 def xor(data1
, data2
):
452 return [x ^ y
for x
, y
in zip(data1
, data2
)]
455 def iter_mix_columns(data
, matrix
):
456 for i
in (0, 4, 8, 12):
461 mixed ^
= (0 if data
[i
:i
+ 4][j
] == 0 or row
[j
] == 0 else
462 RIJNDAEL_EXP_TABLE
[(RIJNDAEL_LOG_TABLE
[data
[i
+ j
]] + RIJNDAEL_LOG_TABLE
[row
[j
]]) % 0xFF])
466 def shift_rows(data
):
467 return [data
[((column
+ row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
470 def shift_rows_inv(data
):
471 return [data
[((column
- row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
474 def shift_block(data
):
483 data_shifted
.append(n
)
489 data
= data
[:] # copy
490 for i
in range(len(data
) - 1, -1, -1):
494 data
[i
] = data
[i
] + 1
499 def block_product(block_x
, block_y
):
500 # NIST SP 800-38D, Algorithm 1
502 if len(block_x
) != BLOCK_SIZE_BYTES
or len(block_y
) != BLOCK_SIZE_BYTES
:
503 raise ValueError("Length of blocks need to be %d bytes" % BLOCK_SIZE_BYTES
)
505 block_r
= [0xE1] + [0] * (BLOCK_SIZE_BYTES
- 1)
507 block_z
= [0] * BLOCK_SIZE_BYTES
510 for bit
in range(7, -1, -1):
512 block_z
= xor(block_z
, block_v
)
514 do_xor
= block_v
[-1] & 1
515 block_v
= shift_block(block_v
)
517 block_v
= xor(block_v
, block_r
)
522 def ghash(subkey
, data
):
523 # NIST SP 800-38D, Algorithm 2
525 if len(data
) % BLOCK_SIZE_BYTES
:
526 raise ValueError("Length of data should be %d bytes" % BLOCK_SIZE_BYTES
)
528 last_y
= [0] * BLOCK_SIZE_BYTES
529 for i
in range(0, len(data
), BLOCK_SIZE_BYTES
):
530 block
= data
[i
: i
+ BLOCK_SIZE_BYTES
]
531 last_y
= block_product(xor(last_y
, block
), subkey
)
538 'aes_cbc_decrypt_bytes',
543 'aes_gcm_decrypt_and_verify',
544 'aes_gcm_decrypt_and_verify_bytes',
547 'aes_cbc_encrypt_bytes',