Skip to content

Instantly share code, notes, and snippets.

@qnighy
Created June 14, 2016 13:01
Show Gist options
  • Select an option

  • Save qnighy/f460f9898a8af8c8765e08b317f5331a to your computer and use it in GitHub Desktop.

Select an option

Save qnighy/f460f9898a8af8c8765e08b317f5331a to your computer and use it in GitHub Desktop.
GF(256) = GF(2^8) = GF(2)[x]/(x^8 + x^4 + x^3 + x + 1)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class GF256(object):
""" GF(256), defined as GF(2)[x]/(x^8 + x^4 + x^3 + x + 1).
"""
def __init__(self, byteval):
byteval = int(byteval)
assert 0 <= byteval < 256
self.byteval = byteval
def __str__(self):
return "GF256(" + str(self.byteval) + ")"
def __repr__(self):
return "GF256(" + str(self.byteval) + ")"
def __add__(self, other):
return GF256(self.byteval ^ other.byteval)
def __sub__(self, other):
return GF256(self.byteval ^ other.byteval)
def __mul__(self, other):
ret = 0
for i in range(8):
if (other.byteval >> i) & 1:
ret ^= self.byteval << i
for i in reversed(range(8)):
ret = min(ret, ret ^ (283 << i))
return GF256(ret)
def __pow__(self, exponent):
if self.byteval == 0 and exponent < 0:
raise ZeroDivisionError("division by zero")
exponent = exponent % 255
ret = GF256(1)
for i in reversed(range(8)):
ret = ret * ret
if (exponent >> i) & 1:
ret = ret * self
return ret
def inverse(self):
return self ** -1
def __truediv__(self, other):
return self * other.inv()
def generate_log_table():
e = list(range(255))
l = list(range(256))
x = GF256(1)
for i in range(255):
e[i] = x.byteval
l[x.byteval] = i
x = x * GF256(3)
return (e, l)
gf256exp3, gf256log3 = generate_log_table()
class GF256(object):
"""
GF(256), defined as GF(2)[x]/(x^8 + x^4 + x^3 + x + 1).
This is a fast version using log3/exp3 tables.
"""
exp3 = gf256exp3
log3 = gf256log3
def __init__(self, byteval):
byteval = int(byteval)
assert 0 <= byteval < 256
self.byteval = byteval
def __str__(self):
return "GF256(" + str(self.byteval) + ")"
def __repr__(self):
return "GF256(" + str(self.byteval) + ")"
def __add__(self, other):
return GF256(self.byteval ^ other.byteval)
def __sub__(self, other):
return GF256(self.byteval ^ other.byteval)
def __mul__(self, other):
if self.byteval == 0:
return self
if other.byteval == 0:
return other
return GF256(GF256.exp3[(
GF256.log3[self.byteval] +
GF256.log3[self.byteval]) % 255])
def __pow__(self, exponent):
if self.byteval == 0:
if exponent < 0:
raise ZeroDivisionError("division by zero")
return self
return GF256(GF256.exp3[(
GF256.log3[self.byteval] * exponent) % 255])
def inverse(self):
return self ** -1
def __truediv__(self, other):
return self * other.inv()
def rijndael_s(x):
if x == 0:
xi = 0
else:
xi = GF256(x).inverse().byteval
y0 = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
y = 255 & (y0 ^ (y0 >> 8) ^ 99)
return y
print([hex(rijndael_s(x)) for x in range(256)])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment