🏳️
The CTF Recipes
  • Introduction
  • Cryptography
    • Introduction
    • General knowledge
      • Encoding
        • Character encoding
          • ASCII
          • Unicode
          • UTF-8
        • Data encoding
          • Base16
          • Base32
          • Base64
      • Maths
        • Modular arithmetic
          • Greatest Common Divisor
          • Fermat's little theorem
          • Quadratic residues
          • Tonelli-Shanks
          • Chinese Remainder Theorem
          • Modular binomial
      • Padding
        • PKCS#7
    • Misc
      • XOR
    • Mono-alphabetic substitution
      • Index of coincidence
      • frequency analysis
      • Well known algorithms
        • 🔴Scytale
        • 🔴ROT
        • 🔴Polybe
        • 🔴Vigenere
        • 🔴Pigpen cipher
        • 🔴Affine cipher
    • Symmetric Cryptography
      • AES
        • Block Encryption procedure
          • Byte Substitution
          • Shift Row
          • Mix Column
          • Add Key
          • Key Expansion / Key Schedule
        • Mode of Operation
          • ECB
            • Block shuffling
              • Challenge example
            • ECB Oracle
              • Challenge example
          • CBC
            • Bit flipping
              • Challenge example
            • Padding oracle
              • Challenge example
          • OFB
            • Key stream reconstruction
            • Encrypt to Uncrypt
  • 🛠️Pwn
    • General knowledge
      • STACK
        • Variables storage
        • Stack frame
      • PLT and GOT
      • HEAP
        • HEAP operations
        • Chunk
        • Bins
        • Chunk allocation and reallocation
      • Syscall
    • Architectures
      • aarch32
        • Registers
        • Instruction set
        • Calling convention
      • aarch64
        • Registers
        • Instruction set
        • Calling convention
      • mips32
        • Registers
        • Instruction set
        • Calling convention
      • mips64
        • Registers
        • Instruction set
        • Calling convention
      • x86 / x64
        • Registers
        • Instruction set
        • Calling convention
    • Stack exploitation
      • Stack Buffer Overflow
        • Dangerous functions
          • gets
          • memcpy
          • sprintf
          • strcat
          • strcpy
        • Basics
          • Challenge example
        • Instruction pointer Overwrite
          • Challenge example
        • De Bruijn Sequences
        • Stack reading
          • Challenge example
      • Format string
        • Dangerous functions
          • printf
          • fprintf
        • Placeholder
        • Data Leak
          • Challenge example
        • Data modification
          • Challenge example
      • Arbitrary code execution
        • Shellcode
        • ret2reg
        • Code reuse attack
          • Ret2plt
          • Ret2dlresolve
          • GOT Overwrite
          • Ret2LibC
          • Leaking LibC
          • Ret2csu
          • Return Oriented Programming - ROP
          • Sigreturn Oriented Programming - SROP
          • Blind Return Oriented Programming - BROP
            • Challenge example
          • 🔴Call Oriented Programming - COP
          • 🔴Jump Oriented Programming - JOP
          • One gadget
        • Stack pivoting
    • 🛠️Heap exploitation
      • Heap overflow
        • Challenge example
      • Use after free
        • Challenge example
      • 🛠️Double free
      • 🔴Unlink exploit
    • Protections
      • Stack Canaries
      • No eXecute
      • PIE
      • ASLR
      • RELRO
    • Integer overflow
Powered by GitBook
On this page
  • Python implementation
  • Optimized
  1. Cryptography
  2. Symmetric Cryptography
  3. AES
  4. Block Encryption procedure

Mix Column

The "Mix Column" operates on the rows of the 4x4 state matrix.

It is a non-linear operation that involves multiplying each column by a fixed matrix and reducing the result modulo a fixed polynomial.

The fixed matrice is the following :

+-------------+
| 02 03 01 01 |
| 01 02 03 01 |
| 01 01 02 03 |
| 03 01 01 02 |
+-------------+

Then the operation is the following :

Fixed matrice        User data          Result
+-------------+     +-------------+     +-------------+
| 02 03 01 01 |     | 00 01 02 03 |     | r1 r2 r3 r4 |
| 01 02 03 01 |     | 11 12 13 10 |     | ...         |
| 01 01 02 03 |  *  | 22 23 20 21 |  =  |      ?      |
| 03 01 01 02 |     | 33 30 31 32 |     |             |
+-------------+     +-------------+     +-------------+

Each row of the result are made by the result of the operation of the fixed matrice row times each column : 

