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