| @@ -227,16 +227,39 @@ class GF2p8: | |||||
| if x == -1 and self._invcache: | if x == -1 and self._invcache: | ||||
| return self.__class__(self._invcache[self._v]) | return self.__class__(self._invcache[self._v]) | ||||
| if x < 0: | |||||
| x += 255 | |||||
| # we loop after 255, so no need to do extra work | |||||
| x %= 255 | |||||
| v = self.__class__(1) | |||||
| # Note: not constant time, also, not optimial algorithm | |||||
| # TODO - make faster via caching and squaring | |||||
| for i in range(x): | |||||
| v *= self | |||||
| # The art of computer programming vol 2. § 4.6.3 Algorithm A | |||||
| # https://archive.org/details/artofcomputerpro0000knut/page/400/mode/2up | |||||
| return v | |||||
| # A1 | |||||
| n = x | |||||
| y = self.__class__(1) | |||||
| z = self | |||||
| while n: | |||||
| # A2 | |||||
| n, isodd = divmod(n, 2) | |||||
| if not isodd: | |||||
| # A5 | |||||
| z *= z | |||||
| continue | |||||
| # A3 | |||||
| y *= z | |||||
| # A4 | |||||
| if not n: | |||||
| break | |||||
| # A5 | |||||
| z *= z | |||||
| return y | |||||
| def powerseries(self, cnt): | def powerseries(self, cnt): | ||||
| '''Generate [ self ** 0, self ** 1, ..., self ** cnt ].''' | '''Generate [ self ** 0, self ** 1, ..., self ** cnt ].''' | ||||
| @@ -340,11 +363,20 @@ class TestShamirSS(unittest.TestCase): | |||||
| a = GF2p8(random.randint(0, 255)) | a = GF2p8(random.randint(0, 255)) | ||||
| v = GF2p8(1) | v = GF2p8(1) | ||||
| for i in range(10): | |||||
| for i in range(260): | |||||
| self.assertEqual(a ** i, v) | self.assertEqual(a ** i, v) | ||||
| v = v * a | v = v * a | ||||
| for i in range(10): | |||||
| neg = random.randint(-600, -1) | |||||
| p = neg | |||||
| while p < 0: | |||||
| p += 255 | |||||
| self.assertEqual(a ** neg, a ** p) | |||||
| for i in range(10): | for i in range(10): | ||||
| a = GF2p8(random.randint(0, 255)) | a = GF2p8(random.randint(0, 255)) | ||||