1

I'm into developing code to do arithmetic in Galois field gf(2^8) and I think I'm getting wrong results on multiplication operations.

private static byte Multiply(byte a, byte b)
{
    byte result = 0;

    while (b != 0)
    {
        if ((b & 1) != 0)
        {
            result ^= a;
        }

        a <<= 1;
        b >>= 1;
    }

    return result;
}

The result for Multiply(1, 2) gives the correct value of 2 but Multiply(240, 249) gives me 112 instead of the expected 148.

Now I'm not sure if this value is good or not with Russian Peasant Multiplication.

Maybe there's another algorithm that gives correct results?

Eldar
  • 9,781
  • 2
  • 10
  • 35
Macko
  • 906
  • 3
  • 11
  • 27

1 Answers1

1

Example code:

#define POLY 0x11D

static BYTE GFMpy(BYTE b0, BYTE b1)
{
int i;
int product;
    product = 0;
    for(i = 0; i < 8; i++){
        product <<= 1;
        if(product & 0x100){
            product ^= POLY;}
        if(b0 & 0x80u){
            product ^= b1;}
        b0 <<= 1;}
    return((BYTE)product);
}

Example using lookup tables:

#define POLY (0x11d)
/* all non-zero elements are powers of 2 for POLY == 0x11d */
typedef unsigned char BYTE;
/* ... */
static BYTE exp2[512];
static BYTE log2[256];
/* ... */
static void Tbli()
{
int i;
int b;
    b = 0x01;                   /* init exp2 table */
    for(i = 0; i < 512; i++){
        exp2[i] = (BYTE)b;
        b = (b << 1);           /*  powers of 2 */
        if(b & 0x100)
            b ^= POLY;
    }

    log2[0] = 0xff;             /* init log2 table */
    for(i = 0; i < 255; i++)
        log2[exp2[i]] = (BYTE)i;
}
/* ... */
static BYTE GFMpy(BYTE m0, BYTE m1) /* multiply */
{
    if(0 == m0 || 0 == m1)
        return(0);
    return(exp2[log2[m0] + log2[m1]]);
}
/* ... */
static BYTE GFDiv(BYTE m0, BYTE m1) /* divide */
{
    if(0 == m0)
        return(0);
    return(exp2[log2[m0] + 255 - log2[m1]]);
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • If u can explain what are these magic numbers: 0x100 and 0x80u ? And why they are used? Is it specific to only one GF ? – Macko Dec 12 '21 at 12:16
  • Multiply(240, 249) is giving me value of 119 with POLY = 0x11B. Is it correct ? – Macko Dec 12 '21 at 12:33
  • 1
    @Macko - 0x100 represents x^8. All GF(2^8) polynomials are of the form x^8 + ... + 1. 0x80 represents x^7, the most significant bit of a byte. Multiply(240,249) with POLY:0x11D = 148. Multiply(240,249) with POLY:0x11B = 119. – rcgldr Dec 12 '21 at 17:20
  • how to implement division in GF ? – Macko Dec 12 '21 at 21:43
  • 1
    @Macko - you could raise a number to the 254th power (x^254 == 1/x in GF(2^8)), but it would be faster to generate exponentiate and log tables (base 2). I updated my answer to show the table version. – rcgldr Dec 13 '21 at 05:21
  • Great, can u share some numbers for unit tests ? – Macko Dec 13 '21 at 07:59
  • @Macko - you know the multiply works, so try multiplying two numbers, then divide the product by one of the numbers and see if it returns the other number. Do this for a few numbers. – rcgldr Dec 13 '21 at 09:42
  • why exp2[512] is set to this lenght ? – Macko Dec 16 '21 at 10:47
  • how to implement mod and pow operation in this field? – Macko Dec 16 '21 at 20:57
  • @Macko power - use [exponentiation by repeated squaring](https://simple.wikipedia.org/wiki/Exponentiation_by_squaring) . Modulo = number xor ((number / modulus) * modulus), since the field division rounds down. exp is 512 bytes long so a check for greater than 255 is not needed for multiply, and 255 is added for divide so a check for less than zero is not needed for divide. – rcgldr Dec 17 '21 at 04:49