]> jfr.im git - yt-dlp.git/blame - youtube_dl/aes.py
[dotsub] Fix extraction and modernize
[yt-dlp.git] / youtube_dl / aes.py
CommitLineData
dcddc10a
PH
1from __future__ import unicode_literals
2
c8434e83 3__all__ = ['aes_encrypt', 'key_expansion', 'aes_ctr_decrypt', 'aes_cbc_decrypt', 'aes_decrypt_text']
f3bcebb1 4
5import base64
6from math import ceil
7
0012690a 8from .utils import bytes_to_intlist, intlist_to_bytes
48ea9cea 9
f3bcebb1 10BLOCK_SIZE_BYTES = 16
11
5f6a1245 12
f3bcebb1 13def aes_ctr_decrypt(data, key, counter):
14 """
15 Decrypt with aes in counter mode
5f6a1245 16
f3bcebb1 17 @param {int[]} data cipher
18 @param {int[]} key 16/24/32-Byte cipher key
19 @param {instance} counter Instance whose next_value function (@returns {int[]} 16-Byte block)
20 returns the next counter block
21 @returns {int[]} decrypted data
22 """
23 expanded_key = key_expansion(key)
6e74bc41 24 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
5f6a1245
JW
25
26 decrypted_data = []
f3bcebb1 27 for i in range(block_count):
28 counter_block = counter.next_value()
2514d263
JW
29 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
30 block += [0] * (BLOCK_SIZE_BYTES - len(block))
5f6a1245 31
f3bcebb1 32 cipher_counter_block = aes_encrypt(counter_block, expanded_key)
33 decrypted_data += xor(block, cipher_counter_block)
34 decrypted_data = decrypted_data[:len(data)]
5f6a1245 35
f3bcebb1 36 return decrypted_data
37
5f6a1245 38
c8434e83 39def aes_cbc_decrypt(data, key, iv):
40 """
41 Decrypt with aes in CBC mode
5f6a1245 42
c8434e83 43 @param {int[]} data cipher
44 @param {int[]} key 16/24/32-Byte cipher key
45 @param {int[]} iv 16-Byte IV
46 @returns {int[]} decrypted data
47 """
48 expanded_key = key_expansion(key)
49 block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
5f6a1245
JW
50
51 decrypted_data = []
c8434e83 52 previous_cipher_block = iv
53 for i in range(block_count):
2514d263
JW
54 block = data[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES]
55 block += [0] * (BLOCK_SIZE_BYTES - len(block))
5f6a1245 56
c8434e83 57 decrypted_block = aes_decrypt(block, expanded_key)
58 decrypted_data += xor(decrypted_block, previous_cipher_block)
59 previous_cipher_block = block
60 decrypted_data = decrypted_data[:len(data)]
5f6a1245 61
c8434e83 62 return decrypted_data
63
5f6a1245 64
f3bcebb1 65def key_expansion(data):
66 """
67 Generate key schedule
5f6a1245 68
f3bcebb1 69 @param {int[]} data 16/24/32-Byte cipher key
5f6a1245 70 @returns {int[]} 176/208/240-Byte expanded key
f3bcebb1 71 """
5f6a1245 72 data = data[:] # copy
f3bcebb1 73 rcon_iteration = 1
74 key_size_bytes = len(data)
48ea9cea 75 expanded_key_size_bytes = (key_size_bytes // 4 + 7) * BLOCK_SIZE_BYTES
5f6a1245 76
f3bcebb1 77 while len(data) < expanded_key_size_bytes:
78 temp = data[-4:]
79 temp = key_schedule_core(temp, rcon_iteration)
80 rcon_iteration += 1
2514d263 81 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
5f6a1245 82
f3bcebb1 83 for _ in range(3):
84 temp = data[-4:]
2514d263 85 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
5f6a1245 86
f3bcebb1 87 if key_size_bytes == 32:
88 temp = data[-4:]
89 temp = sub_bytes(temp)
2514d263 90 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
5f6a1245 91
b74e86f4 92 for _ in range(3 if key_size_bytes == 32 else 2 if key_size_bytes == 24 else 0):
f3bcebb1 93 temp = data[-4:]
2514d263 94 data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
f3bcebb1 95 data = data[:expanded_key_size_bytes]
5f6a1245 96
f3bcebb1 97 return data
98
5f6a1245 99
f3bcebb1 100def aes_encrypt(data, expanded_key):
101 """
102 Encrypt one block with aes
5f6a1245 103
f3bcebb1 104 @param {int[]} data 16-Byte state
5f6a1245 105 @param {int[]} expanded_key 176/208/240-Byte expanded key
f3bcebb1 106 @returns {int[]} 16-Byte cipher
107 """
48ea9cea 108 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
c8434e83 109
f3bcebb1 110 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
2514d263 111 for i in range(1, rounds + 1):
f3bcebb1 112 data = sub_bytes(data)
113 data = shift_rows(data)
114 if i != rounds:
115 data = mix_columns(data)
2514d263 116 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
c8434e83 117
118 return data
119
5f6a1245 120
c8434e83 121def aes_decrypt(data, expanded_key):
122 """
123 Decrypt one block with aes
5f6a1245 124
c8434e83 125 @param {int[]} data 16-Byte cipher
126 @param {int[]} expanded_key 176/208/240-Byte expanded key
127 @returns {int[]} 16-Byte state
128 """
129 rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
5f6a1245 130
c8434e83 131 for i in range(rounds, 0, -1):
2514d263 132 data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
c8434e83 133 if i != rounds:
134 data = mix_columns_inv(data)
135 data = shift_rows_inv(data)
136 data = sub_bytes_inv(data)
137 data = xor(data, expanded_key[:BLOCK_SIZE_BYTES])
5f6a1245 138
f3bcebb1 139 return data
140
5f6a1245 141
f3bcebb1 142def aes_decrypt_text(data, password, key_size_bytes):
143 """
144 Decrypt text
145 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
146 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
147 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
148 - Mode of operation is 'counter'
5f6a1245 149
f3bcebb1 150 @param {str} data Base64 encoded string
151 @param {str,unicode} password Password (will be encoded with utf-8)
152 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
153 @returns {str} Decrypted data
154 """
155 NONCE_LENGTH_BYTES = 8
5f6a1245 156
48ea9cea
PH
157 data = bytes_to_intlist(base64.b64decode(data))
158 password = bytes_to_intlist(password.encode('utf-8'))
5f6a1245 159
2514d263 160 key = password[:key_size_bytes] + [0] * (key_size_bytes - len(password))
48ea9cea 161 key = aes_encrypt(key[:BLOCK_SIZE_BYTES], key_expansion(key)) * (key_size_bytes // BLOCK_SIZE_BYTES)
5f6a1245 162
f3bcebb1 163 nonce = data[:NONCE_LENGTH_BYTES]
164 cipher = data[NONCE_LENGTH_BYTES:]
5f6a1245 165
f3bcebb1 166 class Counter:
2514d263 167 __value = nonce + [0] * (BLOCK_SIZE_BYTES - NONCE_LENGTH_BYTES)
5f6a1245 168
f3bcebb1 169 def next_value(self):
170 temp = self.__value
171 self.__value = inc(self.__value)
172 return temp
5f6a1245 173
f3bcebb1 174 decrypted_data = aes_ctr_decrypt(cipher, key, Counter())
0012690a 175 plaintext = intlist_to_bytes(decrypted_data)
5f6a1245 176
f3bcebb1 177 return plaintext
178
179RCON = (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
180SBOX = (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
181 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
182 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
183 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
184 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
185 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
186 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
187 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
188 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
189 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
190 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
191 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
192 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
193 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
194 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
195 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
c8434e83 196SBOX_INV = (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
197 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
198 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
199 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
200 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
201 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
202 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
203 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
204 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
205 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
206 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
207 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
208 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
209 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
210 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
211 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
5f6a1245
JW
212MIX_COLUMN_MATRIX = ((0x2, 0x3, 0x1, 0x1),
213 (0x1, 0x2, 0x3, 0x1),
214 (0x1, 0x1, 0x2, 0x3),
215 (0x3, 0x1, 0x1, 0x2))
216MIX_COLUMN_MATRIX_INV = ((0xE, 0xB, 0xD, 0x9),
217 (0x9, 0xE, 0xB, 0xD),
218 (0xD, 0x9, 0xE, 0xB),
219 (0xB, 0xD, 0x9, 0xE))
c8434e83 220RIJNDAEL_EXP_TABLE = (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
221 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
222 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
223 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
224 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
225 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
226 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
227 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
228 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
229 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
230 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
231 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
232 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
233 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
234 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
235 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
236RIJNDAEL_LOG_TABLE = (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
237 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
238 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
239 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
240 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
241 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
242 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
243 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
244 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
245 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
246 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
247 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
248 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
249 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
250 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
251 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
f3bcebb1 252
5f6a1245 253
f3bcebb1 254def sub_bytes(data):
48ea9cea 255 return [SBOX[x] for x in data]
f3bcebb1 256
5f6a1245 257
c8434e83 258def sub_bytes_inv(data):
259 return [SBOX_INV[x] for x in data]
260
5f6a1245 261
f3bcebb1 262def rotate(data):
263 return data[1:] + [data[0]]
264
5f6a1245 265
f3bcebb1 266def key_schedule_core(data, rcon_iteration):
267 data = rotate(data)
268 data = sub_bytes(data)
269 data[0] = data[0] ^ RCON[rcon_iteration]
5f6a1245 270
f3bcebb1 271 return data
272
5f6a1245 273
f3bcebb1 274def xor(data1, data2):
2514d263 275 return [x ^ y for x, y in zip(data1, data2)]
f3bcebb1 276
5f6a1245 277
c8434e83 278def rijndael_mul(a, b):
5f6a1245 279 if(a == 0 or b == 0):
c8434e83 280 return 0
281 return RIJNDAEL_EXP_TABLE[(RIJNDAEL_LOG_TABLE[a] + RIJNDAEL_LOG_TABLE[b]) % 0xFF]
282
5f6a1245 283
c8434e83 284def mix_column(data, matrix):
f3bcebb1 285 data_mixed = []
286 for row in range(4):
287 mixed = 0
288 for column in range(4):
c8434e83 289 # xor is (+) and (-)
290 mixed ^= rijndael_mul(data[column], matrix[row][column])
f3bcebb1 291 data_mixed.append(mixed)
292 return data_mixed
293
5f6a1245 294
c8434e83 295def mix_columns(data, matrix=MIX_COLUMN_MATRIX):
f3bcebb1 296 data_mixed = []
297 for i in range(4):
2514d263 298 column = data[i * 4: (i + 1) * 4]
c8434e83 299 data_mixed += mix_column(column, matrix)
f3bcebb1 300 return data_mixed
301
5f6a1245 302
c8434e83 303def mix_columns_inv(data):
304 return mix_columns(data, MIX_COLUMN_MATRIX_INV)
305
5f6a1245 306
f3bcebb1 307def shift_rows(data):
308 data_shifted = []
309 for column in range(4):
310 for row in range(4):
5f6a1245 311 data_shifted.append(data[((column + row) & 0b11) * 4 + row])
f3bcebb1 312 return data_shifted
313
5f6a1245 314
c8434e83 315def shift_rows_inv(data):
316 data_shifted = []
317 for column in range(4):
318 for row in range(4):
5f6a1245 319 data_shifted.append(data[((column - row) & 0b11) * 4 + row])
c8434e83 320 return data_shifted
321
5f6a1245 322
f3bcebb1 323def inc(data):
5f6a1245 324 data = data[:] # copy
2514d263 325 for i in range(len(data) - 1, -1, -1):
f3bcebb1 326 if data[i] == 255:
327 data[i] = 0
328 else:
329 data[i] = data[i] + 1
330 break
331 return data