From b5703e6f50b35efaa6b7820773273827d2d5cc7a Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Sat, 27 May 2023 10:58:16 -0700 Subject: [PATCH] add first cut of GF(2^8).. --- shamirss.py | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 shamirss.py diff --git a/shamirss.py b/shamirss.py new file mode 100644 index 0000000..1221c12 --- /dev/null +++ b/shamirss.py @@ -0,0 +1,117 @@ +import unittest +import random + +def _makered(x, y): + '''Make reduction table entry. + + given x * 2^8, reduce it assuming polynomial y. + ''' + + x = x << 8 + + for i in range(3, -1, -1): + if x & (1 << (i + 8)): + x ^= (0x100 + y) << i + + assert x < 256 + + return x + +class GF2p8: + @staticmethod + def _primativemul(a, b): + masks = [ 0, 0xff ] + + r = 0 + + for i in range(0, 8): + mask = a & 1 + r ^= (masks[mask] & b) << i + a = a >> 1 + + return r + + # polynomial 0x187 + _reduce = { x: _makered(x, 0x87) for x in range(0, 16) } + + def __init__(self, v): + if v >= 256: + raise ValueError('%d is not a member of GF(2^8)' % v) + + self._v = v + + def __add__(self, o): + if isinstance(o, int): + return self + self.__class__(o) + + return self.__class__(self._v ^ o._v) + + def __radd__(self, o): + return self.__add__(o) + + def __rmul__(self, o): + return self.__mul__(o) + + def __sub__(self, o): + return self.__class__(self._v ^ o._v) + + def __mul__(self, o): + + if isinstance(o, int): + o = self.__class__(o) + + m = o._v + + # multiply + r = self._primativemul(self._v, m) + + # reduce + r ^= self._reduce[r >> 12] << 4 + r ^= self._reduce[(r >> 8) & 0xf ] + + r &= 0xff + + return self.__class__(r) + + def __eq__(self, o): + if isinstance(o, int): + return self._v == o + + return self._v == o._v + + def __repr__(self): + return '%s(%d)' % (self.__class__.__name__, self._v) + +class TestShamirSS(unittest.TestCase): + def test_gf28(self): + for i in range(10): + a = GF2p8(random.randint(0, 255)) + b = GF2p8(random.randint(0, 255)) + c = GF2p8(random.randint(0, 255)) + + self.assertEqual(a * 0, 0) + + # Identity + self.assertEqual(a + 0, a) + self.assertEqual(a * 1, a) + self.assertEqual(0 + a, a) + self.assertEqual(1 * a, a) + + # Associativity + self.assertEqual((a + b) + c, a + (b + c)) + self.assertEqual((a * b) * c, a * (b * c)) + + # Communitative + self.assertEqual(a + b, b + a) + self.assertEqual(a * b, b * a) + + # Distributive + self.assertEqual(a * (b + c), a * b + a * c) + self.assertEqual((b + c) * a, b * a + c * a) + + # Basic mul + self.assertEqual(GF2p8(0x80) * 2, 0x87) + self.assertEqual(GF2p8(0x80) * 6, (0x80 * 6) ^ (0x187 << 1)) + self.assertEqual(GF2p8(0x80) * 8, (0x80 * 8) ^ (0x187 << 2) ^ (0x187 << 1) ^ 0x187) + + self.assertEqual(a + b - b, a)