Created
June 14, 2016 13:01
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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