1

How would I implement the Multiplicative Inverse in GF2^8 in Python 3? My current functions look like this:

def gf_add(a, b):
    return a ^ b

def gf_mul(a, b, mod=0x1B):
    p = bytes(hex(0x00))
    for i in range(8):
        if (b & 1) != 0:
            p ^= a
        high_bit_set = bytes(a & 0x80)
        a <<= 1
        if high_bit_set != 0:
            a ^= mod
        b >>= 1
    return p
Jonas
  • 6,915
  • 8
  • 35
  • 53
DarkPhoenix6
  • 54
  • 1
  • 9
  • I do not really get what the `mod` part is doing. – Willem Van Onsem Aug 01 '17 at 15:57
  • multiplication in a finite field is multiplication of two polynomials then divided by a modulus the result is the product – DarkPhoenix6 Aug 01 '17 at 16:06
  • The best way is probably to make a table with the powers of a generator g (by definition, powers of g include every element of the field except 0, and `g**255 == 1`). You find which exponent of g corresponds to the element you're inverting (call it e), and then find the element that corresponds to the exponent (255-e), that will be the multiplicative inverse. It's basically using logarithms. Also, finite fields always have generators. – jpkotta Aug 01 '17 at 16:28

2 Answers2

3

Here is how I'd do it:

def gf_degree(a) :
  res = 0
  a >>= 1
  while (a != 0) :
    a >>= 1;
    res += 1;
  return res

def gf_invert(a, mod=0x1B) :
  v = mod
  g1 = 1
  g2 = 0
  j = gf_degree(a) - 8

  while (a != 1) :
    if (j < 0) :
      a, v = v, a
      g1, g2 = g2, g1
      j = -j

    a ^= v << j
    g1 ^= g2 << j

    a %= 256  # Emulating 8-bit overflow
    g1 %= 256 # Emulating 8-bit overflow

    j = gf_degree(a) - gf_degree(v)

  return g1

The function gf_degree calculates the degree of the polynomial, and gf_invert, naturally, inverts any element of GF(2^8), except 0, of course. The implementation of gf_invert follows a "text-book" algorithm on finding the multiplicative inverse of elements of a finite field.

Example

print(gf_invert(5))   # 82
print(gf_invert(1))   #  1
print(gf_invert(255)) # 28

Here is a live demo.

As mentioned in the comments you could also have used a logarithmic approach, or simply use brute force (trying every combination of multiplication).

Jonas
  • 6,915
  • 8
  • 35
  • 53
  • I understand finite fields but have no idea what algorithm your code actually uses. – Jason S Aug 15 '17 at 22:59
  • @JasonS To be fair I implemented this in my C++ GF2^X library (and ported it to Python for this answer), and I do not remember the name (or author(s)) of the algorithm. However, I do remember that my implementation is based on an algorithm from a textbook I used. – Jonas Aug 16 '17 at 09:10
  • 1
    @JasonS - This appears to be a variation of [extended Euclid algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers) . If mod was set to 0x11B, a typical implementation of extended Euclid algorithm could be used, without the degree function or the %= 256 lines. If using the typical approach, there's a check needed at the end: `if(g1 < 0)g1 += mod` . Note if using log tables, that for mod 0x11b, every number in the field other than 0 is a power of 3 (versus the usual 2). – rcgldr Aug 29 '17 at 20:07
  • Ok that makes sense, so it's trying to solve ka + mv = 1 in the polynomial ring GF(2)[x], where a = polynomial to be inverted, and v = `0x11b`. – Jason S Aug 29 '17 at 20:51
  • @JasonS - correct and only `k` needs to be calculated, `m` is not needed for the inverse. If you did want `m`, you could duplicate the logic for `g1` and `g2`, using `h1` and `h2`, starting with `h1 = 0` and `h2 = 1`. For software, a 256 byte table could be used. In hardware, the gate count can be reduced from that needed for a 256 byte table by using sub-field mapping, as noted in [compact AES S box.pdf](https://pdfs.semanticscholar.org/1442/dff91bf7a583cb776b024e5375f29b21b239.pdf), which also uses mod == 0x11B, mapping an 8 bit field to two 4 bit fields then to four 2 bit fields. – rcgldr Aug 30 '17 at 01:08
2

You might look at my libgf2 module (which no one else actually uses) and use GF2Element:

from libgf2 import GF2Element

x = GF2Element(0x8, 0x11B)
x.inv 
# find the inverse of x^3 in the quotient ring GF(2)[x]/p(x)
# where p(x) = x^8 + x^4 + x^3 + x + 1 (0x11B in bit vector format)

See this blog article for more details.


Note: libgf2 is in Python 2.7 so you'd have to port to Python 3, but it's a fairly small library.

Jason S
  • 184,598
  • 164
  • 608
  • 970