I'm implementing AES in C# and at some point (MixColumns function) I have to multiply two Bytes over the GF(2^8) finite field.
So, I have three options:
For the custom function I found a piece of C code which I tried to rewrite for C#, but it doesn't work (I get wrong results). (*)
Here is the original C piece of code (source):
/* Multiply two numbers in the GF(2^8) finite field defined
* by the polynomial x^8 + x^4 + x^3 + x + 1 */
uint8_t gmul(uint8_t a, uint8_t b) {
uint8_t p = 0;
uint8_t counter;
uint8_t hi_bit_set;
for (counter = 0; counter < 8; counter++) {
if (b & 1)
p ^= a;
hi_bit_set = (a & 0x80);
a <<= 1;
if (hi_bit_set)
a ^= 0x1b; /* x^8 + x^4 + x^3 + x + 1 */
b >>= 1;
}
return p;
}
And this is what I rewrote:
public Byte GMul(Byte a, Byte b) { // Galois Field (256) Multiplication
Byte p = 0;
Byte counter;
Byte hi_bit_set;
for (counter = 0; counter < 8; counter++) {
if ((b & 1) != 0) {
p ^= a;
}
hi_bit_set = (Byte) (a & 0x80);
a <<= 1;
if (hi_bit_set != 0) {
a ^= 0x1b; /* x^8 + x^4 + x^3 + x + 1 */
}
b >>= 1;
}
return p;
}
I also found some lookup tables here, and it seemed a simple and fine approach, but I don't really know how to use them, though I got a hunch. (**)
Bottom line: which option should I choose, and how can I make it work, given what I wrote above is all I got so far, and that I don't really want to go very deep with the math knowledge.
UPDATE:
*)
Meanwhile I realised my C# rewrote code was producing correct answers, it was just my fault because I messed up when I verified them.
**)
The tables can be used as a Byte[256] array, and the answer for, let's say, x*3
is table_3[x]
, x
being converted from HEX to DECIMAL when used as index for the table array.
In order to multiply x * 3 in GF(2), one just accesses x=table_3[x];
There's probably a 3 Look-up-table method available that uses a logarithm approach.
Just as in regular numbers a*b = 2^(log2(a)+log2(b)), the same happens in GF(2), but without floating points or rounding errors.