cleanup, comments, and attribution of sources for various gf2 functions
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 8 Mar 2022 05:14:09 +0000 (05:14 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 8 Mar 2022 05:14:12 +0000 (05:14 +0000)
openpower/sv/gf2.py

index 420034d46be5a6be4cc031ef80ae69da1b03c523..ee21cd3a9736dd13116c89a01dc0d3889b959eef 100644 (file)
@@ -1,5 +1,14 @@
+# a mish-mash of various GF(2^m) functions from different sources
+# on the internet which help demonstrate arithmetic in GF(2^m)
+# these are intended to be implemented in hardware, so the basic
+# primitives need to be *real* basic: XOR, shift, AND, OR, etc.
+#
+# development discussion and links at:
+# https://bugs.libre-soc.org/show_bug.cgi?id=782
+
 from functools import reduce
 
+# https://stackoverflow.com/questions/45442396/
 def gf_degree(a) :
   res = 0
   a >>= 1
@@ -8,9 +17,17 @@ def gf_degree(a) :
     res += 1;
   return res
 
-# constants used in the multGF2 function
+
+# useful constants used throughout this module
 degree = mask1 = mask2 = polyred = None
 
+def getGF2():
+    """reconstruct the polynomial coefficients of g(x)
+    """
+    return polyred | mask1
+
+
+# original at https://jhafranco.com/tag/binary-finite-field/
 def setGF2(irPoly):
     """Define parameters of binary finite field GF(2^m)/g(x)
        - irPoly: coefficients of irreducible polynomial g(x)
@@ -29,12 +46,7 @@ def setGF2(irPoly):
     polyred = reduce(lambda x, y: (x << 1) + y, i2P(irPoly)[1:])
         
 
-def getGF2():
-    """reconstruct the polynomial coefficients of g(x)
-    """
-    return polyred | mask1
-
-
+# original at https://jhafranco.com/tag/binary-finite-field/
 def multGF2(p1, p2):
     """Multiply two polynomials in GF(2^m)/g(x)"""
     p = 0
@@ -48,6 +60,8 @@ def multGF2(p1, p2):
     return p & mask2
 
 
+# https://github.com/jpahullo/python-multiprocessing/
+# py_ecc/ffield.py
 def divmodGF2(f, v):
     fDegree, vDegree = gf_degree(f), gf_degree(v)
     res, rem = 0, f
@@ -62,6 +76,7 @@ def divmodGF2(f, v):
     return (res, rem)
 
 
+# https://en.m.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
 def xgcd(a, b):
     """return (g, x, y) such that a*x + b*y = g = gcd(a, b)"""
     x0, x1, y0, y1 = 0, 1, 1, 0
@@ -114,7 +129,7 @@ if __name__ == "__main__":
     print("%02x" % x)
     
     # Define binary field GF(2^8)/x^8 + x^4 + x^3 + x + 1
-    # (used in the Advanced Encryption Standard-AES)
+    # (used in Rijndael)
     # note that polyred has the MSB stripped!
     setGF2(0b100011011) # degree 8
     
@@ -130,14 +145,16 @@ if __name__ == "__main__":
 
     # reconstruct x by multiplying divided result by y and adding the remainder
     x1 = multGF2(res, y)
-    print("%02x == %02x" % (z, x1 ^ rem))
-
+    print("%02x == %02x" % (z, x1 ^ rem)) # XOR is "add" in GF2
 
+    # demo output of xgcd
     print(xgcd(x, y))
 
     #for i in range(1, 256):
     #   print (i, gf_invert(i))
 
+    # show how inversion-and-multiply works.  answer here should be "x":
+    # z = x * y, therefore z * (1/y) should equal "x"
     y1 = gf_invert(y)
     z1 = multGF2(z, y1)
     print(hex(polyred), hex(y1), hex(x), "==", hex(z1))