SNAPKITTYWEST's picture
push from SNAPKITTYWEST/aes-verification-suite
51bd9ff verified
Raw History Blame Contribute Delete
2.34 kB
"""
GF(2^8) Field Arithmetic for AES Verification
Irreducible polynomial: x^8 + x^4 + x^3 + x + 1 (0x11B)
All 256 elements, verified multiplicative group of order 255.
"""
def gf_mul(a: int, b: int) -> int:
"""Multiply two elements in GF(2^8)."""
p = 0
for _ in range(8):
if b & 1:
p ^= a
hi = a & 0x80
a = (a << 1) & 0xFF
if hi:
a ^= 0x1B
b >>= 1
return p
def gf_pow(x: int, n: int) -> int:
"""Compute x^n in GF(2^8) via square-and-multiply."""
result = 1
base = x
while n > 0:
if n & 1:
result = gf_mul(result, base)
base = gf_mul(base, base)
n >>= 1
return result
def gf_inv(x: int) -> int:
"""Multiplicative inverse: x^{-1} = x^254 in GF(2^8). Convention: 0^{-1} = 0."""
if x == 0:
return 0
return gf_pow(x, 254)
def verify_field():
"""Verify GF(2^8) properties."""
results = {}
# 1. x * x^254 = 1 for all nonzero x (Fermat's little theorem)
fermat_ok = all(gf_mul(x, gf_pow(x, 254)) == 1 for x in range(1, 256))
results["fermat_little_theorem"] = fermat_ok
# 2. Multiplicative group is cyclic of order 255
# Find a generator (primitive element)
generator = None
for g in range(2, 256):
seen = set()
val = 1
for _ in range(255):
val = gf_mul(val, g)
seen.add(val)
if len(seen) == 255:
generator = g
break
results["generator_exists"] = generator is not None
results["generator_value"] = generator
# 3. x^255 = 1 for all nonzero x
order_ok = all(gf_pow(x, 255) == 1 for x in range(1, 256))
results["all_order_divides_255"] = order_ok
# 4. Distributivity: a * (b ^ c) = (a*b) ^ (a*c)
import random
random.seed(42)
dist_ok = True
for _ in range(10000):
a = random.randint(0, 255)
b = random.randint(0, 255)
c = random.randint(0, 255)
lhs = gf_mul(a, b ^ c)
rhs = gf_mul(a, b) ^ gf_mul(a, c)
if lhs != rhs:
dist_ok = False
break
results["distributivity"] = dist_ok
return results
if __name__ == "__main__":
results = verify_field()
print("GF(2^8) Verification:")
for k, v in results.items():
print(f" {k}: {v}")