Calculate Intermediate value from the last Round of AES

I have tried to use this tutorial wiki.newae.com/Tutorial_B8_Prof … ate_Attack in order to make my first template attack in the first round of an AES.
My first experiment doesn’t give me good results, I have a nice Point of interest, however I don’t find any correct bytes from my secret key. So I decide to modify the template attack in order to attack the last round:

This the code to calculate the intermediate value for the first round and its hamming weight:

[code]# Useful utilities
sbox=(
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)
hw = [bin(x).count(“1”) for x in range(256)]

def cov(x, y):
# Find the covariance between two 1D lists (x and y).
# Note that var(x) = cov(x, x)
return np.cov(x, y)[0][1]

Start calculating template

1: load data

tempTraces = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_traces.npy’)
tempPText = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_textin.npy’)
tempKey = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_keylist.npy’)

2: Find HW(sbox) to go with each input

Note - we’re only working with the first byte here

tempSbox = [sbox[tempPText[i][0] ^ tempKey[i][0]] for i in range(len(tempPText))]
tempHW = [hw[s] for s in tempSbox]
[/code]

But I don’t find how to modify my code in order to calculate the intermediate value of the last round. As I know that:

  [code]

The intermediate value of the last round= SubBytes^(-1)[ShiftRows^(-1)[k10♁ciphertext]]
[/code]

If I suppose that is correct, Mus I just change this equation in my code???

tempSbox = [sbox[Ciphertext[i][0] ^ key[i][0]] for i in range(len(Ciphertext))] 

I would be very grateful if you could help me please: How to calculate please the intermediate value of the last round in python?

Hi Marita,

You posted this question on the Assembla page as well, so I’ll just copy my responses here:

Dear @gdeon , Thank you very much for your explanation. In fact, I have 500000 traces. Traces that I put, is just an example.

Based on the key_List I have calculated the 10th Round key. So as I understand, the key_Guess is the 10th round key. Right?

Then according to your answer about calculating intermediate value from the last round, as I understand the shiftRows step is not important and we can ignore it, by that way we just calculate the intermediate value for the byte 0 by this way : states = [inv_sbox[Ciphertexts[i][0] ^ Guess_Keys[i][0]] for i in range(len(Ciphertexts))]
then I take the state table to calculate the Hamming weight for each state, and I complete the template script without any modification as it was described in the tutorial.

To summarize:

[code]inv_sbox=(
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d)

hw = [bin(x).count(“1”) for x in range(256)]

Start calculating template

1: load data

Traces = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_traces.npy’)
Ciphertexts = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_textout.npy’)
Guess_Keys = np.load(r’C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_keylist.npy’)

2: Find HW(sbox) to go with each input

Note - we’re only working with the first byte here

states = [inv_sbox[Ciphertexts[i][0] ^ Guess_Keys[i][0]] for i in range(len(Ciphertexts))]
tempHW = [hw[s] for s in states]
[/code]

I’m just worried about one thing - how did you calculate the 10th round keys? In your code example it looks like you’re just loading the keys from the CWCapture output file, which is the initial round key. If you’ve used the key schedule to calculate the 10th round keys then you’re good to go.

Dear @gelon
I use this tutorial to calculate my 10th key,
risec.aist.go.jp/project/sas … 1_0616.pdf

This tutorial gives me RoundKey.exe program which let me to calculate the 10th Round, I add a simple batch file which lets me to do the same traitment for many keys. It takes a lot of time, but it gives me a correct results. Do you propse another way to calculate them?
Thank you in advance.

Hmm. I’m surprised that it takes a lot of time!

There’s a key schedule calculator built into ChipWhisperer. You can use by importing

from chipwhisperer.analyzer.attacks.models.aes.key_schedule import keyScheduleRounds

and then running

key_round10 = keyScheduleRounds(key, 0, 10)

However, I’m not sure this is any faster - it’s not very optimized, so 500000 keys could take a long time! You could also try to find an implementation of AES in C and use that key schedule code, but it’s hard to say if you can easily find something fast enough for you.

Thank you very much for your help.