in Rijndael SubBytes()
step all bytes of input block are substituted based on a lookup table S-Box. S-Box is initialized by taking all elements of $GF(2^8)$, calculating their multiplicative inverse and then calculating their affine transform.
Here is C code which does that as found on wikipedia page.
#include <stdint.h>
#define ROTL8(x,shift) ((uint8_t) ((x) << (shift)) | ((x) >> (8 - (shift))))
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;
}
I cant wrap my head around how multiplicative inverse is being calculated here. I assume p
here acts as input while q
is its inverse. Hence $p*q = 1$.
I want to understand how exactly this works because I am trying to implement a function that initializes Rijndael inverse S-Box, where first the inverse affine transform is calculated and then the multiplicative inverse.
p
andq
as 1, but for calculating inverse S-Box you have inverse affine transforms for every element of $GF(2^8)$ and I assume calculating multiplicative inverse for those values requires a different approach $\endgroup$ – Ach113 Oct 20 '20 at 8:30invsbox[xformed ^ 0x63] = p
andinvsbox[0x63] = 0
after the corresponding assignments tosbox
. If you only need the inverse sbox, you can also delete the assignments tosbox
. $\endgroup$ – benrg Oct 20 '20 at 16:31