r1 = ( 02 * 00 ) ⊕ ( 03 * 11 ) ⊕ ( 01 * 22 ) ⊕ ( 01 * 33 )
r2 = ( 02 * 01 ) ⊕ ( 03 * 12 ) ⊕ ( 01 * 23 ) ⊕ ( 01 * 30 ) 
r3 = ( 02 * 02 ) ⊕ ( 03 * 13 ) ⊕ ( 01 * 20 ) ⊕ ( 01 * 31 )
etc. 

Because of all operation are a Galois Field multiplication, it is not only a times 2 or 3

Only 3 operators are used into this operation :

  • 1

  • 2

  • 3

It make easier to explain a process to calculate the result of the mix column operation, but keep in mind that it look easy but it is not.

Here is only a limited explanation that do not cover the entire mathematics behavior of this maths tool

All operations are made with the binary forms of the number.

  • Multiply by 1 is just like standard decimal operation, a * 1 = a

  • Multiply by 2

a * 2 = a << 1 (<< is left shift, 1 is the number of shift done, pad on with 0's)

Because we work into GF(2^8), the number can't have more than 8 bits, so if there is more after the bit shift, then the number must be xored with 0b0011011

This value is calculated using the irreducible Polynomial theorem that it will not be explain here.

Here is an example with 0xd4 * 2

d4 = 11010100
d4 * 2 = 11010100 * 10 
       = 110101000
110101000 and 100000000 = 1
d4 * 2 = (110101000 % 100000000) ⊕ 0011011 
       = 10110011

The xor operation is done only because d4 * 02 >= 100000000

  • Multiply by 3

3 = 11 (in binary form) 
11 = 10 ⊕ 01

It mean that : 

a * 3 = (bin(a) * 10) ⊕ (bin(a) * 01)

bin(a) * 01 = a * 1
            = a
                        
bin(a) * 10 = a * 2

So : 
a * 3 = a * 2 ⊕ a

Here is an example with 0xd4 * 3

d4 = 11010100
d4 * 2 =  10110011 ( such as explained before )
d4 * 3 = d4 * 2 ⊕ d4 
       = 10110011 ⊕ 11010100
       = 1100111

Python implementation

import copy

def galois_mult(a, b):
    """
    Multiplication in the Galois field GF(2^8).
    """
    p = 0
    hi_bit_set = 0
    for i in range(2):
        if b & 1 == 1: p ^= a
        hi_bit_set = a & 0x80
        a <<= 1
        if hi_bit_set == 0x80: a ^= 0x1b
        b >>= 1
    return p % 256

def mixcolumn(column):
    """
    Mix one column by by considering it as a polynomial and performing
    operations in the Galois field (2^8).
    """
    # XOR is addition in this field
    temp = copy.copy(column) # Store temporary column for operations
    column[0] = galois_mult(temp[0], 2) ^ galois_mult(temp[1], 3) ^ \
                galois_mult(temp[2], 1) ^ galois_mult(temp[3], 1)
    column[1] = galois_mult(temp[0], 1) ^ galois_mult(temp[1], 2) ^ \
                galois_mult(temp[2], 3) ^ galois_mult(temp[3], 1)
    column[2] = galois_mult(temp[0], 1) ^ galois_mult(temp[1], 1) ^ \
                galois_mult(temp[2], 2) ^ galois_mult(temp[3], 3)
    column[3] = galois_mult(temp[0], 3) ^ galois_mult(temp[1], 1) ^ \
                galois_mult(temp[2], 1) ^ galois_mult(temp[3], 2)

def mixcolumns(state):
    """
    Perform a mixing operation which operates on the columns of the states,
    combining the four bytes in each column.
    """
    for i in range(len(state)):
        # Create column from the corresponding array positions
        column = copy.copy(state[i])

        # Mix the extracted column
        mixcolumn(column)

        # Set the new column in the state
        state[i] = column
    return state

Optimized

# learned from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)


def mix_single_column(a):
    # see Sec 4.1.2 in The Design of Rijndael
    t = a[0] ^ a[1] ^ a[2] ^ a[3]
    u = a[0]
    a[0] ^= t ^ xtime(a[0] ^ a[1])
    a[1] ^= t ^ xtime(a[1] ^ a[2])
    a[2] ^= t ^ xtime(a[2] ^ a[3])
    a[3] ^= t ^ xtime(a[3] ^ u)
    return a


def mix_columns(s):
    for i in range(4):
        s[i] = mix_single_column(s[i])
    return s


def inv_mix_columns(s):
    # see Sec 4.1.3 in The Design of Rijndael
    for i in range(4):
        u = xtime(xtime(s[i][0] ^ s[i][2]))
        v = xtime(xtime(s[i][1] ^ s[i][3]))
        s[i][0] ^= u
        s[i][1] ^= v
        s[i][2] ^= u
        s[i][3] ^= v
    print(s)
    return mix_columns(s)
PreviousShift RowNextAdd Key

Last updated 2 years ago