Key Expansion / Key Schedule

Each round use its own round key into the "Add Key" step that is derived from the original encryption key.

So, the Key Schedule will allow creating a different key for each encryption round, each of these sub-keys being 128 bits

The entire key length is then 128 times n+1 ( where n is the amount of round, depending of the original key size )

  • 12811=1408128 \cdot 11 = 1408 bits for AES-128

  • 12813=1664128 \cdot 13 = 1664 bits for AES-192

  • 12815=1920128 \cdot 15 = 1920 bits for AES-256

To make the key expansion, the original key is divided into 32 bits blocks called words

Here is 4 words for AES-128, 6 for AES-192 and 8 for AES-256

The next words are calculated following these graph :

Figure 1. AES 128 Expansion key
Figure 2. AES 192 Expansion key
Figure 3. AES 256 Expansion key

Algorithm steps

As explained before, AES-128 need a total key lenght of 1408 bits ( 1112811 \cdot 128 ).

As each word has a size of 32 bits, ( 140832=44\frac{1408}{32} = 44 )44 words are needed.

The first four words group

The first four words are provided by the original key.

  • W0 = key[0:31]

  • W1 = key[32:63]

  • W2 = key[64:95]

  • W3 = key[96:127]

Here, we have the four words of the key used for the round 0 ( before the 10 loops )

To serve as the round key for the ithi^{th} round, ii must be a multiple of 4.

These will obviously serve as the round key for the i/4thi/4^{th} round. For example :

  • w4, w5, w6, w7 is the round key for round 1

  • w8, w9, w10, w11 the round key for round 2,

  • and so on.

The others words groups

Let’s say that we have the four words of the round key for the i th round:

wi  wi+1  wi+2  wi+3w_i \; w_{i+1} \; w_{i+2} \; w_{i+3}

And we need to determine the words

wi+4  wi+5  wi+6  wi+7w_{i+4} \; w_{i+5} \; w_{i+6} \; w_{i+7}

Using the Figure 1, we can write :

wi+5=wi+4wi+1wi+6=wi+5wi+2wi+7=wi+6wi+3w_{i+5} = w_{i+4} \oplus w_{i+1} \\ w_{i+6} = w_{i+5} \oplus w_{i+2} \\ w_{i+7} = w_{i+6} \oplus w_{i+3} \\

Note that except for the first word in a new 4-word grouping, each word is an XOR of the previous word and the corresponding word in the previous 4-word grouping.

The first word of each groups

wi+4w_{i+4} is the beginning of the 4-word group and is obtained by using :

wi+4=wig(wi+3)w_{i+4} = w_i \oplus g(w_{i+3})

The first word of the new 4-word group is obtained by XOR’ing the first word of the last group ( wiw_i ) with the result of a function g() applied to the last word of the previous 4-word group

The g() function

The function g()g()consists of the following 3 steps :

  • Perform a one-byte left circular rotation on the argument 4-byte word.

  • Perform a byte substitution for each byte of the word using the same "S-box" in the SubBytes step of the encryption rounds

  • XOR the bytes obtained from the previous step with a round constant.

The round constant is a word whose three rightmost bytes are always zero.

Therefore, XOR’ing with the round constant amounts to XOR’ing with just its leftmost byte.

The round constant for the ithi^{th}round is noted Rcon[i]Rcon[i].

Rcon[i]=(RC[i],0,0,0)Rcon[i] = (RC[i], 0 , 0 ,0 )

The only non-zero byte in the round constants, RC[i]RC[i], obeys the following recursion:

RC[1]=0x01RC[i]=0x02RC[i1]RC[1] = 0x01 \\ RC[i] = 0x02 \cdot RC[i-1]

Python implementation

Last updated