Reputation: 146
I am trying to write a function which computes the Rijndael S-box according to this Wikipedia article. Rijndael S-box
#define ROTL8(x,shift) ((uint8_t) ((x) << shift | ((x) >> (8 - (shift)))))
uint8_t sbox(uint8_t b)
{
uint8_t s = b ^ ROTL8(b,1) ^ ROTL8(b,2) ^ ROTL8(b,3) ^ ROTL8(b,4) ^ 0x63;
return s;
}
Now this works when I try sbox(0x00)=0x63 and sbox(0x01)=0x7c, but it starts to go astray from sbox(0x02), which should be 0x77, but I get 0x5d instead. I suspected the issue might be the rotation not working correctly, but that now does not seem like an issue...
What is wrong here?
Upvotes: 0
Views: 1383
Reputation: 5512
This is the wrong way to implement AES's S-box - most implementations are either hardcoded (they explicitly write the entire S-box as a 256-byte array), or they iteratively build the entries of the S-box, as in the Wikipedia article you linked:
void initialize_aes_sbox(uint8_t sbox[256]) {
uint8_t p = 1, q = 1;
/* loop invariant: p * q == 1 in the Galois field */
do {
/* multiply p by 3 */
p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0);
/* divide q by 3 (equals multiplication by 0xf6) */
q ^= q << 1;
q ^= q << 2;
q ^= q << 4;
q ^= q & 0x80 ? 0x09 : 0;
/* compute the affine transformation */
uint8_t xformed = q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4);
sbox[p] = xformed ^ 0x63;
} while (p != 1);
/* 0 is a special case since it has no inverse */
sbox[0] = 0x63;
}
notice that xformed
's value - which is the value you calculated in your own implementation - changes iteratively over the iterations (and it is not the S-box value of its q
the way you implemented). In practice, every manual S-box construction has some sort of similar iterative process - look over at Code Golf for some creative implementations.
Upvotes: 2