https://www.quora.com/How-is-an-S-box-constructed-in-AES
https://www.youtube.com/watch?v=shaQZg8bqUM
https://en.wikipedia.org/wiki/Primitive_root_modulo_n
(Primitive root modulo n = generator)
A multiplicative inverse is a number that undoes multiplicative by a certain number, it is the replacement division operation in modular arithmetic. For example, if we are operating in GF(61), that is, all integers modulo 61, and we calculate some modular inverses:
modular inverse of 5 (% 61) = 49; (5 * 49) % 61 = 1
modular inverse of 29 (% 61) = 40; (29 * 40) % 61 = 1
Then we can use them to multiply and undo multiplication like so:
(5 * 29) % 61 = 23
(23 * 40) % 61 = 5
(23 * 49) % 61 = 29
By multiplying by the multiplicative inverse of each factor, we undid the multiplication.
The Rijndael s-box (substitution box; lookup table) is an array created using a generator. A generator in modular arithmetic is a value that when squared by consecutive powers continues to produce a unique value until every number in the modular field has been exhausted, thus, it is said to have a periodicity of the modulus minus one. Its purpose in AES serves to obscure the relationship between key and ciphertext.
In our code to generate the s-box, p starts out equalling 3, which means by multiplying it by 3 (over GF(2^8)) we are squaring it over and over again to generate a seemingly randomly placed but unique value <= 256. Our q value is the same thing, except we are going through its series of unique values backwards by squaring the multiplicative inverse of 3 (246 under our Galois field) over and over again. So with each unique value from the generator, we then calculate a circular left shift on q by 1, then the value by cls(q,2), then xor by cls(q,3), then xor by cls(q,4), then xor by 99. This entire design was developed with the cryptographical concept of nonlinearity in mind - obscuring the correlation between input and output. This is how it resists linear and differential cryptanalysis.
Once we have generated our s-box, we create our inverse s-box simply by switching index and value (ie s_box[0] = 99, inverse_s_box[99] = 0).