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