]>
jfr.im git - yt-dlp.git/blob - yt_dlp/aes.py
3 from .compat
import compat_b64decode
, compat_ord
4 from .dependencies
import Cryptodome_AES
5 from .utils
import bytes_to_intlist
, intlist_to_bytes
8 def aes_cbc_decrypt_bytes(data
, key
, iv
):
9 """ Decrypt bytes with AES-CBC using pycryptodome """
10 return Cryptodome_AES
.new(key
, Cryptodome_AES
.MODE_CBC
, iv
).decrypt(data
)
12 def aes_gcm_decrypt_and_verify_bytes(data
, key
, tag
, nonce
):
13 """ Decrypt bytes with AES-GCM using pycryptodome """
14 return Cryptodome_AES
.new(key
, Cryptodome_AES
.MODE_GCM
, nonce
).decrypt_and_verify(data
, tag
)
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
))))
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
))))
26 def unpad_pkcs7(data
):
27 return data
[:-compat_ord(data
[-1])]
33 def aes_ecb_encrypt(data
, key
, iv
=None):
35 Encrypt with aes in ECB mode
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
42 expanded_key
= key_expansion(key
)
43 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
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
)]
54 def aes_ecb_decrypt(data
, key
, iv
=None):
56 Decrypt with aes in ECB mode
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
63 expanded_key
= key_expansion(key
)
64 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
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
)]
75 def aes_ctr_decrypt(data
, key
, iv
):
77 Decrypt with aes in counter mode
79 @param {int[]} data cipher
80 @param {int[]} key 16/24/32-Byte cipher key
81 @param {int[]} iv 16-Byte initialization vector
82 @returns {int[]} decrypted data
84 return aes_ctr_encrypt(data
, key
, iv
)
87 def aes_ctr_encrypt(data
, key
, iv
):
89 Encrypt with aes in counter mode
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
96 expanded_key
= key_expansion(key
)
97 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
98 counter
= iter_vector(iv
)
101 for i
in range(block_count
):
102 counter_block
= next(counter
)
103 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
104 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
106 cipher_counter_block
= aes_encrypt(counter_block
, expanded_key
)
107 encrypted_data
+= xor(block
, cipher_counter_block
)
108 encrypted_data
= encrypted_data
[:len(data
)]
110 return encrypted_data
113 def aes_cbc_decrypt(data
, key
, iv
):
115 Decrypt with aes in CBC mode
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
122 expanded_key
= key_expansion(key
)
123 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
126 previous_cipher_block
= iv
127 for i
in range(block_count
):
128 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
129 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
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
)]
136 return decrypted_data
139 def aes_cbc_encrypt(data
, key
, iv
):
141 Encrypt with aes in CBC mode. Using PKCS#7 padding
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
148 expanded_key
= key_expansion(key
)
149 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
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
)
159 encrypted_block
= aes_encrypt(mixed_block
, expanded_key
)
160 encrypted_data
+= encrypted_block
162 previous_cipher_block
= encrypted_block
164 return encrypted_data
167 def aes_gcm_decrypt_and_verify(data
, key
, tag
, nonce
):
169 Decrypt with aes in GBM mode and checks authenticity using tag
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
178 # XXX: check aes, gcm param
180 hash_subkey
= aes_encrypt([0] * BLOCK_SIZE_BYTES
, key_expansion(key
))
183 j0
= nonce
+ [0, 0, 0, 1]
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
)
189 # TODO: add nonce support to aes_ctr_decrypt
191 # nonce_ctr = j0[:12]
194 decrypted_data
= aes_ctr_decrypt(data
, key
, iv_ctr
+ [0] * (BLOCK_SIZE_BYTES
- len(iv_ctr
)))
195 pad_len
= len(data
) // 16 * 16
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
204 if tag
!= aes_ctr_encrypt(s_tag
, key
, j0
):
205 raise ValueError("Mismatching authentication tag")
207 return decrypted_data
210 def aes_encrypt(data
, expanded_key
):
212 Encrypt one block with aes
214 @param {int[]} data 16-Byte state
215 @param {int[]} expanded_key 176/208/240-Byte expanded key
216 @returns {int[]} 16-Byte cipher
218 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
220 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
221 for i
in range(1, rounds
+ 1):
222 data
= sub_bytes(data
)
223 data
= shift_rows(data
)
225 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX
))
226 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
231 def aes_decrypt(data
, expanded_key
):
233 Decrypt one block with aes
235 @param {int[]} data 16-Byte cipher
236 @param {int[]} expanded_key 176/208/240-Byte expanded key
237 @returns {int[]} 16-Byte state
239 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
241 for i
in range(rounds
, 0, -1):
242 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
244 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX_INV
))
245 data
= shift_rows_inv(data
)
246 data
= sub_bytes_inv(data
)
247 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
252 def aes_decrypt_text(data
, password
, key_size_bytes
):
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'
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
265 NONCE_LENGTH_BYTES
= 8
267 data
= bytes_to_intlist(compat_b64decode(data
))
268 password
= bytes_to_intlist(password
.encode())
270 key
= password
[:key_size_bytes
] + [0] * (key_size_bytes
- len(password
))
271 key
= aes_encrypt(key
[:BLOCK_SIZE_BYTES
], key_expansion(key
)) * (key_size_bytes
// BLOCK_SIZE_BYTES
)
273 nonce
= data
[:NONCE_LENGTH_BYTES
]
274 cipher
= data
[NONCE_LENGTH_BYTES
:]
276 decrypted_data
= aes_ctr_decrypt(cipher
, key
, nonce
+ [0] * (BLOCK_SIZE_BYTES
- NONCE_LENGTH_BYTES
))
277 plaintext
= intlist_to_bytes(decrypted_data
)
282 RCON
= (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
283 SBOX
= (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)
299 SBOX_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)
315 MIX_COLUMN_MATRIX
= ((0x2, 0x3, 0x1, 0x1),
316 (0x1, 0x2, 0x3, 0x1),
317 (0x1, 0x1, 0x2, 0x3),
318 (0x3, 0x1, 0x1, 0x2))
319 MIX_COLUMN_MATRIX_INV
= ((0xE, 0xB, 0xD, 0x9),
320 (0x9, 0xE, 0xB, 0xD),
321 (0xD, 0x9, 0xE, 0xB),
322 (0xB, 0xD, 0x9, 0xE))
323 RIJNDAEL_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)
339 RIJNDAEL_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)
357 def key_expansion(data
):
359 Generate key schedule
361 @param {int[]} data 16/24/32-Byte cipher key
362 @returns {int[]} 176/208/240-Byte expanded key
364 data
= data
[:] # copy
366 key_size_bytes
= len(data
)
367 expanded_key_size_bytes
= (key_size_bytes
// 4 + 7) * BLOCK_SIZE_BYTES
369 while len(data
) < expanded_key_size_bytes
:
371 temp
= key_schedule_core(temp
, rcon_iteration
)
373 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
377 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
379 if key_size_bytes
== 32:
381 temp
= sub_bytes(temp
)
382 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
384 for _
in range(3 if key_size_bytes
== 32 else 2 if key_size_bytes
== 24 else 0):
386 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
387 data
= data
[:expanded_key_size_bytes
]
399 return [SBOX
[x
] for x
in data
]
402 def sub_bytes_inv(data
):
403 return [SBOX_INV
[x
] for x
in data
]
407 return data
[1:] + [data
[0]]
410 def key_schedule_core(data
, rcon_iteration
):
412 data
= sub_bytes(data
)
413 data
[0] = data
[0] ^ RCON
[rcon_iteration
]
418 def xor(data1
, data2
):
419 return [x ^ y
for x
, y
in zip(data1
, data2
)]
422 def iter_mix_columns(data
, matrix
):
423 for i
in (0, 4, 8, 12):
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])
433 def shift_rows(data
):
434 return [data
[((column
+ row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
437 def shift_rows_inv(data
):
438 return [data
[((column
- row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
441 def shift_block(data
):
450 data_shifted
.append(n
)
456 data
= data
[:] # copy
457 for i
in range(len(data
) - 1, -1, -1):
461 data
[i
] = data
[i
] + 1
466 def block_product(block_x
, block_y
):
467 # NIST SP 800-38D, Algorithm 1
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
)
472 block_r
= [0xE1] + [0] * (BLOCK_SIZE_BYTES
- 1)
474 block_z
= [0] * BLOCK_SIZE_BYTES
477 for bit
in range(7, -1, -1):
479 block_z
= xor(block_z
, block_v
)
481 do_xor
= block_v
[-1] & 1
482 block_v
= shift_block(block_v
)
484 block_v
= xor(block_v
, block_r
)
489 def ghash(subkey
, data
):
490 # NIST SP 800-38D, Algorithm 2
492 if len(data
) % BLOCK_SIZE_BYTES
:
493 raise ValueError("Length of data should be %d bytes" % BLOCK_SIZE_BYTES
)
495 last_y
= [0] * BLOCK_SIZE_BYTES
496 for i
in range(0, len(data
), BLOCK_SIZE_BYTES
):
497 block
= data
[i
: i
+ BLOCK_SIZE_BYTES
]
498 last_y
= block_product(xor(last_y
, block
), subkey
)
506 'aes_cbc_decrypt_bytes',
509 'aes_gcm_decrypt_and_verify',
510 'aes_gcm_decrypt_and_verify_bytes',