+# 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
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)
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
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
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
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
# 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))