Issues modifying manual CPA attack example

Hi, I am trying to modify the provided manual CPA attack example. Apologies if my security knowledge is lacking. This is my first real foray into hands on security attacks!

As a starting point, I simplified the provided example and removed ‘aes_indep_enc(pt)’ in the get_pt function of ‘simpleserial-aes.c’ and replaced it with just the sbox operation, like this:

for(int i=0; i<16; i++){
pt[i] = sbox[(pt[i]^key[i])];
}

The key array is populated in the get_key function before this and I copied the sbox into this file as well.

With this modification the attack still works. But beyond this, any modification I make throws a ‘true_divide’ error in numpy in line ‘cpaoutput[kguess] = sumnum / np.sqrt(sumden1 * sumden2)’.

So what I am really trying to do here is mimic this attack for a multiplication. so based on multiplying the ‘plaintext’ with a ‘key’ can i recover the key in the same way.

But changing the ‘^’ to ‘*’ causes this true divide error even when i still keep the sbox lookup which I wont for my actual attack.

Any suggestions would be appreciated!

Sounds like you’ve run into a divide by zero?

Hi, Yes you are absolutely right. it is a divide by zero. I’m trying to understand why it happens when i change the operation but XOR works. none of the values in the SBOX table are 0. so no matter what index I use it should always return a non-zero value. Yet when I replace the XOR with another operation the code still breaks!

I tried setting the numpy error to ignore but then it just always outputs a guess of all 0s. so whatever causes this divide by zero exception just totally kills the correlation code and it always gives me zeros.

So is the correlation code basically not designed to work for this corner case? Do you have suggestions?

Hmm, are you taking the example code from PA_CPA_2-Manual_CPA_Attack.ipynb and changing

def intermediate(pt, keyguess):
    return sbox[pt ^ keyguess]

to this?

def intermediate(pt, keyguess):
    return sbox[pt * keyguess]

If so, you’re replacing the bitwise XOR operator, which here takes two 8-bit inputs and returns an 8-bit output, with a multiplication, which returns a 16-bit ouput. But sbox[x] for x >= 2**8 isn’t defined! This may be where your divide by zeros are coming from.

Apologies if I’ve misunderstood what you’re doing.
(Also there is a zero in the sbox table… it’s a bijection [0, 255] -> [0,255], including 0).

Jean-Pierre

Yes, exactly. Sorry, I didn’t provide all the details in my original post. So when I change it to *, I also mask it to prevent out of bounds access. So I do,

sbox[(pt*keyguess)&0xFF]. 

No, what you are saying is what I’m trying to do. And it’s interesting then why i’m getting this. For instance I ran another experiement and changed the line to

sbox[pt&keyguess]. 

And I still get the true divide error. So maybe I am just hitting a corner case of the CPA algorithm as written?

I agree, a big part of the challenge for me is that I don’t have a theoretical basis in security attacks such as CPA. So I’m trying to figure it out as I do this! I’ve been reading lots of papers that show CPA attacks on AES to better understand the theory but I still dont feel very comfortable with it.

I’d look at it from a different point of view. Work out the math; why is the divide by zero happening? What does it mean? Put a breakpoint in the attack code and try to understand what’s happening.

Jean-Pierre

Yes, I think you are absolutely right. That’s what I’m going to try to do now and see if I can figure out why i see this odd behaviour first. Thank you!

Hi, Just to close this out, the issue was because multiplication can result in a ‘kguess’ of 0. In the provided AES example, kguess never got a value of zero so this true_divide issue was never seen. So when I changed the loop bounds from ‘range(0,256)’ to ‘range(1,256)’, the problem is resolved.