youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

aes.py (16130B)


      1 from __future__ import unicode_literals
      2 
      3 from math import ceil
      4 
      5 from .compat import compat_b64decode
      6 from .utils import bytes_to_intlist, intlist_to_bytes
      7 
      8 BLOCK_SIZE_BYTES = 16
      9 
     10 
     11 def aes_ctr_decrypt(data, key, counter):
     12     """
     13     Decrypt with aes in counter mode
     14 
     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
     20     """
     21     expanded_key = key_expansion(key)
     22     block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
     23 
     24     decrypted_data = []
     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))
     29 
     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)]
     33 
     34     return decrypted_data
     35 
     36 
     37 def aes_cbc_decrypt(data, key, iv):
     38     """
     39     Decrypt with aes in CBC mode
     40 
     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
     45     """
     46     expanded_key = key_expansion(key)
     47     block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
     48 
     49     decrypted_data = []
     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))
     54 
     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)]
     59 
     60     return decrypted_data
     61 
     62 
     63 def aes_cbc_encrypt(data, key, iv):
     64     """
     65     Encrypt with aes in CBC mode. Using PKCS#7 padding
     66 
     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
     71     """
     72     expanded_key = key_expansion(key)
     73     block_count = int(ceil(float(len(data)) / BLOCK_SIZE_BYTES))
     74 
     75     encrypted_data = []
     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)
     82 
     83         encrypted_block = aes_encrypt(mixed_block, expanded_key)
     84         encrypted_data += encrypted_block
     85 
     86         previous_cipher_block = encrypted_block
     87 
     88     return encrypted_data
     89 
     90 
     91 def key_expansion(data):
     92     """
     93     Generate key schedule
     94 
     95     @param {int[]} data  16/24/32-Byte cipher key
     96     @returns {int[]}     176/208/240-Byte expanded key
     97     """
     98     data = data[:]  # copy
     99     rcon_iteration = 1
    100     key_size_bytes = len(data)
    101     expanded_key_size_bytes = (key_size_bytes // 4 + 7) * BLOCK_SIZE_BYTES
    102 
    103     while len(data) < expanded_key_size_bytes:
    104         temp = data[-4:]
    105         temp = key_schedule_core(temp, rcon_iteration)
    106         rcon_iteration += 1
    107         data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
    108 
    109         for _ in range(3):
    110             temp = data[-4:]
    111             data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
    112 
    113         if key_size_bytes == 32:
    114             temp = data[-4:]
    115             temp = sub_bytes(temp)
    116             data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
    117 
    118         for _ in range(3 if key_size_bytes == 32 else 2 if key_size_bytes == 24 else 0):
    119             temp = data[-4:]
    120             data += xor(temp, data[-key_size_bytes: 4 - key_size_bytes])
    121     data = data[:expanded_key_size_bytes]
    122 
    123     return data
    124 
    125 
    126 def aes_encrypt(data, expanded_key):
    127     """
    128     Encrypt one block with aes
    129 
    130     @param {int[]} data          16-Byte state
    131     @param {int[]} expanded_key  176/208/240-Byte expanded key
    132     @returns {int[]}             16-Byte cipher
    133     """
    134     rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
    135 
    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)
    140         if i != rounds:
    141             data = mix_columns(data)
    142         data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
    143 
    144     return data
    145 
    146 
    147 def aes_decrypt(data, expanded_key):
    148     """
    149     Decrypt one block with aes
    150 
    151     @param {int[]} data          16-Byte cipher
    152     @param {int[]} expanded_key  176/208/240-Byte expanded key
    153     @returns {int[]}             16-Byte state
    154     """
    155     rounds = len(expanded_key) // BLOCK_SIZE_BYTES - 1
    156 
    157     for i in range(rounds, 0, -1):
    158         data = xor(data, expanded_key[i * BLOCK_SIZE_BYTES: (i + 1) * BLOCK_SIZE_BYTES])
    159         if i != rounds:
    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])
    164 
    165     return data
    166 
    167 
    168 def aes_decrypt_text(data, password, key_size_bytes):
    169     """
    170     Decrypt text
    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'
    175 
    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
    180     """
    181     NONCE_LENGTH_BYTES = 8
    182 
    183     data = bytes_to_intlist(compat_b64decode(data))
    184     password = bytes_to_intlist(password.encode('utf-8'))
    185 
    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)
    188 
    189     nonce = data[:NONCE_LENGTH_BYTES]
    190     cipher = data[NONCE_LENGTH_BYTES:]
    191 
    192     class Counter(object):
    193         __value = nonce + [0] * (BLOCK_SIZE_BYTES - NONCE_LENGTH_BYTES)
    194 
    195         def next_value(self):
    196             temp = self.__value
    197             self.__value = inc(self.__value)
    198             return temp
    199 
    200     decrypted_data = aes_ctr_decrypt(cipher, key, Counter())
    201     plaintext = intlist_to_bytes(decrypted_data)
    202 
    203     return plaintext
    204 
    205 
    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)
    279 
    280 
    281 def sub_bytes(data):
    282     return [SBOX[x] for x in data]
    283 
    284 
    285 def sub_bytes_inv(data):
    286     return [SBOX_INV[x] for x in data]
    287 
    288 
    289 def rotate(data):
    290     return data[1:] + [data[0]]
    291 
    292 
    293 def key_schedule_core(data, rcon_iteration):
    294     data = rotate(data)
    295     data = sub_bytes(data)
    296     data[0] = data[0] ^ RCON[rcon_iteration]
    297 
    298     return data
    299 
    300 
    301 def xor(data1, data2):
    302     return [x ^ y for x, y in zip(data1, data2)]
    303 
    304 
    305 def rijndael_mul(a, b):
    306     if(a == 0 or b == 0):
    307         return 0
    308     return RIJNDAEL_EXP_TABLE[(RIJNDAEL_LOG_TABLE[a] + RIJNDAEL_LOG_TABLE[b]) % 0xFF]
    309 
    310 
    311 def mix_column(data, matrix):
    312     data_mixed = []
    313     for row in range(4):
    314         mixed = 0
    315         for column in range(4):
    316             # xor is (+) and (-)
    317             mixed ^= rijndael_mul(data[column], matrix[row][column])
    318         data_mixed.append(mixed)
    319     return data_mixed
    320 
    321 
    322 def mix_columns(data, matrix=MIX_COLUMN_MATRIX):
    323     data_mixed = []
    324     for i in range(4):
    325         column = data[i * 4: (i + 1) * 4]
    326         data_mixed += mix_column(column, matrix)
    327     return data_mixed
    328 
    329 
    330 def mix_columns_inv(data):
    331     return mix_columns(data, MIX_COLUMN_MATRIX_INV)
    332 
    333 
    334 def shift_rows(data):
    335     data_shifted = []
    336     for column in range(4):
    337         for row in range(4):
    338             data_shifted.append(data[((column + row) & 0b11) * 4 + row])
    339     return data_shifted
    340 
    341 
    342 def shift_rows_inv(data):
    343     data_shifted = []
    344     for column in range(4):
    345         for row in range(4):
    346             data_shifted.append(data[((column - row) & 0b11) * 4 + row])
    347     return data_shifted
    348 
    349 
    350 def inc(data):
    351     data = data[:]  # copy
    352     for i in range(len(data) - 1, -1, -1):
    353         if data[i] == 255:
    354             data[i] = 0
    355         else:
    356             data[i] = data[i] + 1
    357             break
    358     return data
    359 
    360 
    361 __all__ = ['aes_encrypt', 'key_expansion', 'aes_ctr_decrypt', 'aes_cbc_decrypt', 'aes_decrypt_text']